first commit
Some checks failed
Test examples / Test Examples (20) (push) Has been cancelled
Test examples / Test Examples (22) (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Trigger Release / start (push) Has been cancelled
Stale issue handler / stale (push) Has been cancelled
Update Font Data / create-pull-request (push) Has been cancelled
build-and-deploy / deploy-target (push) Has been cancelled
build-and-deploy / build (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / build-wasm (nodejs) (push) Has been cancelled
build-and-deploy / build-wasm (web) (push) Has been cancelled
build-and-deploy / Deploy preview tarball (push) Has been cancelled
build-and-deploy / Potentially publish release (push) Has been cancelled
build-and-deploy / publish-turbopack-npm-packages (push) Has been cancelled
build-and-deploy / Deploy examples (push) Has been cancelled
build-and-deploy / thank you, build (push) Has been cancelled
build-and-deploy / Upload Turbopack Bytesize metrics to Datadog (push) Has been cancelled
Rspack Next.js development integration tests / Rspack integration tests (push) Has been cancelled
Rspack Next.js production integration tests / Rspack integration tests (push) Has been cancelled
Turbopack Next.js development integration tests / Next.js integration tests (push) Has been cancelled
Turbopack Next.js production integration tests / Next.js integration tests (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack development test manifest (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack production test manifest (push) Has been cancelled
Upload bundler test manifests to areweturboyet.com / Upload test results (push) Has been cancelled
Update React / create-pull-request (push) Has been cancelled
test-e2e-project-reset-cron / reset-test-project (push) Has been cancelled
Notify about the top 15 issues/PRs/feature requests (most reacted) in the last 90 days / run (push) Has been cancelled

This commit is contained in:
Arian Tron
2026-03-10 19:37:31 +03:30
commit 61f56f997c
27684 changed files with 2784175 additions and 0 deletions

View File

@@ -0,0 +1,127 @@
# Create Next App
The easiest way to get started with Next.js is by using `create-next-app`. This CLI tool enables you to quickly start building a new Next.js application, with everything set up for you. You can create a new app using the default Next.js template, or by using one of the [official Next.js examples](https://github.com/vercel/next.js/tree/canary/examples). To get started, use the following command:
### Interactive
You can create a new project interactively by running:
```bash
npx create-next-app@latest
# or
yarn create next-app
# or
pnpm create next-app
# or
bunx create-next-app
```
You will be asked for the name of your project, and then whether you want to
create a TypeScript project:
```bash
✔ Would you like to use TypeScript? … No / Yes
```
Select **Yes** to install the necessary types/dependencies and create a new TS project.
### Non-interactive
You can also pass command line arguments to set up a new project
non-interactively. See `create-next-app --help`:
```bash
Usage: create-next-app [project-directory] [options]
Options:
-V, --version output the version number
--ts, --typescript
Initialize as a TypeScript project. (default)
--js, --javascript
Initialize as a JavaScript project.
--tailwind
Initialize with Tailwind CSS config. (default)
--eslint
Initialize with ESLint config.
--app
Initialize as an App Router project.
--src-dir
Initialize inside a `src/` directory.
--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, --example [name]|[github-url]
An example to bootstrap the app with. You can use an example name
from the official Next.js repo or a GitHub URL. The URL can use
any branch and/or subdirectory
--example-path <path-to-example>
In a rare case, your GitHub URL might contain a branch name with
a slash (e.g. bug/fix-1) and the path to the example (e.g. foo/bar).
In this case, you must specify the path to the example separately:
--example-path foo/bar
--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 skip initializing a git repository.
--yes
Use previous preferences or defaults for all options that were not
explicitly specified, without prompting.
-h, --help display help for command
```
### Why use Create Next App?
`create-next-app` allows you to create a new Next.js app within seconds. It is officially maintained by the creators of Next.js, and includes a number of benefits:
- **Interactive Experience**: Running `npx create-next-app@latest` (with no arguments) launches an interactive experience that guides you through setting up a project.
- **Zero Dependencies**: Initializing a project is as quick as one second. Create Next App has zero dependencies.
- **Offline Support**: Create Next App will automatically detect if you're offline and bootstrap your project using your local package cache.
- **Support for Examples**: Create Next App can bootstrap your application using an example from the Next.js examples collection (e.g. `npx create-next-app --example route-handlers`).
- **Tested**: The package is part of the Next.js monorepo and tested using the same integration test suite as Next.js itself, ensuring it works as expected with every release.

View File

@@ -0,0 +1,300 @@
/* eslint-disable import/no-extraneous-dependencies */
import retry from 'async-retry'
import { copyFileSync, existsSync, mkdirSync } from 'node:fs'
import { basename, dirname, join, resolve } from 'node:path'
import { cyan, green, red } from 'picocolors'
import type { RepoInfo } from './helpers/examples'
import {
downloadAndExtractExample,
downloadAndExtractRepo,
existsInRepo,
getRepoInfo,
hasRepo,
} from './helpers/examples'
import type { PackageManager } from './helpers/get-pkg-manager'
import { tryGitInit } from './helpers/git'
import { install } from './helpers/install'
import { isFolderEmpty } from './helpers/is-folder-empty'
import { getOnline } from './helpers/is-online'
import { isWriteable } from './helpers/is-writeable'
import { generateAgentFiles } from './helpers/generate-agent-files'
import { runTypegen } from './helpers/typegen'
import type { Bundler, TemplateMode, TemplateType } from './templates'
import { getTemplateFile, installTemplate } from './templates'
export class DownloadError extends Error {}
export async function createApp({
appPath,
packageManager,
example,
examplePath,
typescript,
tailwind,
eslint,
biome,
app,
srcDir,
importAlias,
skipInstall,
empty,
api,
bundler,
disableGit,
reactCompiler,
agentsMd,
}: {
appPath: string
packageManager: PackageManager
example?: string
examplePath?: string
typescript: boolean
tailwind: boolean
eslint: boolean
biome: boolean
app: boolean
srcDir: boolean
importAlias: string
skipInstall: boolean
empty: boolean
api?: boolean
bundler: Bundler
disableGit?: boolean
reactCompiler: boolean
agentsMd: boolean
}): Promise<void> {
let repoInfo: RepoInfo | undefined
const mode: TemplateMode = typescript ? 'ts' : 'js'
const template: TemplateType = `${app ? 'app' : 'default'}${tailwind ? '-tw' : ''}${empty ? '-empty' : ''}`
if (example) {
let repoUrl: URL | undefined
try {
repoUrl = new URL(example)
} catch (error: unknown) {
const err = error as Error
// TypeError is thrown when the URL is invalid. Equivalent of doing `err.code !== "ERR_INVALID_URL"` in Node.js
if (!(err instanceof TypeError)) {
console.error(error)
process.exit(1)
}
}
if (repoUrl) {
if (repoUrl.origin !== 'https://github.com') {
console.error(
`Invalid URL: ${red(
`"${example}"`
)}. Only GitHub repositories are supported. Please use a GitHub URL and try again.`
)
process.exit(1)
}
repoInfo = await getRepoInfo(repoUrl, examplePath)
if (!repoInfo) {
console.error(
`Found invalid GitHub URL: ${red(
`"${example}"`
)}. Please fix the URL and try again.`
)
process.exit(1)
}
const found = await hasRepo(repoInfo)
if (!found) {
console.error(
`Could not locate the repository for ${red(
`"${example}"`
)}. Please check that the repository exists and try again.`
)
process.exit(1)
}
} else if (example !== '__internal-testing-retry') {
const found = await existsInRepo(example)
if (!found) {
console.error(
`Could not locate an example named ${red(
`"${example}"`
)}. It could be due to the following:\n`,
`1. Your spelling of example ${red(
`"${example}"`
)} 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)
if (!(await isWriteable(dirname(root)))) {
console.error(
'The application path is not writable, please check folder permissions and try again.'
)
console.error(
'It is likely you do not have write permissions for this folder.'
)
process.exit(1)
}
const appName = basename(root)
mkdirSync(root, { recursive: true })
if (!isFolderEmpty(root, appName)) {
process.exit(1)
}
const useYarn = packageManager === 'yarn'
const isOnline = !useYarn || (await getOnline())
const originalDirectory = process.cwd()
console.log(`Creating a new Next.js app in ${green(root)}.`)
console.log()
process.chdir(root)
const packageJsonPath = join(root, 'package.json')
let hasPackageJson = false
if (example) {
/**
* If an example repository is provided, clone it.
*/
try {
if (repoInfo) {
const repoInfo2 = repoInfo
console.log(
`Downloading files from repo ${cyan(
example
)}. This might take a moment.`
)
console.log()
await retry(() => downloadAndExtractRepo(root, repoInfo2), {
retries: 3,
})
} else {
console.log(
`Downloading files for example ${cyan(
example
)}. This might take a moment.`
)
console.log()
await retry(() => downloadAndExtractExample(root, example), {
retries: 3,
})
}
} catch (reason) {
function isErrorLike(err: unknown): err is { message: string } {
return (
typeof err === 'object' &&
err !== null &&
typeof (err as { message?: unknown }).message === 'string'
)
}
throw new DownloadError(
isErrorLike(reason) ? reason.message : reason + ''
)
}
// Copy `.gitignore` if the application did not provide one
const ignorePath = join(root, '.gitignore')
if (!existsSync(ignorePath)) {
copyFileSync(
getTemplateFile({ template, mode, file: 'gitignore' }),
ignorePath
)
}
// Copy `next-env.d.ts` to any example that is typescript
const tsconfigPath = join(root, 'tsconfig.json')
if (existsSync(tsconfigPath)) {
copyFileSync(
getTemplateFile({ template, mode: 'ts', file: 'next-env.d.ts' }),
join(root, 'next-env.d.ts')
)
}
hasPackageJson = existsSync(packageJsonPath)
if (!skipInstall && hasPackageJson) {
console.log('Installing packages. This might take a couple of minutes.')
console.log()
await install(packageManager, isOnline)
console.log()
try {
console.log()
await runTypegen(packageManager)
console.log()
} catch (err) {
// Best effort: do not fail app creation if typegen fails
console.error('Error running typegen:', err)
}
}
} else {
/**
* If an example repository is not provided for cloning, proceed
* by installing from a template.
*/
await installTemplate({
appName,
root,
template: api ? 'app-api' : template,
mode,
packageManager,
isOnline,
tailwind,
eslint,
biome,
srcDir,
importAlias,
skipInstall,
bundler,
reactCompiler,
})
}
if (agentsMd) {
generateAgentFiles(root)
}
if (disableGit) {
console.log('Skipping git initialization.')
console.log()
} else if (tryGitInit(root)) {
console.log('Initialized a git repository.')
console.log()
}
let cdpath: string
if (join(originalDirectory, appName) === appPath) {
cdpath = appName
} else {
cdpath = appPath
}
console.log(`${green('Success!')} Created ${appName} at ${appPath}`)
if (hasPackageJson) {
console.log('Inside that directory, you can run several commands:')
console.log()
console.log(cyan(` ${packageManager} ${useYarn ? '' : 'run '}dev`))
console.log(' Starts the development server.')
console.log()
console.log(cyan(` ${packageManager} ${useYarn ? '' : 'run '}build`))
console.log(' Builds the app for production.')
console.log()
console.log(cyan(` ${packageManager} start`))
console.log(' Runs the built app in production mode.')
console.log()
console.log('We suggest that you begin by typing:')
console.log()
console.log(cyan(' cd'), cdpath)
console.log(` ${cyan(`${packageManager} ${useYarn ? '' : 'run '}dev`)}`)
}
console.log()
}

View File

@@ -0,0 +1,50 @@
/* eslint-disable import/no-extraneous-dependencies */
import { resolve, dirname, basename, join } from 'node:path'
import { copyFile, mkdir } from 'node:fs/promises'
import { async as glob } from 'fast-glob'
interface CopyOption {
cwd?: string
rename?: (basename: string) => string
parents?: boolean
}
const identity = (x: string) => x
export const copy = async (
src: string | string[],
dest: string,
{ cwd, rename = identity, parents = true }: CopyOption = {}
) => {
const source = typeof src === 'string' ? [src] : src
if (source.length === 0 || !dest) {
throw new TypeError('`src` and `dest` are required')
}
const sourceFiles = await glob(source, {
cwd,
dot: true,
absolute: false,
stats: false,
})
const destRelativeToCwd = cwd ? resolve(cwd, dest) : dest
return Promise.all(
sourceFiles.map(async (p) => {
const dirName = dirname(p)
const baseName = rename(basename(p))
const from = cwd ? resolve(cwd, p) : p
const to = parents
? join(destRelativeToCwd, dirName, baseName)
: join(destRelativeToCwd, baseName)
// Ensure the destination directory exists
await mkdir(dirname(to), { recursive: true })
return copyFile(from, to)
})
)
}

View File

@@ -0,0 +1,147 @@
/* eslint-disable import/no-extraneous-dependencies */
import { Readable } from 'node:stream'
import { sep, posix } from 'node:path'
import { pipeline } from 'node:stream/promises'
import { x } from 'tar'
export type RepoInfo = {
username: string
name: string
branch: string
filePath: string
}
export async function isUrlOk(url: string): Promise<boolean> {
try {
const res = await fetch(url, { method: 'HEAD' })
return res.status === 200
} catch {
return false
}
}
export async function getRepoInfo(
url: URL,
examplePath?: string
): Promise<RepoInfo | undefined> {
const [, username, name, t, _branch, ...file] = url.pathname.split('/')
const filePath = examplePath ? examplePath.replace(/^\//, '') : file.join('/')
if (
// Support repos whose entire purpose is to be a Next.js example, e.g.
// https://github.com/:username/:my-cool-nextjs-example-repo-name.
t === undefined ||
// Support GitHub URL that ends with a trailing slash, e.g.
// https://github.com/:username/:my-cool-nextjs-example-repo-name/
// In this case "t" will be an empty string while the next part "_branch" will be undefined
(t === '' && _branch === undefined)
) {
try {
const infoResponse = await fetch(
`https://api.github.com/repos/${username}/${name}`
)
if (infoResponse.status !== 200) {
return
}
const info = await infoResponse.json()
return { username, name, branch: info['default_branch'], filePath }
} catch {
return
}
}
// If examplePath is available, the branch name takes the entire path
const branch = examplePath
? `${_branch}/${file.join('/')}`.replace(new RegExp(`/${filePath}|/$`), '')
: _branch
if (username && name && branch && t === 'tree') {
return { username, name, branch, filePath }
}
}
export function hasRepo({
username,
name,
branch,
filePath,
}: RepoInfo): Promise<boolean> {
const contentsUrl = `https://api.github.com/repos/${username}/${name}/contents`
const packagePath = `${filePath ? `/${filePath}` : ''}/package.json`
return isUrlOk(contentsUrl + packagePath + `?ref=${branch}`)
}
export function existsInRepo(nameOrUrl: string): Promise<boolean> {
try {
const url = new URL(nameOrUrl)
return isUrlOk(url.href)
} catch {
return isUrlOk(
`https://api.github.com/repos/vercel/next.js/contents/examples/${encodeURIComponent(
nameOrUrl
)}`
)
}
}
async function downloadTarStream(url: string) {
const res = await fetch(url)
if (!res.body) {
throw new Error(`Failed to download: ${url}`)
}
return Readable.fromWeb(res.body as import('stream/web').ReadableStream)
}
export async function downloadAndExtractRepo(
root: string,
{ username, name, branch, filePath }: RepoInfo
) {
let rootPath: string | null = null
await pipeline(
await downloadTarStream(
`https://codeload.github.com/${username}/${name}/tar.gz/${branch}`
),
x({
cwd: root,
strip: filePath ? filePath.split('/').length + 1 : 1,
filter: (p: string) => {
// Convert Windows path separators to POSIX style
const posixPath = p.split(sep).join(posix.sep)
// Determine the unpacked root path dynamically instead of hardcoding to the fetched repo's name / branch.
// This avoids the condition when the repository has been renamed, and the old repository name is used to fetch the example.
// The tar download will work as it is redirected automatically, but the root directory of the extracted
// example will be the new, renamed name instead of the name used to fetch the example, breaking the filter.
if (rootPath === null) {
const pathSegments = posixPath.split(posix.sep)
rootPath = pathSegments.length ? pathSegments[0] : null
}
return posixPath.startsWith(
`${rootPath}${filePath ? `/${filePath}/` : '/'}`
)
},
})
)
}
export async function downloadAndExtractExample(root: string, name: string) {
if (name === '__internal-testing-retry') {
throw new Error('This is an internal example for testing the CLI.')
}
await pipeline(
await downloadTarStream(
'https://codeload.github.com/vercel/next.js/tar.gz/canary'
),
x({
cwd: root,
strip: 2 + name.split('/').length,
filter: (p) => p.includes(`next.js-canary/examples/${name}/`),
})
)
}

View File

@@ -0,0 +1,24 @@
import fs from 'fs'
import path from 'path'
/**
* Generate AGENTS.md and CLAUDE.md in the project root.
* AGENTS.md contains the instructions, CLAUDE.md references it using @ syntax.
*/
export function generateAgentFiles(root: string): void {
const agentsMdContent = `<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in \`node_modules/next/dist/docs/\` before writing any code. Heed deprecation notices.
<!-- END:nextjs-agent-rules -->
`
const claudeMdContent = `@AGENTS.md
`
const agentsMdPath = path.join(root, 'AGENTS.md')
const claudeMdPath = path.join(root, 'CLAUDE.md')
fs.writeFileSync(agentsMdPath, agentsMdContent, 'utf-8')
fs.writeFileSync(claudeMdPath, claudeMdContent, 'utf-8')
}

View File

@@ -0,0 +1,53 @@
import { execSync } from 'child_process'
export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun'
export function getPkgManager(): PackageManager {
const userAgent = process.env.npm_config_user_agent || ''
if (userAgent.startsWith('yarn')) {
return 'yarn'
}
if (userAgent.startsWith('pnpm')) {
return 'pnpm'
}
if (userAgent.startsWith('bun')) {
return 'bun'
}
return 'npm'
}
/**
* Get the major version of pnpm being used.
* Returns null if unable to determine the version.
*
* First tries to parse from npm_config_user_agent (e.g., "pnpm/9.13.2 npm/? ..."),
* then falls back to spawning `pnpm --version --silent`.
*/
export function getPnpmMajorVersion(): number | null {
// Try to get version from user agent first (e.g., "pnpm/9.13.2 npm/? node/v20.x linux x64")
const userAgent = process.env.npm_config_user_agent || ''
const pnpmVersionMatch = userAgent.match(/pnpm\/(\d+)/)
if (pnpmVersionMatch) {
return parseInt(pnpmVersionMatch[1], 10)
}
// Fall back to spawning pnpm --version
try {
const version = execSync('pnpm --version --silent', {
encoding: 'utf8',
stdio: ['pipe', 'pipe', 'ignore'],
}).trim()
const majorVersion = parseInt(version.split('.')[0], 10)
if (!Number.isNaN(majorVersion)) {
return majorVersion
}
} catch {
// pnpm not available or failed to run
}
return null
}

View File

@@ -0,0 +1,57 @@
import { execSync } from 'node:child_process'
import { join } from 'node:path'
import { rmSync } from 'node:fs'
function isInGitRepository(): boolean {
try {
execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' })
return true
} catch (_) {}
return false
}
function isInMercurialRepository(): boolean {
try {
execSync('hg --cwd . root', { stdio: 'ignore' })
return true
} catch (_) {}
return false
}
function isDefaultBranchSet(): boolean {
try {
execSync('git config init.defaultBranch', { stdio: 'ignore' })
return true
} catch (_) {}
return false
}
export function tryGitInit(root: string): boolean {
let didInit = false
try {
execSync('git --version', { stdio: 'ignore' })
if (isInGitRepository() || isInMercurialRepository()) {
return false
}
execSync('git init', { stdio: 'ignore' })
didInit = true
if (!isDefaultBranchSet()) {
execSync('git checkout -b main', { stdio: 'ignore' })
}
execSync('git add -A', { stdio: 'ignore' })
execSync('git commit -m "Initial commit from Create Next App"', {
stdio: 'ignore',
})
return true
} catch (e) {
if (didInit) {
try {
rmSync(join(root, '.git'), { recursive: true, force: true })
} catch (_) {}
}
return false
}
}

View File

@@ -0,0 +1,50 @@
/* eslint-disable import/no-extraneous-dependencies */
import { yellow } from 'picocolors'
import spawn from 'cross-spawn'
import type { PackageManager } from './get-pkg-manager'
/**
* Spawn a package manager installation based on user preference.
*
* @returns A Promise that resolves once the installation is finished.
*/
export async function install(
/** Indicate which package manager to use. */
packageManager: PackageManager,
/** Indicate whether there is an active Internet connection.*/
isOnline: boolean
): Promise<void> {
const args: string[] = ['install']
if (!isOnline) {
console.log(
yellow('You appear to be offline.\nFalling back to the local cache.')
)
args.push('--offline')
}
/**
* Return a Promise that resolves once the installation is finished.
*/
return new Promise((resolve, reject) => {
/**
* Spawn the installation process.
*/
const child = spawn(packageManager, args, {
stdio: 'inherit',
env: {
...process.env,
ADBLOCK: '1',
// we set NODE_ENV to development as pnpm skips dev
// dependencies when production
NODE_ENV: 'development',
DISABLE_OPENCOLLECTIVE: '1',
},
})
child.on('close', (code) => {
if (code !== 0) {
reject({ command: `${packageManager} ${args.join(' ')}` })
return
}
resolve()
})
})
}

View File

@@ -0,0 +1,67 @@
/* eslint-disable import/no-extraneous-dependencies */
import { lstatSync, readdirSync } from 'node:fs'
import { join } from 'node:path'
import { green, blue } from 'picocolors'
export function isFolderEmpty(root: string, name: string): boolean {
const validFilesOrFolders = [
'.claude',
'.cursor',
'.DS_Store',
'.git',
'.gitattributes',
'.gitignore',
'.gitlab-ci.yml',
'.hg',
'.hgcheck',
'.hgignore',
'.idea',
'.npmignore',
'.travis.yml',
'.vscode',
'.zed',
'LICENSE',
'Thumbs.db',
'docs',
'mkdocs.yml',
'npm-debug.log',
'yarn-debug.log',
'yarn-error.log',
'yarnrc.yml',
'.yarn',
]
const conflicts = readdirSync(root).filter(
(fileOrFolder) =>
!validFilesOrFolders.includes(fileOrFolder) &&
// Support IntelliJ IDEA-based editors
!/\.iml$/.test(fileOrFolder)
)
if (conflicts.length > 0) {
console.log(
`The directory ${green(name)} contains files that could conflict:`
)
console.log()
for (const file of conflicts) {
try {
const stats = lstatSync(join(root, file))
if (stats.isDirectory()) {
console.log(` ${blue(file)}/`)
} else {
console.log(` ${file}`)
}
} catch {
console.log(` ${file}`)
}
}
console.log()
console.log(
'Either try using a new directory name, or remove the files listed above.'
)
console.log()
return false
}
return true
}

View File

@@ -0,0 +1,52 @@
import { execSync } from 'node:child_process'
import { lookup } from 'node:dns/promises'
import { URL } from 'node:url'
function getProxy(): string | undefined {
if (process.env.https_proxy) {
return process.env.https_proxy
}
try {
const httpsProxy = execSync('npm config get https-proxy').toString().trim()
return httpsProxy !== 'null' ? httpsProxy : undefined
} catch (e) {
return
}
}
export async function getOnline(): Promise<boolean> {
try {
await lookup('registry.yarnpkg.com')
// If DNS lookup succeeds, we are online
return true
} catch {
// The DNS lookup failed, but we are still fine as long as a proxy has been set
const proxy = getProxy()
if (!proxy) {
return false
}
let url: URL
try {
url = new URL(proxy)
} catch {
// Invalid proxy URL
return false
}
const { hostname } = url
if (!hostname) {
// Invalid proxy URL
return false
}
try {
await lookup(hostname)
// If DNS lookup succeeds for the proxy server, we are online
return true
} catch {
// The DNS lookup for the proxy server also failed, so we are offline
return false
}
}
}

View File

@@ -0,0 +1,11 @@
import { W_OK } from 'node:constants'
import { access } from 'node:fs/promises'
export async function isWriteable(directory: string): Promise<boolean> {
try {
await access(directory, W_OK)
return true
} catch (err) {
return false
}
}

View File

@@ -0,0 +1,56 @@
/* eslint-disable import/no-extraneous-dependencies */
import spawn from 'cross-spawn'
import type { PackageManager } from './get-pkg-manager'
/**
* Runs `next typegen` using the package manager to execute the locally installed Next.js binary.
* Assumes the current working directory is the project root where Next is installed.
*/
export async function runTypegen(
packageManager: PackageManager
): Promise<void> {
return new Promise((resolve, reject) => {
// Determine the command and arguments based on the package manager
let command: string
let args: string[]
switch (packageManager) {
case 'npm':
command = 'npm'
args = ['exec', 'next', '--', 'typegen']
break
case 'yarn':
command = 'yarn'
args = ['exec', 'next', '--', 'typegen']
break
case 'pnpm':
command = 'pnpm'
args = ['exec', 'next', '--', 'typegen']
break
case 'bun':
command = 'bun'
// Bun only has `bun x` which is not the same thing.
// We need to hope Bun never implements their own `bun next`.
args = ['next', 'typegen']
break
default:
packageManager satisfies never
throw new Error(`Unsupported package manager: ${packageManager}`)
}
const child = spawn(command, args, {
stdio: 'inherit',
env: {
...process.env,
},
})
child.on('close', (code) => {
if (code !== 0) {
reject(new Error(`next typegen exited with code ${code}`))
return
}
resolve()
})
})
}

View File

@@ -0,0 +1,26 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import validateProjectName from 'validate-npm-package-name'
type ValidateNpmNameResult =
| {
valid: true
}
| {
valid: false
problems: string[]
}
export function validateNpmName(name: string): ValidateNpmNameResult {
const nameValidation = validateProjectName(name)
if (nameValidation.validForNewPackages) {
return { valid: true }
}
return {
valid: false,
problems: [
...(nameValidation.errors || []),
...(nameValidation.warnings || []),
],
}
}

View File

@@ -0,0 +1,742 @@
#!/usr/bin/env node
/* eslint-disable import/no-extraneous-dependencies */
import ciInfo from 'ci-info'
import { Command } from 'commander'
import Conf from 'conf'
import { existsSync } from 'node:fs'
import { basename, resolve } from 'node:path'
import { blue, bold, cyan, green, red, yellow } from 'picocolors'
import type { InitialReturnValue } from 'prompts'
import prompts from 'prompts'
import updateCheck from 'update-check'
import { createApp, DownloadError } from './create-app'
import type { PackageManager } from './helpers/get-pkg-manager'
import { getPkgManager } from './helpers/get-pkg-manager'
import { isFolderEmpty } from './helpers/is-folder-empty'
import { validateNpmName } from './helpers/validate-pkg'
import packageJson from './package.json'
import { Bundler } from './templates'
let projectPath: string = ''
const handleSigTerm = () => process.exit(0)
process.on('SIGINT', handleSigTerm)
process.on('SIGTERM', handleSigTerm)
const onPromptState = (state: {
value: InitialReturnValue
aborted: boolean
exited: boolean
}) => {
if (state.aborted) {
// If we don't re-enable the terminal cursor before exiting
// the program, the cursor will remain hidden
process.stdout.write('\x1B[?25h')
process.stdout.write('\n')
process.exit(1)
}
}
const program = new Command(packageJson.name)
.version(
packageJson.version,
'-v, --version',
'Output the current version of create-next-app.'
)
.argument('[directory]')
.usage('[directory] [options]')
.helpOption('-h, --help', 'Display this help message.')
.option('--ts, --typescript', 'Initialize as a TypeScript project. (default)')
.option('--js, --javascript', 'Initialize as a JavaScript project.')
.option('--tailwind', 'Initialize with Tailwind CSS config. (default)')
.option('--react-compiler', 'Initialize with React Compiler enabled.')
.option('--eslint', 'Initialize with ESLint config.')
.option('--biome', 'Initialize with Biome config.')
.option('--app', 'Initialize as an App Router project.')
.option('--src-dir', "Initialize inside a 'src/' directory.")
.option('--rspack', 'Enable Rspack as the bundler.')
.option(
'--import-alias <prefix/*>',
'Specify import alias to use (default "@/*").'
)
.option('--api', 'Initialize a headless API using the App Router.')
.option('--empty', 'Initialize an empty project.')
.option(
'--use-npm',
'Explicitly tell the CLI to bootstrap the application using npm.'
)
.option(
'--use-pnpm',
'Explicitly tell the CLI to bootstrap the application using pnpm.'
)
.option(
'--use-yarn',
'Explicitly tell the CLI to bootstrap the application using Yarn.'
)
.option(
'--use-bun',
'Explicitly tell the CLI to bootstrap the application using Bun.'
)
.option(
'--reset, --reset-preferences',
'Reset the preferences saved for create-next-app.'
)
.option(
'--skip-install',
'Explicitly tell the CLI to skip installing packages.'
)
.option('--yes', 'Use saved preferences or defaults for unprovided options.')
.option(
'-e, --example <example-name|github-url>',
`
An example to bootstrap the app with. You can use an example name
from the official Next.js repo or a public GitHub URL. The URL can use
any branch and/or subdirectory.
`
)
.option(
'--example-path <path-to-example>',
`
In a rare case, your GitHub URL might contain a branch name with
a slash (e.g. bug/fix-1) and the path to the example (e.g. foo/bar).
In this case, you must specify the path to the example separately:
--example-path foo/bar
`
)
.option(
'--agents-md',
'Include AGENTS.md to guide coding agents to write up-to-date Next.js code. (default)'
)
.option('--disable-git', `Skip initializing a git repository.`)
.action((name) => {
// Commander does not implicitly support negated options. When they are used
// by the user they will be interpreted as the positional argument (name) in
// the action handler. See https://github.com/tj/commander.js/pull/1355
if (name && !name.startsWith('--no-')) {
projectPath = name
}
})
.allowUnknownOption()
.parse(process.argv)
const opts = program.opts()
const { args } = program
const packageManager: PackageManager = !!opts.useNpm
? 'npm'
: !!opts.usePnpm
? 'pnpm'
: !!opts.useYarn
? 'yarn'
: !!opts.useBun
? 'bun'
: getPkgManager()
async function run(): Promise<void> {
const conf = new Conf({ projectName: 'create-next-app' })
if (opts.resetPreferences) {
const { resetPreferences } = await prompts({
onState: onPromptState,
type: 'toggle',
name: 'resetPreferences',
message: 'Would you like to reset the saved preferences?',
initial: false,
active: 'Yes',
inactive: 'No',
})
if (resetPreferences) {
conf.clear()
console.log('The preferences have been reset successfully!')
}
process.exit(0)
}
if (typeof projectPath === 'string') {
projectPath = projectPath.trim()
}
if (!projectPath) {
const res = await prompts({
onState: onPromptState,
type: 'text',
name: 'path',
message: 'What is your project named?',
initial: 'my-app',
validate: (name) => {
const validation = validateNpmName(basename(resolve(name)))
if (validation.valid) {
return true
}
return 'Invalid project name: ' + validation.problems[0]
},
})
if (typeof res.path === 'string') {
projectPath = res.path.trim()
}
}
if (!projectPath) {
console.log(
'\nPlease specify the project directory:\n' +
` ${cyan(opts.name())} ${green('<project-directory>')}\n` +
'For example:\n' +
` ${cyan(opts.name())} ${green('my-next-app')}\n\n` +
`Run ${cyan(`${opts.name()} --help`)} to see all options.`
)
process.exit(1)
}
const appPath = resolve(projectPath)
const appName = basename(appPath)
const validation = validateNpmName(appName)
if (!validation.valid) {
console.error(
`Could not create a project called ${red(
`"${appName}"`
)} because of npm naming restrictions:`
)
validation.problems.forEach((p) =>
console.error(` ${red(bold('*'))} ${p}`)
)
process.exit(1)
}
if (opts.example === true) {
console.error(
'Please provide an example name or url, otherwise remove the example option.'
)
process.exit(1)
}
if (existsSync(appPath) && !isFolderEmpty(appPath, appName)) {
process.exit(1)
}
const example = typeof opts.example === 'string' && opts.example.trim()
const preferences = (conf.get('preferences') || {}) as Record<
string,
boolean | string
>
/**
* If the user does not provide the necessary flags, prompt them for their
* preferences, unless `--yes` option was specified, or when running in CI.
*/
let skipPrompt = ciInfo.isCI || opts.yes
let useRecommendedDefaults = false
if (!example) {
const defaults: typeof preferences = {
typescript: true,
eslint: false,
linter: 'eslint',
tailwind: true,
app: true,
srcDir: false,
importAlias: '@/*',
customizeImportAlias: false,
empty: false,
disableGit: false,
reactCompiler: false,
agentsMd: true,
}
type DisplayConfigItem = {
key: keyof typeof defaults
values?: Record<string, string>
}
const displayConfig: DisplayConfigItem[] = [
{
key: 'typescript',
values: { true: 'TypeScript', false: 'JavaScript' },
},
{ key: 'linter', values: { eslint: 'ESLint', biome: 'Biome' } },
{ key: 'reactCompiler', values: { true: 'React Compiler' } },
{ key: 'tailwind', values: { true: 'Tailwind CSS' } },
{ key: 'srcDir', values: { true: 'src/ dir' } },
{ key: 'app', values: { true: 'App Router', false: 'Pages Router' } },
{ key: 'agentsMd', values: { true: 'AGENTS.md' } },
]
// Helper to format settings for display based on displayConfig
const formatSettingsDescription = (
settings: Record<string, boolean | string>
) => {
const descriptions: string[] = []
for (const config of displayConfig) {
const value = settings[config.key]
if (config.values) {
// Look up the display label for this value
const label = config.values[String(value)]
if (label) {
descriptions.push(label)
}
}
}
return descriptions.join(', ')
}
// Check if we have saved preferences
const hasSavedPreferences = Object.keys(preferences).length > 0
// Check if user provided any configuration flags
// If they did, skip the "recommended defaults" prompt and go straight to
// individual prompts for any missing options
const hasProvidedOptions = process.argv.some((arg) => arg.startsWith('--'))
// Only show the "recommended defaults" prompt if:
// - Not in CI and not using --yes flag
// - User hasn't provided any custom options
if (!skipPrompt && !hasProvidedOptions) {
const choices: Array<{
title: string
value: string
description?: string
}> = [
{
title: 'Yes, use recommended defaults',
value: 'recommended',
description: formatSettingsDescription(defaults),
},
{
title: 'No, customize settings',
value: 'customize',
description: 'Choose your own preferences',
},
]
// Add "reuse previous settings" option if we have saved preferences
if (hasSavedPreferences) {
const prefDescription = formatSettingsDescription(preferences)
choices.splice(1, 0, {
title: 'No, reuse previous settings',
value: 'reuse',
description: prefDescription,
})
}
const { setupChoice } = await prompts(
{
type: 'select',
name: 'setupChoice',
message: 'Would you like to use the recommended Next.js defaults?',
choices,
initial: 0,
},
{
onCancel: () => {
console.error('Exiting.')
process.exit(1)
},
}
)
if (setupChoice === 'recommended') {
useRecommendedDefaults = true
skipPrompt = true
} else if (setupChoice === 'reuse') {
skipPrompt = true
}
}
// If using recommended defaults, populate preferences with defaults
// This ensures they are saved for reuse next time
if (useRecommendedDefaults) {
Object.assign(preferences, defaults)
}
const getPrefOrDefault = (field: string) => {
// If using recommended defaults, always use hardcoded defaults
if (useRecommendedDefaults) {
return defaults[field]
}
// If not using the recommended template, we prefer saved preferences, otherwise defaults.
return preferences[field] ?? defaults[field]
}
if (!opts.typescript && !opts.javascript) {
if (skipPrompt) {
// default to TypeScript in CI as we can't prompt to
// prevent breaking setup flows
opts.typescript = getPrefOrDefault('typescript')
} else {
const styledTypeScript = blue('TypeScript')
const { typescript } = await prompts(
{
type: 'toggle',
name: 'typescript',
message: `Would you like to use ${styledTypeScript}?`,
initial: getPrefOrDefault('typescript'),
active: 'Yes',
inactive: 'No',
},
{
/**
* User inputs Ctrl+C or Ctrl+D to exit the prompt. We should close the
* process and not write to the file system.
*/
onCancel: () => {
console.error('Exiting.')
process.exit(1)
},
}
)
/**
* Depending on the prompt response, set the appropriate program flags.
*/
opts.typescript = Boolean(typescript)
opts.javascript = !typescript
preferences.typescript = Boolean(typescript)
}
}
// Determine linter choice if not specified via CLI flags
// Support both --no-linter (new) and --no-eslint (legacy) for backward compatibility
const noLinter =
args.includes('--no-linter') || args.includes('--no-eslint')
if (!opts.eslint && !opts.biome && !noLinter && !opts.api) {
if (skipPrompt) {
const preferredLinter = getPrefOrDefault('linter')
opts.eslint = preferredLinter === 'eslint'
opts.biome = preferredLinter === 'biome'
// No need to set noLinter flag since we check args at runtime
} else {
const linterIndexMap = {
eslint: 0,
biome: 1,
none: 2,
}
const { linter } = await prompts({
onState: onPromptState,
type: 'select',
name: 'linter',
message: 'Which linter would you like to use?',
choices: [
{
title: 'ESLint',
value: 'eslint',
description: 'More comprehensive lint rules',
},
{
title: 'Biome',
value: 'biome',
description: 'Fast formatter and linter (fewer rules)',
},
{
title: 'None',
value: 'none',
description: 'Skip linter configuration',
},
],
initial:
linterIndexMap[
getPrefOrDefault('linter') as keyof typeof linterIndexMap
],
})
opts.eslint = linter === 'eslint'
opts.biome = linter === 'biome'
preferences.linter = linter
// Keep backwards compatibility with old eslint preference
preferences.eslint = linter === 'eslint'
}
} else if (opts.eslint) {
opts.biome = false
preferences.linter = 'eslint'
preferences.eslint = true
} else if (opts.biome) {
opts.eslint = false
preferences.linter = 'biome'
preferences.eslint = false
} else if (noLinter) {
opts.eslint = false
opts.biome = false
preferences.linter = 'none'
preferences.eslint = false
}
if (
!opts.reactCompiler &&
!args.includes('--no-react-compiler') &&
!opts.api
) {
if (skipPrompt) {
opts.reactCompiler = getPrefOrDefault('reactCompiler')
} else {
const styledReactCompiler = blue('React Compiler')
const { reactCompiler } = await prompts({
onState: onPromptState,
type: 'toggle',
name: 'reactCompiler',
message: `Would you like to use ${styledReactCompiler}?`,
initial: getPrefOrDefault('reactCompiler'),
active: 'Yes',
inactive: 'No',
})
opts.reactCompiler = Boolean(reactCompiler)
preferences.reactCompiler = Boolean(reactCompiler)
}
}
if (!opts.tailwind && !args.includes('--no-tailwind') && !opts.api) {
if (skipPrompt) {
opts.tailwind = getPrefOrDefault('tailwind')
} else {
const tw = blue('Tailwind CSS')
const { tailwind } = await prompts({
onState: onPromptState,
type: 'toggle',
name: 'tailwind',
message: `Would you like to use ${tw}?`,
initial: getPrefOrDefault('tailwind'),
active: 'Yes',
inactive: 'No',
})
opts.tailwind = Boolean(tailwind)
preferences.tailwind = Boolean(tailwind)
}
}
if (!opts.srcDir && !args.includes('--no-src-dir')) {
if (skipPrompt) {
opts.srcDir = getPrefOrDefault('srcDir')
} else {
const styledSrcDir = blue('`src/` directory')
const { srcDir } = await prompts({
onState: onPromptState,
type: 'toggle',
name: 'srcDir',
message: `Would you like your code inside a ${styledSrcDir}?`,
initial: getPrefOrDefault('srcDir'),
active: 'Yes',
inactive: 'No',
})
opts.srcDir = Boolean(srcDir)
preferences.srcDir = Boolean(srcDir)
}
}
if (!opts.app && !args.includes('--no-app') && !opts.api) {
if (skipPrompt) {
opts.app = getPrefOrDefault('app')
} else {
const styledAppDir = blue('App Router')
const { app } = await prompts({
onState: onPromptState,
type: 'toggle',
name: 'app',
message: `Would you like to use ${styledAppDir}? (recommended)`,
initial: getPrefOrDefault('app'),
active: 'Yes',
inactive: 'No',
})
opts.app = Boolean(app)
preferences.app = Boolean(app)
}
}
const importAliasPattern = /^[^*"]+\/\*\s*$/
if (
typeof opts.importAlias !== 'string' ||
!importAliasPattern.test(opts.importAlias)
) {
if (skipPrompt) {
// We don't use preferences here because the default value is @/* regardless of existing preferences
opts.importAlias = defaults.importAlias
} else if (args.includes('--no-import-alias')) {
opts.importAlias = defaults.importAlias
} else {
const styledImportAlias = blue('import alias')
const { customizeImportAlias } = await prompts({
onState: onPromptState,
type: 'toggle',
name: 'customizeImportAlias',
message: `Would you like to customize the ${styledImportAlias} (\`${defaults.importAlias}\` by default)?`,
initial: getPrefOrDefault('customizeImportAlias'),
active: 'Yes',
inactive: 'No',
})
if (!customizeImportAlias) {
// We don't use preferences here because the default value is @/* regardless of existing preferences
opts.importAlias = defaults.importAlias
} else {
const { importAlias } = await prompts({
onState: onPromptState,
type: 'text',
name: 'importAlias',
message: `What ${styledImportAlias} would you like configured?`,
initial: getPrefOrDefault('importAlias'),
validate: (value) =>
importAliasPattern.test(value)
? true
: 'Import alias must follow the pattern <prefix>/*',
})
opts.importAlias = importAlias
preferences.importAlias = importAlias
}
}
}
if (args.includes('--no-agents-md')) {
opts.agentsMd = false
} else if (!opts.agentsMd) {
if (skipPrompt) {
opts.agentsMd = getPrefOrDefault('agentsMd')
} else {
const { agentsMd } = await prompts(
{
type: 'toggle',
name: 'agentsMd',
message:
'Would you like to include AGENTS.md to guide coding agents to write up-to-date Next.js code?',
initial: getPrefOrDefault('agentsMd'),
active: 'Yes',
inactive: 'No',
},
{
onCancel: () => {
console.error('Exiting.')
process.exit(1)
},
}
)
opts.agentsMd = Boolean(agentsMd)
preferences.agentsMd = Boolean(agentsMd)
}
}
}
const bundler: Bundler = opts.rspack ? Bundler.Rspack : Bundler.Turbopack
try {
await createApp({
appPath,
packageManager,
example: example && example !== 'default' ? example : undefined,
examplePath: opts.examplePath,
typescript: opts.typescript,
tailwind: opts.tailwind,
eslint: opts.eslint,
biome: opts.biome,
app: opts.app,
srcDir: opts.srcDir,
importAlias: opts.importAlias,
skipInstall: opts.skipInstall,
empty: opts.empty,
api: opts.api,
bundler,
disableGit: opts.disableGit,
reactCompiler: opts.reactCompiler,
agentsMd: opts.agentsMd,
})
} catch (reason) {
if (!(reason instanceof DownloadError)) {
throw reason
}
const res = await prompts({
onState: onPromptState,
type: 'confirm',
name: 'builtin',
message:
`Could not download "${example}" because of a connectivity issue between your machine and GitHub.\n` +
`Do you want to use the default template instead?`,
initial: true,
})
if (!res.builtin) {
throw reason
}
await createApp({
appPath,
packageManager,
typescript: opts.typescript,
eslint: opts.eslint,
biome: opts.biome,
tailwind: opts.tailwind,
app: opts.app,
srcDir: opts.srcDir,
importAlias: opts.importAlias,
skipInstall: opts.skipInstall,
empty: opts.empty,
bundler,
disableGit: opts.disableGit,
reactCompiler: opts.reactCompiler,
agentsMd: opts.agentsMd,
})
}
conf.set('preferences', preferences)
}
// Determine the appropriate dist-tag to check for updates.
// For prerelease versions like "16.1.1-canary.32", extract "canary" and check
// against that dist-tag. This ensures canary users are notified about newer
// canary releases, not incorrectly prompted to "update" to stable.
function getDistTag(version: string): string {
const prereleaseMatch = version.match(/-([a-z]+)/)
return prereleaseMatch ? prereleaseMatch[1] : 'latest'
}
const update = updateCheck(packageJson, {
distTag: getDistTag(packageJson.version),
}).catch(() => null)
async function notifyUpdate(): Promise<void> {
try {
if ((await update)?.latest) {
const global = {
npm: 'npm i -g',
yarn: 'yarn global add',
pnpm: 'pnpm add -g',
bun: 'bun add -g',
}
const distTag = getDistTag(packageJson.version)
const pkgTag = distTag === 'latest' ? '' : `@${distTag}`
const updateMessage = `${global[packageManager]} create-next-app${pkgTag}`
console.log(
yellow(bold('A new version of `create-next-app` is available!')) +
'\n' +
'You can update by running: ' +
cyan(updateMessage) +
'\n'
)
}
process.exit(0)
} catch {
// ignore error
}
}
async function exit(reason: { command?: string }) {
console.log()
console.log('Aborting installation.')
if (reason.command) {
console.log(` ${cyan(reason.command)} has failed.`)
} else {
console.log(
red('Unexpected error. Please report it as a bug:') + '\n',
reason
)
}
console.log()
await notifyUpdate()
process.exit(1)
}
run().then(notifyUpdate).catch(exit)

View File

@@ -0,0 +1,53 @@
{
"name": "create-next-app",
"version": "16.2.0-canary.85",
"keywords": [
"react",
"next",
"next.js"
],
"description": "Create Next.js-powered React apps with one command",
"repository": {
"type": "git",
"url": "https://github.com/vercel/next.js",
"directory": "packages/create-next-app"
},
"author": "Next.js Team <support@vercel.com>",
"license": "MIT",
"bin": {
"create-next-app": "./dist/index.js"
},
"files": [
"dist"
],
"scripts": {
"dev": "ncc build ./index.ts -w -o dist/",
"prebuild": "node ../../scripts/rm.mjs dist",
"build": "ncc build ./index.ts -o ./dist/ --minify --no-cache --no-source-map-register",
"prepublishOnly": "cd ../../ && turbo run build",
"lint-fix": "pnpm prettier -w --plugin prettier-plugin-tailwindcss 'templates/*-tw/{ts,js}/{app,pages}/**/*.{js,ts,tsx}'"
},
"devDependencies": {
"@types/async-retry": "1.4.2",
"@types/cross-spawn": "6.0.0",
"@types/node": "20.14.2",
"@types/prompts": "2.4.2",
"@types/validate-npm-package-name": "4.0.2",
"@vercel/ncc": "0.38.1",
"async-retry": "1.3.1",
"ci-info": "4.0.0",
"commander": "12.1.0",
"conf": "13.0.1",
"cross-spawn": "7.0.3",
"fast-glob": "3.3.1",
"picocolors": "1.0.0",
"prettier-plugin-tailwindcss": "0.6.2",
"prompts": "2.4.2",
"tar": "7.5.7",
"update-check": "1.5.4",
"validate-npm-package-name": "5.0.1"
},
"engines": {
"node": ">=20.9.0"
}
}

View File

@@ -0,0 +1,5 @@
{
"trailingComma": "all",
"singleQuote": false,
"semi": true
}

View File

@@ -0,0 +1,40 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/route.ts`. The page auto-updates as you edit the file.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
## API Routes
This directory contains example API routes for the headless API app.
For more details, see [route.js file convention](https://nextjs.org/docs/app/api-reference/file-conventions/route).

View File

@@ -0,0 +1,6 @@
import { NextResponse } from "next/server";
export async function GET(request, { params }) {
const { slug } = await params;
return NextResponse.json({ message: `Hello ${slug}!` });
}

View File

@@ -0,0 +1,5 @@
import { NextResponse } from "next/server";
export async function GET() {
return NextResponse.json({ message: "Hello world!" });
}

View File

@@ -0,0 +1,34 @@
{
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": ["**", "!node_modules", "!.next", "!dist", "!build"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
},
"domains": {
"next": "recommended",
"react": "recommended"
}
},
"assist": {
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}

View File

@@ -0,0 +1,40 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@@ -0,0 +1,7 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}

View File

@@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
/* config options here */
};
export default nextConfig;

View File

@@ -0,0 +1,40 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/route.ts`. The page auto-updates as you edit the file.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
## API Routes
This directory contains example API routes for the headless API app.
For more details, see [route.js file convention](https://nextjs.org/docs/app/api-reference/file-conventions/route).

View File

@@ -0,0 +1,9 @@
import { NextRequest, NextResponse } from "next/server";
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ slug: string }> },
) {
const { slug } = await params;
return NextResponse.json({ message: `Hello ${slug}!` });
}

View File

@@ -0,0 +1,5 @@
import { NextResponse } from "next/server";
export async function GET() {
return NextResponse.json({ message: "Hello world!" });
}

View File

@@ -0,0 +1,34 @@
{
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": ["**", "!node_modules", "!.next", "!dist", "!build"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
},
"domains": {
"next": "recommended",
"react": "recommended"
}
},
"assist": {
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}

View File

@@ -0,0 +1,40 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View File

@@ -0,0 +1,7 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
};
export default nextConfig;

View File

@@ -0,0 +1,34 @@
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts",
"**/*.mts"
],
"exclude": ["node_modules"]
}

View File

@@ -0,0 +1,3 @@
# Rename this file to `.env.local` to use environment variables locally with `next dev`
# https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
MY_HOST="example.com"

View File

@@ -0,0 +1,34 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

View File

@@ -0,0 +1,12 @@
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}

