Mason is an open source tool that generates code from custom templates called bricks. It can be helpful for developers who find themselves writing the same code over and over again, or those looking for a way to customize reusable templates.
Mason can increase the efficiency of development teams by enabling greater day-to-day automation. For example, if there is a widget or method that your team will be using throughout an entire project, you can simply write that piece of code once as a brick template. You can then use mason at any time to generate that piece of code from the template with dynamic variables. Brick templates can be maintained locally as part of a specific project or remotely via a GitHub repository.
As an individual developer, mason can be extremely helpful for creating and generating your own templates to start new projects. In fact, that’s exactly what we did with Very Good CLI, which uses mason under the hood to generate Very Good Core, our VGV opinionated Flutter starter app template. Another example is groovin_cli, an app generator created by GroovinChip using mason and inspired by Very Good CLI.
Mason is written in Dart but can be used to generate code in any programming language. It can also generate code from templates of any size — ranging from a few lines to a complete application consisting of hundreds of files and directories.
How it Works
Mason uses the mustache templating syntax to enable developers to create and maintain complex templates called bricks without having to write any generator code. Internally, mason maintains references to all installed brick templates and surfaces them to the developer via the mason make command. Brick templates consist of a brick.yaml file and a __brick__ directory which contains the template code.
When you want to generate code from a brick, mason gathers the input variables needed for the brick, either via prompts or as command line arguments, and injects them into the brick before writing the newly generated code to disk. Since mason is a CLI tool, you can run it straight from your terminal.
Getting Started
Mason can be installed either via pub.dev or homebrew.
At this point, mason should be available as a command. You can verify by running mason in your terminal.
Hello World Example
The first example we’ll take a look at is the hello world example which comes out of the box when you initialize mason.
Initializing Mason
Start by running mason init in your directory of choice. It should generate a mason.yaml along with a bricks directory.
The mason.yaml is where bricks can be registered similar to the pubspec.yaml. Bricks can be referenced either via path or git URL as seen below.
The bricks directory contains the brick templates. In this case, there is only a single brick called, hello. The brick.yaml contains important metadata about the template such as the name, description, and required variables.
Each brick also has a __brick__ directory which contains the template itself. Any files or directories within __brick__ will be part of the generated code when the brick is run.
If we take a quick look at the HELLO.md template file, we can see that we're able to access the name variable via {{name}}.
Now that we've taken a closer look at the parts of a brick template, let's install one.
Installing Brick Templates
We can install all bricks declared in the mason.yaml via the mason get command.
This will generate a .mason which contains relevant metadata needed to determine where the templates are installed. We recommend adding the .mason directory to your .gitignore.
Now we're ready to generate some code!
Generating Code
Once the bricks have been installed, we can run mason make hello to use the hello template.
HELLO.md will be generated in the current directory. The contents of the file should look something like:
Mason will prompt you for any variables that haven't been provided via command line arguments:
HELLO.md should now have been overwritten to include the updated name: Dash.
Now let's take a look at how to create our own brick for a custom widget.
Custom Widget Example
We can use the mason new command to create a new brick.
Note that mason automatically declared the new widget brick in the mason.yaml.
Here is our new widget brick's brick.yaml file:
Let's add a variable called routable which will determine whether or not the new widget should expose a route function.
Now the brick.yaml is complete. Let's start writing the template.
We can delete the default hello.md file within the __brick__ directory and create a new file called:
{{#snakeCase}}{{name}}{{/snakeCase}}.dart
The snakeCase lambda is provided by mason. Currently mason provides many lambdas out of the box such as:
- camelCase
- constantCase
- dotCase
- headerCase
- lowerCase
- pascalCase
- paramCase
- pathCase
- sentenceCase
- snakeCase
- titleCase
- upperCase
This will tell mason to create a filename, <name>.dart, and ensure the filename is snake case. Next, let's modify the content of our widget template file to include the widget code.
Here we're defining a StatelessWidget called name and using the pascalCase lambda to ensure it is a valid class name. We're also using mustache sections to define a static route function only if the variable routable is true.
That's it, now anytime we want to generate a new widget, we can use mason make widget.
Then we can take a look at the generated code in dash_container.dart:
If we want a new widget that is not routable, we can set routable to false:
And if we take a look at the newly generated flutter_box.dart, we should see there is no route method defined:
What's Next
We're actively working on several new features including support for global templates and template extensions. You can head over to the mason repo to check on the progress, provide feedback, and explore other examples.
Happy templating!