SkillShare Logo
STEP 2 OF 7 · SCAFFOLD

Project Setup

Create the two halves of the app — a frontend (the UI) and a backend(the API) — then install every package you'll need. Pick the tab that matches your stack choice.

01 — STRUCTURE

One Repo, Two Apps

We keep the frontend and backend side-by-side in a single folder. The database is set up on the next page (Docker for Postgres, Atlas for MongoDB).

inventory-app/
inventory-app/
├─ web/                 # frontend — Next.js OR React + Vite
├─ server/              # backend  — Express OR NestJS
├─ docker-compose.yml   # Runs Postgres & services (added in Step 7)
└─ README.md
create the folder
$ mkdir inventory-app
$ cd inventory-app
Next.js note
Next.js can host the API itself via Route Handlers, so a separate server/ is optional. This guide keeps a standalone backend so the same API works for both Next.js and React + Vite. If you prefer Next-only, put the backend code in web/app/api/* instead — the logic is identical.
02 — FRONTEND

Create the Frontend

Both options use React under the hood. Next.js (nextjs.org) is a full framework; React + Vite (vite.dev) is a minimal SPA (single-page app) setup.

create the frontend
$ npx create-next-app@latest
# ✔ What is your project named? web
# ✔ Would you like to use the recommended Next.js defaults? › No, customize settings
# ✔ Would you like to use TypeScript? Yes
# ✔ Which linter would you like to use? ESLint
# ✔ Would you like to use React Compiler? Yes
# ✔ Would you like to use Tailwind CSS? Yes
# ✔ Would you like your code inside a `src/` directory? Yes
# ✔ Would you like to use App Router? (recommended) Yes
# ✔ Would you like to customize the import alias (@/* by default)? No
# ✔ Would you like to include AGENTS.md to guide coding agents to write up-to-date Next.js code? Yes
$ cd web 
$ npm run dev   # → http://localhost:3000

Tailwind is wired up automatically. State (the logged-in user, the product list) will live in Zustand:

web/
$ npm install zustand
Optional polish
Add shadcn/ui for ready-made buttons, dialogs, and tables: npx shadcn@latest init. The components are copied into your project, so you own and can edit them.
03 — BACKEND

Create the Backend

The API holds all the real logic — auth, validation, database access, email. Express (expressjs.com) is minimal; NestJS (nestjs.com) is structured.

create the backend
$ npm i -g @nestjs/cli
$ nest new server   # choose npm when asked
$ cd server && npm run start:dev   # → http://localhost:3000

Nest gives you controllers, services, and modules out of the box. Generate the feature modules you'll fill in later:

server/
$ nest g resource auth
$ nest g resource products
# pick "REST API" and "Yes" to generate CRUD entry points
Port note
Nest defaults to port 3000, which clashes with Next.js. Change Nest to 5000 in main.ts (await app.listen(5000)) so both can run together (and align with the port used by our frontend proxy).
04 — PACKAGES

Install the Core Packages

These power authentication, validation, email, and database access. Run inside server/.

Shared by every stack

server/
# For Express:
$ npm install bcryptjs jsonwebtoken express-validator nodemailer
$ npm install -D @types/bcryptjs @types/jsonwebtoken @types/nodemailer

# For NestJS (uses class-validator + bcrypt):
$ npm install bcrypt nodemailer
$ npm install -D @types/bcrypt @types/nodemailer
  • bcryptjs — hash passwords safely.
  • jsonwebtoken — sign/verify JWTs (login + email-verify tokens).
  • express-validator — validate incoming request bodies (Express); NestJS uses class-validator via DTOs.
  • nodemailer — send verification & low-stock emails over SMTP.

Database driver — pick one

Postgres uses TypeORM; MongoDB uses Mongoose. We install the full setup on the next page; the packages are:

Express → TypeORM
$ npm install typeorm pg  # PostgreSQL + TypeORM (skip if using MongoDB)
NestJS → TypeORM
$ npm install @nestjs/typeorm typeorm pg
$ npm install @nestjs/config @nestjs/jwt @nestjs/passport passport passport-jwt class-validator class-transformer
$ npm install -D @types/passport-jwt
TypeScript & Decorators (NestJS only)
NestJS is built on TypeScript and uses decorators. For JavaScript + Express, we define our database schemas using standard EntitySchema definitions, which require no decorator configuration or build pipeline.
05 — CONFIG

Environment Variables

Secrets (DB password, JWT secret, SMTP login) never go in code. Put them in a .env file in server/ and add .env to .gitignore.

server/.env
PORT=5000
MONGODB_URI=mongodb+srv://<user>:<password>@cluster.mongodb.net/inventory?retryWrites=true&w=majority
JWT_SECRET=your_super_secret_jwt_key_minimum_32_characters
JWT_EXPIRES_IN=7d

# Mailtrap SMTP (get from mailtrap.io → Email Testing → SMTP Settings)
EMAIL_HOST=sandbox.smtp.mailtrap.io
EMAIL_PORT=2525
EMAIL_USER=your_mailtrap_user
EMAIL_PASS=your_mailtrap_pass
EMAIL_FROM="Inventory Express <noreply@inventoryexpress.com>"

CLIENT_URL=http://localhost:5173
STORE_OWNER_EMAIL=your@email.com
Never commit secrets
Create a .gitignore with node_modules and .env in it. Commit a .env.example (same keys, blank values) so teammates know what to fill in.
06 — CHECKPOINT

Run Both Dev Servers

Open two bash terminals. Frontend in one, backend in the other.

bash
# terminal 1 — frontend (http://localhost:5173)
$ cd web && npm run dev

# terminal 2 — backend (http://localhost:5000)
$ cd server && npm run dev
  • Frontend loads at http://localhost:5173
  • Backend responds at http://localhost:5000/api/health with {"status":"ok"}
  • All core packages installed without errors
  • .env created in server/ and git-ignored