View File

@@ -0,0 +1,7 @@
export default function Home() {
return (
<main>
<div>Hello World!</div>
</main>
);
}

View File

@@ -0,0 +1,34 @@
{
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": ["**", "!node_modules", "!.next", "!dist", "!build"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
},
"domains": {
"next": "recommended",
"react": "recommended"
}
},
"assist": {
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}

View File

@@ -0,0 +1,16 @@
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
const eslintConfig = defineConfig([
...nextVitals,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
]),
]);
export default eslintConfig;

View File

@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@@ -0,0 +1,7 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}

View File

@@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
/* config options here */
};
export default nextConfig;

View File

@@ -0,0 +1,3 @@
# Rename this file to `.env.local` to use environment variables locally with `next dev`
# https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
MY_HOST="example.com"

View File

@@ -0,0 +1,34 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

View File

@@ -0,0 +1,18 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}

View File

@@ -0,0 +1,7 @@
export default function Home() {
return (
<main>
<div>Hello world!</div>
</main>
);
}

View File

@@ -0,0 +1,34 @@
{
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": ["**", "!node_modules", "!.next", "!dist", "!build"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
},
"domains": {
"next": "recommended",
"react": "recommended"
}
},
"assist": {
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}

View File

@@ -0,0 +1,18 @@
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";
const eslintConfig = defineConfig([
...nextVitals,
...nextTs,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
]),
]);
export default eslintConfig;

