A full-stack monorepo template project, built with npm workspaces.
frontend/- React frontend with Vite, TypeScript, Tailwind CSS, and React Querybackend/- Node.js backend with Express and TypeScriptshared/- Shared TypeScript package for types and constants
- Node.js 18+ and npm
npm installThis will install dependencies for all workspaces.
Start all packages (shared, backend, and frontend) concurrently:
npm run devThis will:
- Build the shared package first
- Start all packages in watch mode
Or start them individually:
# Shared package (builds and watches for changes)
npm run dev --workspace=shared
# Backend only
npm run dev --workspace=backend
# Frontend only
npm run dev --workspace=frontendCreate frontend/.env:
VITE_API_BASE_URL=http://localhost:3001Create backend/.env:
PORT=3001Build all packages:
npm run buildBuild individual packages:
npm run build --workspace=shared
npm run build --workspace=backend
npm run build --workspace=frontend@fullstackplain/shared- Shared types and constants@fullstackplain/backend- Express API server@fullstackplain/frontend- React application
The project uses a feature-based folder structure:
backend/src/
├── features/
│ └── greet/
│ ├── __tests__/
│ │ └── greet.service.test.ts # Unit tests
│ ├── greet.controller.ts # HTTP request/response handling
│ ├── greet.service.ts # Business logic
│ └── greet.routes.ts # Route definitions
├── __tests__/
│ └── index.test.ts # Integration tests
├── app.ts # Express app factory
└── index.ts # Server entry point
frontend/src/
├── api/
│ ├── __tests__/
│ │ └── api.test.ts # API helper tests
│ └── api.ts # Global API helper functions
├── features/
│ └── greet/
│ ├── __tests__/
│ │ └── GreetPage.test.tsx # Unit tests
│ └── GreetPage.tsx # Feature page component
├── __tests__/
│ ├── integration/ # Integration tests
│ └── e2e/ # E2E tests
├── App.tsx # Main app with routing
└── main.tsx # Entry point
The frontend uses a structured test organization:
-
Unit Tests: Located within each feature folder at
src/features/{feature}/__tests__/- Test individual components and functions in isolation
- Example:
src/features/greet/__tests__/GreetPage.test.tsx
-
Integration Tests: Located at
src/__tests__/integration/- Test multiple features/components working together
- Example:
src/__tests__/integration/example.integration.test.tsx
-
E2E Tests: Located at
src/__tests__/e2e/- Test complete user flows across the entire application
- Example:
src/__tests__/e2e/example.e2e.test.tsx
Run tests:
# Run all tests
npm run test --workspace=frontend
# Run tests in watch mode
npm run test:watch --workspace=frontend
# Run tests with coverage
npm run test:coverage --workspace=frontendThe backend uses a structured test organization:
-
Unit Tests: Located within each feature folder at
src/features/{feature}/__tests__/- Test individual services and functions in isolation
- Example:
src/features/greet/__tests__/greet.service.test.ts
-
Integration Tests: Located at
src/__tests__/- Test API routes and full request/response flow
- Example:
src/__tests__/index.test.ts
Run tests:
# Run all tests
npm run test --workspace=backend
# Run tests in watch mode
npm run test:watch --workspace=backend
# Run tests with coverage
npm run test:coverage --workspace=backendGET /api/v1/greet
→ Returns: { greeting: "Hello." }
→ Description: Returns a greeting message
GET /health
→ Returns: { status: "ok" }
→ Description: Health check endpoint
- Framework: React 18
- Build Tool: Vite
- Routing: React Router DOM
- Data Fetching: React Query (TanStack Query)
- Styling: Tailwind CSS
- Testing: Jest + React Testing Library
- Language: TypeScript
- Framework: Express.js
- Runtime: Node.js
- Testing: Jest + Supertest
- Language: TypeScript
- Type Definitions: TypeScript interfaces
- Exports: GreetingResponse type, API_VERSION
- Package Manager: npm workspaces
- Linting: ESLint
- Formatting: Prettier
- Git Hooks: Husky + lint-staged
- Type Checking: TypeScript
The project includes pre-commit hooks that run:
- Lint-staged (formatting and linting)
- Build shared package
- Run all tests
Make sure all tests pass and code is properly formatted before committing.