Every Next.js project starts the same way: a blank terminal and a few decisions that will shape everything that follows. Get the setup right and you spend your time building features. Get it wrong and you spend it untangling config. This guide covers everything you need to do once — from create-next-app to your first git commit — in the order that makes sense.
Create the project
Run the official scaffolding tool. Always use the latest tag so you get the current stable release:
npx create-next-app@latest my-app
The interactive prompt will ask a series of questions. Here are the right answers for a production SaaS project:
Would you like to use TypeScript? › Yes
Would you like to use ESLint? › Yes
Would you like to use Tailwind CSS? › Yes
Would you like to use the src/ directory? › No
Would you like to use App Router? › Yes
Would you like to customize the default import alias? › No
App Router is the current Next.js architecture. The Pages Router still works but receives no new features. If you are starting a project today, always choose App Router.
Understand the folder structure
Out of the box you get a flat structure. For anything beyond a toy project you will want to add a few directories yourself:
my-app/
├── app/ # App Router pages, layouts, route handlers
│ ├── layout.tsx # Root layout — wraps every page
│ ├── page.tsx # Home page (route: /)
│ └── globals.css
├── components/ # Shared UI components (create this)
├── lib/ # Utilities, API clients, helpers (create this)
├── public/ # Static assets served from /
├── .env.local # Local secrets — never committed
├── .env.example # Committed template of required vars
├── next.config.ts
├── tailwind.config.ts
└── tsconfig.json
The components/ and lib/ directories are not created automatically. Add them immediately. Keeping business logic in lib/ and presentational code in components/ makes the codebase much easier to navigate as it grows.
ESLint and Prettier
create-next-app configures ESLint for you with the eslint-config-next ruleset. Add Prettier on top so formatting is handled automatically:
npm install --save-dev prettier eslint-config-prettier
Create .prettierrc at the project root:
{
"semi": true,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100
}
Then update .eslintrc.json to add prettier as the last config so it overrides any formatting rules from ESLint:
{
"extends": ["next/core-web-vitals", "prettier"]
}
Run npm run lint to verify there are no errors before you write a single line of your own code.
Environment variables
Next.js loads environment variables from .env.local automatically. This file should never be committed to version control. Add it to .gitignore (it is already there by default with create-next-app).
The naming convention is important:
# Server-only (never sent to the browser)
DATABASE_URL=postgresql://...
STRIPE_SECRET_KEY=sk_live_...
# Public (exposed to the browser — safe for publishable keys only)
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...
NEXT_PUBLIC_APP_URL=https://myapp.com
Any variable prefixed with NEXT_PUBLIC_ is inlined into the client bundle at build time. Everything else is server-only. Never put a secret key in a NEXT_PUBLIC_ variable — it will be visible to anyone who views your page source.
Create .env.example with placeholder values and commit it. This gives every developer on the team a reference for which variables are required:
# .env.example — copy to .env.local and fill in your values
DATABASE_URL=
STRIPE_SECRET_KEY=
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
NEXT_PUBLIC_APP_URL=
Git setup
create-next-app initialises a git repository and makes the first commit for you. Before you add anything else, verify your .gitignore includes the following entries:
.env.local
.env.*.local
node_modules/
.next/
out/
If you are pushing to GitHub, create the repository on GitHub first, then connect it:
git remote add origin https://github.com/your-username/my-app.git
git push -u origin main
VS Code setup
Create .vscode/extensions.json to recommend the same extensions to every team member:
{
"recommendations": [
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"bradlc.vscode-tailwindcss",
"prisma.prisma"
]
}
Create .vscode/settings.json to format on save automatically:
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}
With these settings in place, every file is formatted the moment you save it. No more formatting debates in code review.
Type-check before you commit
Run the TypeScript compiler without emitting output to catch type errors across the entire project:
npx tsc --noEmit
Add this to your CI pipeline alongside npm run lint and npm run build. Catching type errors in CI is far cheaper than finding them in production.
Why a boilerplate skips all of this
The steps above take two to three hours to do properly — and that is before you have written a single line of application code. A production-ready boilerplate handles all of it for you: App Router, TypeScript, Tailwind, ESLint, Prettier, a sensible folder structure, environment variable templates, git configuration, and VS Code settings, all wired together and tested.
Beyond the scaffolding, a good boilerplate also gives you auth, database, payments, email, analytics, rate limiting, and error tracking — the seven integrations every SaaS needs but none of them are specific to your product. Skip the setup, start with the problem only you can solve.
Everything in this guide — App Router scaffold, TypeScript, Tailwind, ESLint, environment variable patterns, folder structure, and VS Code config — is pre-configured in GetLaunchpad, a Next.js 16 SaaS boilerplate. Get access and ship your product today.