View File

@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View File

@@ -0,0 +1,7 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
};
export default nextConfig;

View File

@@ -0,0 +1,34 @@
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts",
"**/*.mts"
],
"exclude": ["node_modules"]
}

View File

@@ -0,0 +1,3 @@
# Rename this file to `.env.local` to use environment variables locally with `next dev`
# https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
MY_HOST="example.com"

View File

@@ -0,0 +1,34 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

View File

@@ -0,0 +1 @@
@import "tailwindcss";

View File

@@ -0,0 +1,14 @@
import "./globals.css";
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}

View File

@@ -0,0 +1,7 @@
export default function Home() {
return (
<main>
<div>Hello world!</div>
</main>
);
}

View File

@@ -0,0 +1,37 @@
{
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": ["**", "!node_modules", "!.next", "!dist", "!build"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noUnknownAtRules": "off"
}
},
"domains": {
"next": "recommended",
"react": "recommended"
}
},
"assist": {
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}

View File

@@ -0,0 +1,16 @@
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
const eslintConfig = defineConfig([
...nextVitals,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
]),
]);
export default eslintConfig;

View File

@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@@ -0,0 +1,7 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}

View File

@@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
/* config options here */
};
export default nextConfig;

View File

@@ -0,0 +1,7 @@
const config = {
plugins: {
"@tailwindcss/postcss": {},
},
};
export default config;

