If you haven't already installed Cyto, make sure you do so before proceeding. Instructions can be found here
Cyto is built around one concept: the generation of boilerplate from templates. Templates are like blueprints, they tell Cyto what boilerplate to generate, what arguments to prompt the user for, and what special options to set. Generation is just the process of taking a template and creating the boilerplate it specifies. At a high level, template generation can be broken down into this flow of events:
- Cyto loads and validates the template
- Cyto prompts the user for the arguments specified by the template
- Cyto processes each of the template's declared dependencies, creating the boilerplate to write to the filesystem. How each dependency is handled depends on what the dependency's type is.
- Cyto outputs the created boilerplate. Tada!
This document will walk you through what the generation process looks like in practice and how Cyto templates are structured.
Before we dive into the details of how templates are structured, let's see what Cyto looks like in action:
Cyto templates are distributed as npm packages that follow the structure cyto-template-<templateId>. The naming convention for template ids is <group>-<name>. Cyto is meant to be installed on a per-project basis, so make sure that you install everything locally. As an example, we're going to install the cyto-helloworld template.
> npm i --save-dev cyto-template-cyto-helloworldOnce a template has been installed, we can generate it. The command for doing so is cyto gen <templateId> <id>:
> cyto gen cyto-helloworld test
Generating cyto-helloworld with id test
? thingToGreet: world
> ls
test.txtNice! You just generated your first Cyto template. The generated test.txt file should look like this:
> cat test.txt
Hello world!
This file was generated by Connor Taylor with an id of test using Cyto.Projects can end up using a lot of templates and having to install them all one by one (or type out each name) can be a bit unwieldy. Fortunately, you can group templates together into presets. Presets, like templates, are distributed as npm packages and have a naming convention of cyto-preset-<name>. Let's go ahead and install the cyto-preset-tutorials package to get a set of templates that are useful in learning how to use Cyto:
> npm i --save-dev cyto-preset-tutorialsNow that we've seen what the generation process looks like, let's explore how templates are structured. As mentioned before, templates are npm packages, so each template must have a package.json. In addition, they also contain any number of dependency files which have the boilerplate code to generate and a cyto.config.js file that holds all information about a template. Let's look at the files that are included in the cyto-helloWorld example template by running cyto open cyto-helloWorld:
node_modules/cyto-template-cyto-helloWorld/cyto.config.js
module.exports = {
templateId: "cyto-helloWorld",
dependencies: [
'{{id}}.txt',
],
args: [
{
id: 'thingToGreet',
default: 'world',
},
],
options: {
createDirectory: false,
}
};node_modules/cyto-template-cyto-helloWorld/{{id}}.txt
Hello {{thingToGreet}}!
This file was generated by {{author}} with an id of {{id}} using Cyto.
Even at it's simplest, there's a decent amount of information to process here, so let's break down each part.
The cyto.config.js file is the key piece of any template. It holds all the information Cyto needs to take a template and create its specified boilerplate. A cyto.config.js must be written in Javascript, but you'll only need to understand basic Javascript syntax to get started. The actual config for the template is the object exported by the cyto.config.js file. That object must contain, at minimum, four keys:
templateId: A unique identifier for each Cyto template.dependencies: An array that represents everything a template needs to be generated. Dependencies can be strings, objects, or functions (more on this later). In this template, we have one string dependency:{{id}}.txt. This means Cyto will look for a file called{{id}}.txtinside of thecyto-template-cyto-helloWorldpackage and output it when the template is generated.args: An array of objects that represents all of the values that Cyto needs to get from a user in order to properly generate the template. Arguments can have a few different types (more on this later as well), but the default type isstring. Thecyto-helloWorldtemplate has only 1 argument:thingToGreet, which has a default value ofworld.options: An object that holds a collection of values to set while running Cyto. Here, we set thecreateDirectoryflag to false, which tells Cyto not to create a new directory to hold all of the template's generated content (note: this is the default, it's just included for illustrative purposes)
Dependency files are any files included in a template's directory other than the cyto.config.js or package.json files. They contain boilerplate to generate for the template they are part of and are represented as strings in the dependencies array of a cyto.config.js file. In the cyto-helloWorld template, there is only one dependency file: {{id}}.txt file. Dependency files are rendered with a slightly modified version of the Mustache templating engine before being written to the filesystem. String dependencies in the cyto.config.js file are also passed through the Mustache renderer, so if the id argument is set to hello for this template, the name of the rendered {{id}}.txt file will be hello.txt. The only requirement for a dependency file is that it must be a valid Mustache template. If you're unfamiliar with Mustache, stop here and take a few minutes to familiarize yourself with the syntax. To clarify, rendering refers to passing text through the Mustache renderer while generation refers to the entire process of loading the Cyto template, prompting for its arguments, handling its dependencies, and writing the boilerplate to the filesystem.
And that's it! You should now have a basic understanding of how Cyto generates boilerplate and how templates are structured. However, the cyto-helloWorld template is fairly trivial example. Cyto really starts to shine when you make use of its more advanced features, which will be explained in the rest of the documentation.