Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/01-app/01-getting-started/01-installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,30 @@ Would you like to include AGENTS.md to guide coding agents to write up-to-date N

After the prompts, [`create-next-app`](/docs/app/api-reference/cli/create-next-app) will create a folder with your project name and install the required dependencies.

## Start from a starter

Different types of apps need different caching architectures. A blog caches its content and revalidates when it changes, while a dashboard reads per-user data on each request. Starters are minimal, first-party skeletons that set up the right architecture for your app type, so you and your coding agent build on a working pattern instead of starting from scratch.

Pick the one that matches what you are building:

| Starter | Best for | How it renders |
| ------------------------------------------------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| [`blog`](https://github.com/vercel/next.js/tree/canary/starters/blog) | Blogs, docs, marketing sites, portfolios | Reads are cached and tagged. Pages prerender to static shells and revalidate by tag. |
| [`store`](https://github.com/vercel/next.js/tree/canary/starters/store) | Ecommerce, product catalogs, booking | A cached, shared catalog with a per-visitor cart that streams into the static shell. |
| [`dashboard`](https://github.com/vercel/next.js/tree/canary/starters/dashboard) | SaaS apps, admin panels, internal tools | Authenticated per-user data behind a data access layer, streamed in parallel. Shared data stays cached. |
| [`chat`](https://github.com/vercel/next.js/tree/canary/starters/chat) | AI chatbots, assistants, real-time tools | A prerendered shell with a streamed conversation sidebar. Replies stream per request from a Route Handler. |
| [`feed`](https://github.com/vercel/next.js/tree/canary/starters/feed) | Social feeds, timelines, activity streams | The first page prerenders in the static shell. More pages stream in on demand, and new posts show right away. |

Create one with the `--example` flag, swapping `blog` for `store`, `dashboard`, `chat`, or `feed`:

```bash filename="Terminal"
npx create-next-app@latest --example https://github.com/vercel/next.js/tree/canary/starters/blog my-blog
```

The starters share a baseline: [Cache Components](/docs/app/getting-started/caching) and [`partialPrefetching`](/docs/app/api-reference/config/next-config-js/partialPrefetching) enabled, feature folders under `features/` that own cached queries (`"use cache"`, `cacheLife`, `cacheTag`) and Server Actions, seeded local data that runs with no setup, `<Suspense>` boundaries with dimension-matched skeletons, and an `AGENTS.md` describing the architecture for [AI coding agents](/docs/app/guides/ai-agents). This baseline matches what `create-next-app` generates.

> **Good to know:** Starters are minimal foundations maintained in the [Next.js repository](https://github.com/vercel/next.js/tree/canary/starters). For integrations with a specific library or service, see the [examples](https://github.com/vercel/next.js/tree/canary/examples), and for complete deployable applications, see the [templates](https://vercel.com/templates/next.js).

## Manual installation

To manually create a new Next.js app, install the required packages:
Expand Down
2 changes: 2 additions & 0 deletions docs/01-app/02-guides/authentication.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ description: Learn how to implement authentication in your Next.js application.

Understanding authentication is crucial for protecting your application's data. This page will guide you through what React and Next.js features to use to implement auth.

> **Good to know:** The [`dashboard` starter](https://github.com/vercel/next.js/tree/canary/starters/dashboard) is a runnable example of a data access layer with per-user reads.
Before starting, it helps to break down the process into three concepts:

1. **[Authentication](#authentication)**: Verifies if the user is who they say they are. It requires the user to prove their identity with something they have, such as a username and password.
Expand Down
2 changes: 2 additions & 0 deletions docs/01-app/02-guides/backend-for-frontend.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Next.js supports the "Backend for Frontend" pattern. This lets you create public

If you are starting a new project, using `create-next-app` with the `--api` flag automatically includes an example `route.ts` in your new project's `app/` folder, demonstrating how to create an API endpoint.

> **Good to know:** The [`chat` starter](https://github.com/vercel/next.js/tree/canary/starters/chat) is a runnable example of a streaming Route Handler.
```bash package="pnpm"
pnpm create next-app --api
```
Expand Down
2 changes: 2 additions & 0 deletions docs/01-app/02-guides/instant-navigation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ related:

This guide walks through understanding instant navigations, writing a route that navigates instantly, visualizing what's in the initial UI, and locking the behavior in with end-to-end tests.

> **Good to know:** The [`store` starter](https://github.com/vercel/next.js/tree/canary/starters/store) is a runnable example of a static shell with a streamed, per-request hole.

## What "instant" means

A navigation is **instant** when the browser can start rendering the new page the moment the user clicks, with static, cached, and fallback content showing up right away, while the server streams the remaining content into its fallbacks.
Expand Down
2 changes: 2 additions & 0 deletions docs/01-app/02-guides/interactive-apps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ When a user interaction requires server-side work, the result is not available i

This guide adds responsive feedback to a task management app called _Taskboard_. Each step handles a different kind of pending work, from streaming slow reads to confirming mutations before the server responds.

> **Good to know:** The [`feed` starter](https://github.com/vercel/next.js/tree/canary/starters/feed) is a runnable example of optimistic UI and pagination.

> **Good to know:** The patterns in this guide also improve [Core Web Vitals](https://web.dev/articles/vitals). Streaming with [`<Suspense>`](https://react.dev/reference/react/Suspense) lowers [FCP](https://web.dev/articles/fcp) and [LCP](https://web.dev/articles/lcp) by letting the shell paint while slow reads finish. Optimistic UI and transitions lower [INP](https://web.dev/articles/inp) by keeping the click frame fast. Prefetching the next route makes FCP, LCP, and INP on the destination page near-instant. These patterns help, but they don't replace the usual INP work: shipping less client JavaScript and avoiding blocking roundtrips during interactions.

## Example
Expand Down
2 changes: 2 additions & 0 deletions docs/01-app/02-guides/public-static-pages.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Public pages show the same content to every user. Common examples include landin

Since data is shared, these kind of pages can be [prerendered](/docs/app/glossary#prerendering) ahead of time and reused. This leads to faster page loads and lower server costs.

> **Good to know:** The [`blog` starter](https://github.com/vercel/next.js/tree/canary/starters/blog) is a runnable example of this pattern.
This guide will show you how to build public pages that share data across users.

## Example
Expand Down
83 changes: 53 additions & 30 deletions docs/01-app/03-api-reference/06-cli/create-next-app.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,36 +29,37 @@ bun create next-app [project-name] [options]

The following options are available:

| Options | Description |
| --------------------------------------- | --------------------------------------------------------------------- |
| `-h` or `--help` | Show all available options |
| `-v` or `--version` | Output the version number |
| `--no-*` | Negate default options. E.g. `--no-ts` |
| `--ts` or `--typescript` | Initialize as a TypeScript project (default) |
| `--js` or `--javascript` | Initialize as a JavaScript project |
| `--tailwind` | Initialize with Tailwind CSS config (default) |
| `--react-compiler` | Initialize with React Compiler enabled |
| `--eslint` | Initialize with ESLint config |
| `--biome` | Initialize with Biome config |
| `--no-linter` | Skip linter configuration |
| `--app` | Initialize as an App Router project |
| `--api` | Initialize a project with only route handlers |
| `--src-dir` | Initialize inside a `src/` directory |
| `--turbopack` | Force enable Turbopack in generated package.json (enabled by default) |
| `--webpack` | Force enable Webpack in generated package.json |
| `--import-alias <alias-to-configure>` | Specify import alias to use (default "@/\*") |
| `--empty` | Initialize an empty project |
| `--use-npm` | Explicitly tell the CLI to bootstrap the application using npm |
| `--use-pnpm` | Explicitly tell the CLI to bootstrap the application using pnpm |
| `--use-yarn` | Explicitly tell the CLI to bootstrap the application using Yarn |
| `--use-bun` | Explicitly tell the CLI to bootstrap the application using Bun |
| `-e` or `--example [name] [github-url]` | An example to bootstrap the app with |
| `--example-path <path-to-example>` | Specify the path to the example separately |
| `--reset-preferences` | Explicitly tell the CLI to reset any stored preferences |
| `--skip-install` | Explicitly tell the CLI to skip installing packages |
| `--disable-git` | Explicitly tell the CLI to disable git initialization |
| `--agents-md` | Include `AGENTS.md` and `CLAUDE.md` to guide coding agents (default) |
| `--yes` | Use previous preferences or defaults for all options |
| Options | Description |
| --------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `-h` or `--help` | Show all available options |
| `-v` or `--version` | Output the version number |
| `--no-*` | Negate default options. E.g. `--no-ts` |
| `--ts` or `--typescript` | Initialize as a TypeScript project (default) |
| `--js` or `--javascript` | Initialize as a JavaScript project |
| `--tailwind` | Initialize with Tailwind CSS config (default) |
| `--react-compiler` | Initialize with React Compiler enabled |
| `--eslint` | Initialize with ESLint config |
| `--biome` | Initialize with Biome config |
| `--no-linter` | Skip linter configuration |
| `--app` | Initialize as an App Router project |
| `--api` | Initialize a project with only route handlers |
| `--src-dir` | Initialize inside a `src/` directory |
| `--turbopack` | Force enable Turbopack in generated package.json (enabled by default) |
| `--webpack` | Force enable Webpack in generated package.json |
| `--import-alias <alias-to-configure>` | Specify import alias to use (default "@/\*") |
| `--empty` | Initialize an empty project |
| `--use-npm` | Explicitly tell the CLI to bootstrap the application using npm |
| `--use-pnpm` | Explicitly tell the CLI to bootstrap the application using pnpm |
| `--use-yarn` | Explicitly tell the CLI to bootstrap the application using Yarn |
| `--use-bun` | Explicitly tell the CLI to bootstrap the application using Bun |
| `-e` or `--example [name] [github-url]` | An example to bootstrap the app with |
| `--example-path <path-to-example>` | Specify the path to the example separately |
| `--starter <starter-name>` | A [starter](/docs/app/getting-started/installation#start-from-a-starter) to bootstrap the app with |
| `--reset-preferences` | Explicitly tell the CLI to reset any stored preferences |
| `--skip-install` | Explicitly tell the CLI to skip installing packages |
| `--disable-git` | Explicitly tell the CLI to disable git initialization |
| `--agents-md` | Include `AGENTS.md` and `CLAUDE.md` to guide coding agents (default) |
| `--yes` | Use previous preferences or defaults for all options |

## Examples

Expand Down Expand Up @@ -140,6 +141,28 @@ bun create next-app --example [example-name] [your-project-name]

You can view a list of all available examples along with setup instructions in the [Next.js repository](https://github.com/vercel/next.js/tree/canary/examples).

### With a starter

To create a new app from an official [starter](/docs/app/getting-started/installation#start-from-a-starter), a minimal foundation for a specific type of app, use the `--starter` flag. For example:

```bash package="pnpm"
pnpm create next-app --starter [starter-name] [your-project-name]
```

```bash package="npm"
npx create-next-app@latest --starter [starter-name] [your-project-name]
```

```bash package="yarn"
yarn create next-app --starter [starter-name] [your-project-name]
```

```bash package="bun"
bun create next-app --starter [starter-name] [your-project-name]
```

See [choosing a starter](/docs/app/getting-started/installation#start-from-a-starter) for the available starters and what's inside them.

### With any public GitHub example

To create a new app using any public GitHub example, use the `--example` option with the GitHub repo's URL. For example:
Expand Down
1 change: 1 addition & 0 deletions eslint.cli.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default defineConfig([
// resolve inside the sandbox (e.g. @vercel/agent-eval/eval).
'evals/evals/**/*',
'examples/**/*',
'starters/**/*',
'test/**/*',
'**/*.d.ts',
'turbopack/**/*',
Expand Down
3 changes: 2 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ export default defineConfig([
// resolve inside the sandbox (e.g. @vercel/agent-eval/eval).
'evals/evals/**/*',
'examples/**/*',
'starters/**/*',
'test/**/*',
'**/*.d.ts',
'turbopack/**/*',
Expand Down Expand Up @@ -449,7 +450,7 @@ export default defineConfig([
},
},
{
files: ['examples/**/*'],
files: ['examples/**/*', 'starters/**/*'],
linterOptions: {
reportUnusedDisableDirectives: 'off',
},
Expand Down
38 changes: 34 additions & 4 deletions packages/create-next-app/create-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export async function createApp({
packageManager,
example,
examplePath,
starter,
typescript,
tailwind,
eslint,
Expand All @@ -49,6 +50,7 @@ export async function createApp({
packageManager: PackageManager
example?: string
examplePath?: string
starter?: string
typescript: boolean
tailwind: boolean
eslint: boolean
Expand Down Expand Up @@ -129,6 +131,21 @@ export async function createApp({
process.exit(1)
}
}
} else if (starter) {
const found = await existsInRepo(starter, 'starters')

if (!found) {
console.error(
`Could not locate a starter named ${red(
`"${starter}"`
)}. It could be due to the following:\n`,
`1. Your spelling of starter ${red(
`"${starter}"`
)} might be incorrect.\n`,
`2. You might not be connected to the internet or you are behind a proxy.`
)
process.exit(1)
}
}

const root = resolve(appPath)
Expand Down Expand Up @@ -162,12 +179,12 @@ export async function createApp({
const packageJsonPath = join(root, 'package.json')
let hasPackageJson = false

if (example) {
if (example || starter) {
/**
* If an example repository is provided, clone it.
* If an example repository or a starter is provided, clone it.
*/
try {
if (repoInfo) {
if (example && repoInfo) {
const repoInfo2 = repoInfo
console.log(
`Downloading files from repo ${cyan(
Expand All @@ -178,7 +195,7 @@ export async function createApp({
await retry(() => downloadAndExtractRepo(root, repoInfo2), {
retries: 3,
})
} else {
} else if (example) {
console.log(
`Downloading files for example ${cyan(
example
Expand All @@ -188,6 +205,19 @@ export async function createApp({
await retry(() => downloadAndExtractExample(root, example), {
retries: 3,
})
} else if (starter) {
console.log(
`Downloading files for starter ${cyan(
starter
)}. This might take a moment.`
)
console.log()
await retry(
() => downloadAndExtractExample(root, starter, 'starters'),
{
retries: 3,
}
)
}
} catch (reason) {
function isErrorLike(err: unknown): err is { message: string } {
Expand Down
Loading
Loading