View File

@@ -0,0 +1,3 @@
# Rename this file to `.env.local` to use environment variables locally with `next dev`
# https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
MY_HOST="example.com"

View File

@@ -0,0 +1,34 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

View File

@@ -0,0 +1 @@
@import "tailwindcss";

View File

@@ -0,0 +1,19 @@
import type { Metadata } from "next";
import "./globals.css";
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}

View File

@@ -0,0 +1,7 @@
export default function Home() {
return (
<main>
<div>Hello world!</div>
</main>
);
}

View File

@@ -0,0 +1,37 @@
{
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": ["**", "!node_modules", "!.next", "!dist", "!build"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noUnknownAtRules": "off"
}
},
"domains": {
"next": "recommended",
"react": "recommended"
}
},
"assist": {
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}

View File

@@ -0,0 +1,18 @@
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";
const eslintConfig = defineConfig([
...nextVitals,
...nextTs,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
]),
]);
export default eslintConfig;

View File

@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View File

@@ -0,0 +1,7 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
};
export default nextConfig;

View File

@@ -0,0 +1,7 @@
const config = {
plugins: {
"@tailwindcss/postcss": {},
},
};
export default config;

View File

@@ -0,0 +1,34 @@
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts",
"**/*.mts"
],
"exclude": ["node_modules"]
}

