Hey there! We're excited that you're interested in contributing to Create Next Stack. This document should help you get set up locally and guide you through the process of contributing.
- Getting Started
- Repository Overview
- Creating a pull request
- Adding support for a new technology
- Writing a plugin
Before you start contributing, you'll need to get the project set up locally. Follow the steps below to get started.
- Make sure you have the latest Node.js and Git installed.
- Install pnpm using
npm i -g pnpm. - Fork the repository on GitHub.
- Clone your forked repository locally.
- Install dependencies using
pnpm install. - Build the project using
pnpm run build.
This repository is a monorepo managed using pnpm. This means that there are multiple packages in the repository, each with their own package.json file. The package.json file in the root of the repository is used to manage the packages in the repository.
You can see where the monorepo looks for packages in the pnpm-workspace.yaml file:
packages:
- "packages/**"
- "apps/**"Each package's package.json file contains scripts useful during development. These scripts can be run using pnpm <script>, but we are also use Turbo repo to speed up development. This means there is an array of scripts you can run using turbo <script> instead of pnpm <script>. build, lint, and test are examples of such scripts. You can see the configuration in the turbo.json file.
Note that running scripts inside a specific package's directory will only run the script for that package. This is true for both turbo and pnpm. For example, running turbo build inside the packages/create-next-stack directory will build the create-next-stack package only.
The table below provides names and descriptions of the npm scripts available in the create-next-stack package.
| Script | Description |
|---|---|
build |
Builds the project. |
build:watch |
Builds the project on every code change. |
lint |
Lints the project. |
test |
Alias for unit script. |
unit |
Runs unit tests. |
unit:watch |
Runs unit tests on every code change. |
unit:ci |
CI-specific unit test script. |
get-e2e-test-files-array |
Gets a list of all e2e test files, for GitHub Actions to be able to run them in parallel. |
e2e |
Runs all end-to-end tests in series. |
e2e:single |
Runs a single e2e test. Usage: pnpm e2e:single <file path filter>. |
e2e:single:ci |
CI-specific single e2e test script. |
e2e:manual |
Runs create-next-stack in a test directory and runs simple tests on the result.Specify your own CLI flags, eg.: pnpm run e2e:manual --package-manager=pnpm --styling=emotionNote that the app_name argument is set automatically. |
e2e:cna |
Runs npx create-next-app@latest in a test directory. Specify your own CLI flags. |
e2e:cns |
Runs npx create-next-stack@latest in a test directory and runs simple tests on the result. Specify your own CLI flags. |
e2e:raw |
Alias to the create-next-stack binary at ./bin/dev. Specify your own CLI flags. |
clean |
Cleans up the lib and create-next-stack-tests directories. |
clean-tests-dir |
Cleans up the create-next-stack-tests directory. |
update-readme |
Updates the auto-generated sections of the readme. Automatically run on commit. |
Make sure you are set up locally by following the Getting Started section above.
- Create a new branch from
developwith a descriptive name. - Make your changes.
- Run tests using
pnpm testto ensure they all pass. - Submit a Pull Request.
Make sure you are set up locally by following the Getting Started section above.
-
Create a new branch from
developwith a descriptive name.git checkout -b feature/support-my-favorite-technology
-
Make sure you check out the scripts section above. Most notably:
build:watch- Make sure to havebuild:watchrunning if you are running tests, as tests are run on the built files.unit:watch- Some of these tests were specifically made to ease the plugin authoring process, so don't forget this one.e2e- Runs e2e tests. Note that this will run all e2e tests, which can take quite a while.e2e:manual- This is performing a manual run of the CLI. Pass flags to the CLI that you want to test.
- For example,
pnpm run test:manual --package-manager=pnpm --styling=emotion.
clean- Removes all generated files, including build files and thecreate-next-stack-testsdirectory created by the e2e tests.
-
Add a new .ts file for your plugin in the plugins directory at
packages/create-next-stack/src/main/plugins- See the Writing a plugin section below to learn how to write a Create Next Stack plugin.
-
Add new flags to the
create-next-stackcommand increate-next-stack.ts. -
Add the plugin to the
pluginsarray insetup.ts. -
Add potential plugin steps to the
stepsarray insteps.ts. Steps are run top-to-bottom. -
Consider expanding some of the e2e tests to include the new technology. See the
testsdirectory for current e2e tests. -
Go and add the technology to the technology selection form of the website.
- See the TechnologiesForm component.
- This component is currently pretty hideous, and updating it will be automated in the future. See issue #188.
-
Run tests using
yarn testto ensure they all pass. -
Submit a Pull Request on GitHub.
Plugins aren't too scary. A Create Next Stack plugin consists of a simple TypeScript file that exports an object of type Plugin.
See the Framer Motion plugin for example. This plugin adds the framer-motion npm dependency to the generated Next.js project, as well as adding some documentation about the technology.
export const framerMotionPlugin: Plugin = {
id: "framer-motion",
name: "Framer Motion",
description: "Adds support for Framer Motion",
active: ({ flags }) => Boolean(flags["framer-motion"]),
dependencies: [{ name: "framer-motion", version: "^9.0.0" }],
technologies: [
{
id: "framerMotion",
name: "Framer Motion",
description:
"Framer Motion is a popular React animation library. It allows users to create both simple animations and complex gesture-based interactions. The library implements a declarative API, otherwise known as spring animations, which lets the developer define the animation's end state, letting the library handle the rest.",
links: [
{ title: "Website", url: "https://www.framer.com/motion/" },
{ title: "Docs", url: "https://www.framer.com/docs/" },
{ title: "GitHub", url: "https://github.com/framer/motion" },
],
},
],
} as constBelow is a small breakdown of the properties of the above plugin object:
- The
idproperty is a unique identifier for the plugin. - The
nameproperty is the name of the plugin. - The
descriptionproperty is a short description of the plugin. - The
activeproperty is a function that returns a boolean indicating whether the plugin should be active. This function is passed the flags and arguments passed by users to thecreate-next-stackcommand. - The
dependenciesproperty is an array of npm dependencies that should be added to the generated Next.js project. - The
technologiesproperty is an array of objects containing documentation about the technologies supported by the plugin.
Some of these properties are optional, and some are required. Some properties are used by the CLI, some are used by the website, and some both. It's not too important to know exactly where these properties are used. As long as we specify all relevant properties, the CLI and website is going to find out how to use it.
For a complete list of properties of the Plugin type, their explanations, and usage, see the Plugin type definition. You should find all the documentation you need there. If not, please open an issue.
For more examples, please take a look at the existing plugins.