How I use Simple-scaffold to create a component boilerplate and how you can too.
In this article, we will look at how components can be created quicker and more robustly using Simple Scaffold, a command line application for creating multiple files, which makes it perfect for scaffolding components.
It is language agnostic and can just as easily be used for creating Blade or Twig components used in PHP.
What we are going to build is a method of scaffolding components quickly by creating templates for Simple Scaffold, that allow us to create new, named components that have all of their relationships and class names generated for us.
For this tutorial, we will be creating a component with the following structure:
/MyComponent/ (folder)
The aim of this article is to create a scaffolding script that can be run from the CLI of our project to create new components in seconds.
Here is the command we are going to setup:
npm run create-component MyComponent
This is what we want to generate:
export const MyComponent = (props: {example: string}) => {
return (
<div className="my-component">
<p>{props.example}</p>
</div>
)
}
.my-component {
/* Styles go here... */
}
import type { Meta, StoryObj } from '@storybook/react'
import { MyComponent } from './MyComponent'
type Story = StoryObj<typeof meta>
const meta = {
title: 'Components/MyComponent',
component: MyComponent,
parameters: {
layout: 'padded',
},
tags: ['autodocs'],
} satisfies Meta<typeof MyComponent>
export default meta;
export const Default: Story = {
args: {
example: 'This is example text',
},
}
npx
allows you to run any NPM package directly from the NPM registry without requiring a global installation.
It is possible to write most of the setup directly into the CLI, but Simple Scaffold provides a way of defining scaffolds within a JSON file, which is a much more robust way of generating scaffolding templates.
Let's create a simple-scaffold.json file in the root folder of our project:
touch simple-scaffold.json
I like to prefix my template folders with a period, but that is up to you, the folder name can be anything valid for your operating system.
mkdir .component-template
Finally, let's create our files, ready to start writing our templates. You will notice that each file contains a special string used by Simple Scaffold. It is written as {{name}}
. This is used as a variable by Simple Scaffold and is set when we run our create-component command later on.
touch .component-template/{{name}}.tsx .component-template/{{name}}.stories.tsx .component-template/{{name}}.module.css
With our files created, we can begin by adding our templates to simple-scaffold.json.
{
"component": {
"templates": [
".component-template/{{name}}.tsx",
".component-template/{{name}}.stories.ts",
".component-template/{{name}}.module.css"
],
"output": "src/components/{{name}}"
}
}
The component
key is user-defined and could be any other name, this allows for additional scaffolds to be defined in this file in the future under a different key. (As an example, I have an additional config for creating Payload CMS Blocks).
Within our primary component
key, we define another key, templates
which is required by Simple Scaffold. It should be an array of paths to each of our template files.
The output
value allows us to define where our components will be created. In this example, components will be added to src/components
.
npx simple-scaffold -c simple-scaffold.json -k component ExampleComponent
This command will create a new component named ExampleComponent. It will generate the folder and files within. Let's have a quick look at the command arguments to understand what we have written:
npx simple-scaffold
is what executes the command. -c
flag is shorthand for --config
and requires a filename to load our configuration from. -k
flag is short for --key
and this references our primary key component
from simple-scaffold.json and tells Simple Scaffold which configuration to use.Running the command above will create a new folder called ExampleComponent that contains the following files:
So now we have gone through how to create basic component files using Simple Scaffold, let's take a deeper look at the powerful templating and replacement engine capabilities of Simple Scaffold.
The {{ name }}
Template string works within template files and allows us to set up component exports, CSS rules and even generate Storybook stories for new components that are all preconfigured to use the correct names. Simple Scaffold has some great documentation on using {{ name }}
effectively and they provide some useful helpers for instances where you need to reference the component name in a different case, such as when you need to use PascalCase to name a component but your CSS naming convention uses hyphenation and lowercase class names.
import styles from './{{ name }}.css'
export const {{ name }} = (props: {example: string}) => {
return (
<div className="{{ hyphenCase name }}">
<p>{props.example}</p>
</div>
)
}
In this example, we set up a very basic component. Any instances of {{ name }} are replaced with the Component Name specified when running our scaffolding command. Note that the className is defined as {{ hyphenCase name }}
. Assuming that our component is named ExampleComponent, then {{ hyphenCase name }}
will return example-component
This template will generate the following output:
import styles from './ExampleComponent.css'
export const ExampleComponent = (props: {example: string}) => {
return (
<div className="example-component">
<p>{props.example}</p>
</div>
)
}
.{{ pascalCase name }} {
/* Styles go here... */
}
As above, any instances of {{ name }}
is replaced with the Component name specified when running our scaffolding command. As we defined our React component className to use pascalCase we will do the same for the CSS rule by once again using {{ pascalCase name }}
This template will generate the following output:
.example-component {
/* Styles go here... */
}
This is an opinionated StorybookJS story scaffold, based on my own setup which highlights how {{ name }} can be interspersed in a larger and more complex file. Not how it even works defining imports, despite the additional curly braces.
import type { Meta, StoryObj } from '@storybook/react'
import { {{ name }} } from './{{ name }}'
type Story = StoryObj<typeof meta>
const meta = {
title: 'Components/{{ name }}',
component: {{ name }},
parameters: {
layout: 'padded',
},
tags: ['autodocs'],
} satisfies Meta<typeof {{ name }}>
export default meta;
export const Default: Story = {
args: {
example: 'This is example text',
},
}
This template will generate the following output:
import type { Meta, StoryObj } from '@storybook/react'
import { ExampleComponent } from './ExampleComponent'
type Story = StoryObj<typeof meta>
const meta = {
title: 'Components/ExampleComponent',
component: ExampleComponent,
parameters: {
layout: 'padded',
},
tags: ['autodocs'],
} satisfies Meta<typeof ExampleComponent>
export default meta;
export const Default: Story = {
args: {
example: 'This is example text',
},
}
Following this guide should give you a good foundational understanding of what simple Scaffold is and how it can be used to scaffold components quickly and introduce a set of standards for how components should be created within your project. Simple Scaffold is very flexible and language agnostic so it can be used for all kinds of project setups in various languages.
If you have any thoughts or feedback on the article, you can contact me on Bluesky.