View File

@@ -0,0 +1,3 @@
# Rename this file to `.env.local` to use environment variables locally with `next dev`
# https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
MY_HOST="example.com"

View File

@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,26 @@
@import "tailwindcss";
:root {
--background: #ffffff;
--foreground: #171717;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
body {
background: var(--background);
color: var(--foreground);
font-family: Arial, Helvetica, sans-serif;
}

View File

@@ -0,0 +1,28 @@
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({ children }) {
return (
<html
lang="en"
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
>
<body className="min-h-full flex flex-col">{children}</body>
</html>
);
}

View File

@@ -0,0 +1,65 @@
import Image from "next/image";
export default function Home() {
return (
<div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black">
<main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
<Image
className="dark:invert"
src="/next.svg"
alt="Next.js logo"
width={100}
height={20}
priority
/>
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
To get started, edit the page.js file.
</h1>
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
Looking for a starting point or more instructions? Head over to{" "}
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="font-medium text-zinc-950 dark:text-zinc-50"
>
Templates
</a>{" "}
or the{" "}
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="font-medium text-zinc-950 dark:text-zinc-50"
>
Learning
</a>{" "}
center.
</p>
</div>
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
<a
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={16}
height={16}
/>
Deploy Now
</a>
<a
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Documentation
</a>
</div>
</main>
</div>
);
}

View File

@@ -0,0 +1,37 @@
{
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": ["**", "!node_modules", "!.next", "!dist", "!build"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noUnknownAtRules": "off"
}
},
"domains": {
"next": "recommended",
"react": "recommended"
}
},
"assist": {
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}

