Create React App Template System: How to Build and Use Custom Templates

Create React App generates new projects by resolving the --template flag to an npm package, local path, or tarball, then copying files from the template's template/ directory and merging configurations from template.json into the generated project.

The Create React App template system allows developers to scaffold React projects with custom boilerplate, dependencies, and configurations without maintaining a fork of the toolchain. By creating reusable template packages, teams can standardize project setup across organizations while leveraging the official react-scripts build pipeline. This guide explains the template resolution architecture and provides a step-by-step method for building custom templates.

How the Create React App Template System Works

Template Resolution and CLI Parsing

When you execute npx create-react-app my-app --template <template>, the CLI resolves the template identifier in packages/create-react-app/createReactApp.js. The resolution logic (lines 144-152) accepts three formats:

  • npm package names (e.g., cra-template-typescript)
  • Local file paths using the file: protocol (e.g., file:../my-template)
  • Remote tarballs via URL (e.g., https://example.com/template.tgz)

The CLI also verifies version compatibility in createReactApp.js (lines 66-72), ensuring the installed react-scripts is version 3.3.0 or higher before attempting template initialization.

Template Initialization and File Copying

Once resolved, the initialization logic in packages/react-scripts/scripts/init.js orchestrates the project generation:

  1. Locates the template directory (lines 33-40) by searching for a template/ folder within the resolved package
  2. Copies all files from template/ to the new project root recursively
  3. Parses template.json to extract additional metadata under the package key
  4. Merges dependencies (lines 301-307), installing any dependencies or devDependencies specified in template.json via npm or yarn

Anatomy of a Template Package

A valid CRA template is an npm package containing a template/ directory and an optional template.json configuration file.

The template/ Directory

This folder mirrors the structure of a standard CRA project. When users run create-react-app, every file inside template/ is copied to the generated project root. A typical structure includes:


template/
├── public/
│   └── index.html
├── src/
│   ├── App.js
│   ├── App.css
│   └── index.js
└── README.md

The template.json Configuration

Located at the package root, this file defines additional project metadata under a package key. According to the default cra-template implementation in packages/cra-template/template.json, you can specify:

{
  "package": {
    "dependencies": {
      "@testing-library/jest-dom": "^6.6.3",
      "@testing-library/react": "^16.1.0",
      "web-vitals": "^2.1.0"
    },
    "eslintConfig": {
      "extends": ["react-app", "react-app/jest"]
    }
  }
}

Dependencies listed here are automatically installed after the template files are copied.

How to Create a Custom Template

1. Initialize the Package Structure

Create a new directory and initialize npm:

mkdir my-cra-template
cd my-cra-template
npm init -y

Update package.json to follow the cra-template-* naming convention (this allows users to reference your template by short name):

{
  "name": "cra-template-awesome",
  "version": "0.1.0",
  "main": "index.js",
  "files": [
    "template",
    "template.json"
  ]
}

2. Create the Template Directory

Add a template/ folder containing your boilerplate files:

mkdir -p template/src template/public
touch template/README.md

Populate these files with your desired starting structure. For example, template/src/App.js:

import React from 'react';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <h1>Welcome to Awesome Template</h1>
      </header>
    </div>
  );
}

export default App;

3. Configure template.json

If your template requires additional dependencies, create a template.json at the package root:

{
  "package": {
    "dependencies": {
      "axios": "^1.6.0",
      "styled-components": "^6.1.0"
    },
    "scripts": {
      "lint": "eslint src/"
    }
  }
}

4. Test Locally

Before publishing, verify your template works using the file: protocol:

npx create-react-app test-app --template file:./my-cra-template

Check that files are copied correctly and dependencies are installed.

5. Publish to npm

Once validated, publish your template:

npm publish

Users can now scaffold projects with your template:

npx create-react-app my-app --template awesome

Key Source Files in the CRA Codebase

Understanding the implementation helps debug template issues:

  • packages/create-react-app/createReactApp.js – Parses the --template flag, resolves package names vs. local paths vs. tarballs, and validates react-scripts version compatibility (lines 66-72 and 144-152).

  • packages/react-scripts/scripts/init.js – Executes template initialization: locates the template/ directory, copies files recursively, merges template.json configurations, and installs additional dependencies (lines 33-40 and 301-307).

  • packages/cra-template/ – Reference implementation of the default JavaScript template, demonstrating the required template/ structure and template.json schema.

  • packages/cra-template-typescript/ – TypeScript template implementation showing how to include type definitions and compiler configurations.

Summary

  • Create React App generates projects by copying files from a template package specified via the --template flag.
  • The CLI resolves templates as npm packages, local file: paths, or remote tarballs in createReactApp.js (lines 144-152).
  • Valid templates require a template/ directory containing boilerplate files and an optional template.json for dependency management.
  • The initialization script in init.js (lines 33-40, 301-307) handles file copying, JSON merging, and dependency installation.
  • Custom templates should follow the cra-template-* naming convention and can be published to npm or used locally via the file: protocol.

Frequently Asked Questions

What is the default template used by Create React App?

If you do not specify a --template flag, Create React App defaults to cra-template, which is the standard JavaScript template maintained in the official repository. This template includes a basic React setup with testing libraries and web vitals support, defined in its template.json configuration.

Can I use a local folder as a template without publishing to npm?

Yes. You can reference a local template using the file: protocol when running the create command. For example: npx create-react-app my-app --template file:../path/to/my-template. The CLI resolves this path in createReactApp.js and installs the template locally before copying files.

How do I add extra dependencies to my custom template?

Define additional dependencies inside a package key in your template.json file at the root of your template package. When react-scripts/scripts/init.js processes your template, it automatically merges these dependencies and devDependencies into the generated project's package.json and installs them via npm or yarn.

Why does my template require react-scripts 3.3.0 or higher?

Template support was introduced in react-scripts version 3.3.0. The CLI checks for this version in createReactApp.js (lines 66-72) before attempting to install and initialize a template. If you are using an older version of react-scripts, the --template flag will not function correctly.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →