A modern starter template that gives you a solid baseplate to build your next fullstack project.
Everything is already wired together, tested, linted, and production-ready — you just start snapping on your features.
React 19 + Vite + TypeScript + MUI
Node + Express 5 + Apollo Server + MongoDB
All running inside Yarn v4 Workspaces, fully typed, fully tested.
- ⚡️ Vite (ultra-fast dev server)
- ⚛️ React 19 + TypeScript
- 🎨 MUI (theme system + Roboto fonts)
- 🔗 React Router
- 🔮 Apollo Client
- 🧪 Vitest + Testing Library
- 🔧 Clean import aliases (
components/*,pages/*,theme/*,src/*) - 🧩 Working Todo example using real GraphQL
- 🟢 Node.js + Express 5
- 🧬 Apollo Server (GraphQL)
- 🗃️ MongoDB integration
- 🧩 Modular GraphQL design (feature-based modules)
- 🧪 Vitest resolver tests (mocked db/context)
- 🛠 Built with tsup for reliable production builds
- 🧶 Yarn v4 workspaces
- 📏 ESLint 9 (flat config)
- ✨ Prettier formatting
- 🌈 Colored logs for dev mode
- 🏗 Production mode with Express serving the built client
KS Baseplate uses a feature-branch system to keep the main template clean while offering optional integrations you can explore or merge into your own project.
Every feature branch is self-contained and built on top of the main template.
| Branch | Description |
|---|---|
| main | The core KS Baseplate template — clean, minimal, and production-ready. No authentication or optional integrations included. |
| Branch | Status | Description |
|---|---|---|
| feature/auth0 | snapped-on | Adds full authentication/authorization using Auth0 (React SDK + JWT-protected GraphQL API). |
| (future branches) | organizing bricks | Additional integrations (Prisma, Stripe, file uploads, RBAC, etc.) may be added over time. |
git checkout feature/auth0npx degit kamoteshake/KS-Baseplate#feature/auth0 my-appgit merge origin/feature/auth0This system keeps main simple and extensible while allowing developers to use pre-built feature integrations as needed.
Use degit to copy the template without cloning or keeping Git history:
npx degit https://github.com/kamoteshake/KS-Baseplate#main my-new-appThis will:
- Copy the KS Baseplate template
- Remove all Git History
- Create a new folder called
my-new-app
Then move into it:
cd my-new-appyarnyarn devThis starts:
- 🟩 Client → http://localhost:5173
- 🟦 Server → http://localhost:4000
Both with live reload.
git init
git add .
git commit -m "Initial commit"yarn test # Run tests (client + server)
yarn lint # Lint everything
yarn format # Format with Prettier
yarn build # Build client + server for production
yarn start # Start production server.
├── client/ # React + Vite app
│ ├── src/
│ │ ├── apollo/ # Apollo Client (main branch)
│ │ │ ├── client.ts # ApolloClient setup (uses VITE_GRAPHQL_URL)
│ │ │ └── ApolloAppProvider.tsx
│ │ ├── components/
│ │ │ └── TodoSection/
│ │ ├── pages/
│ │ │ └── Home/
│ │ ├── theme/
│ │ ├── router.tsx
│ │ ├── App.tsx
│ │ └── main.tsx
│ └── vite.config.ts
│
├── server/ # Node + Express + GraphQL
│ ├── src/
│ │ ├── config.ts
│ │ ├── db.ts
│ │ ├── graphql/
│ │ │ ├── context.ts
│ │ │ ├── schema.ts
│ │ │ ├── resolvers.ts
│ │ │ └── modules/
│ │ │ ├── hello/
│ │ │ ├── health/
│ │ │ └── todos/
│ │ └── index.ts
│ └── tsup.config.ts
│
├── eslint.config.cjs
├── .prettierrc
├── package.json
└── yarn.lockA clear foundation built for easy expansion.
This template uses workspace-specific .env files.
PORT=4000
MONGO_URI=mongodb://localhost:27017/ks_baseplateVITE_GRAPHQL_URL=http://localhost:4000/graphqlThis value is compiled into the frontend at build time, so it must match your deployment strategy.
VITE_GRAPHQL_URL=http://localhost:4000/graphqlVITE_GRAPHQL_URL=/graphqlThis tells the client to call:
https://yourdomain.com/graphql
VITE_GRAPHQL_URL=https://api.yourdomain.com/graphqlExample env templates are provided at:
server/.env.example
client/.env.exampleIf you update the server PORT, be sure to also update:
VITE_GRAPHQL_URL(in the client.env)- the
dev:clientwait-on URL in the rootpackage.json
This ensures the client waits for the correct server during yarn dev.
Import components cleanly:
import { TodoSection } from 'components/TodoSection';
import { Home } from 'pages/Home';
import { AppThemeProvider } from 'theme/ThemeProvider';
import { helper } from 'src/utils/helpers';Aliases supported:
components/*pages/*theme/*src/*
(Server intentionally keeps relative imports.)
GraphQL code lives in:
server/src/graphql/Each feature module contains:
modules/<feature>/
typeDefs.ts
resolvers.ts
Included modules:
hellohealthtodos(MongoDB-backed example)
Modules are combined through:
schema.tsresolvers.ts
Add new features simply by adding a module folder.
Powered by Vitest + Testing Library:
yarn workspace client testMocked resolver tests via Vitest:
yarn workspace server testRun everything:
yarn testBuild both client and server:
yarn buildStart the production server:
yarn startThis runs:
- 🟩 Client → built by Vite into
client/dist - 🟦 Server → built by tsup into
server/dist
Express serves:
- The built React app at
/ - The GraphQL API at
/graphql
The client uses the environment variable VITE_GRAPHQL_URL, which must be set before building.
For shared-domain deployments (recommended):
VITE_GRAPHQL_URL=/graphqlFor separate-domain deployments:
VITE_GRAPHQL_URL=https://api.yourdomain.com/graphqlRefer to the Environment Variables section for more details.
Only needed if your client and server will live on different domains or ports
By Default, Express server serves both the React app and the GraphQL API from the same origin:
https://yourdomain.com/ → Client
https://yourdomain.com/graphql → Server
This means CORS is not required out of the box.
If you separate your deployments (e.g. Vercel for client + VPS for server), add this to:
server/src/index.tsimport cors from "cors";
app.use(
cors({
origin: "https://your-frontend-domain.com",
credentials: true,
})
);Multiple allowed origins:
app.use(
cors({
origin: [
"https://app.example.com",
"https://admin.example.com",
"http://localhost:5173"
],
credentials: true,
})
);MIT License — free to use, modify, and adapt.
Contributions, ideas, improvements, or feature requests are welcome! Feel free to open an issue or submit a PR.