View File

@@ -0,0 +1,16 @@
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
const eslintConfig = defineConfig([
...nextVitals,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
]),
]);
export default eslintConfig;

View File

@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@@ -0,0 +1,7 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}

View File

@@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
/* config options here */
};
export default nextConfig;

View File

@@ -0,0 +1,7 @@
const config = {
plugins: {
"@tailwindcss/postcss": {},
},
};
export default config;

View File

@@ -0,0 +1 @@
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 391 B

View File

@@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 128 B

View File

@@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>

After

Width:  |  Height:  |  Size: 385 B

View File

@@ -0,0 +1,3 @@
# Rename this file to `.env.local` to use environment variables locally with `next dev`
# https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
MY_HOST="example.com"

View File

@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,26 @@
@import "tailwindcss";
:root {
--background: #ffffff;
--foreground: #171717;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
body {
background: var(--background);
color: var(--foreground);
font-family: Arial, Helvetica, sans-serif;
}

View File

@@ -0,0 +1,33 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html
lang="en"
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
>
<body className="min-h-full flex flex-col">{children}</body>
</html>
);
}

View File

@@ -0,0 +1,65 @@
import Image from "next/image";
export default function Home() {
return (
<div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black">
<main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
<Image
className="dark:invert"
src="/next.svg"
alt="Next.js logo"
width={100}
height={20}
priority
/>
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
To get started, edit the page.tsx file.
</h1>
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
Looking for a starting point or more instructions? Head over to{" "}
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="font-medium text-zinc-950 dark:text-zinc-50"
>
Templates
</a>{" "}
or the{" "}
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="font-medium text-zinc-950 dark:text-zinc-50"
>
Learning
</a>{" "}
center.
</p>
</div>
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
<a
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={16}
height={16}
/>
Deploy Now
</a>
<a
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Documentation
</a>
</div>
</main>
</div>
);
}

View File

@@ -0,0 +1,37 @@
{
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": ["**", "!node_modules", "!.next", "!dist", "!build"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noUnknownAtRules": "off"
}
},
"domains": {
"next": "recommended",
"react": "recommended"
}
},
"assist": {
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}

View File

@@ -0,0 +1,18 @@
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";
const eslintConfig = defineConfig([
...nextVitals,
...nextTs,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
]),
]);
export default eslintConfig;

View File

@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

Some files were not shown because too many files have changed in this diff Show More