Please Note this project is currently in development and still has some rough edges. Use at your own risk.
A production-ready monorepo combining a TanStackReact frontend with Sanity Studio, powered by Turborepo.
This project is a custom fork of the original Santan Monorepo, which can be found here.
- Overview
- Quick Start
- Project Structure
- Development
- Production
- Type Generation
- Available Commands
- Documentation
- Troubleshooting
This monorepo combines a React frontend and Sanity Studio into a single, optimized workspace with:
✅ Shared type system - Auto-generated Sanity types used across both apps
✅ Turborepo caching - Lightning-fast builds with intelligent caching
✅ Production-ready - Properly configured for deployment
✅ Type-safe - Full TypeScript support throughout
✅ Hot reloading - Fast development experience
Frontend (apps/frontend)
- React 19
- TanStack Router & Query
- Vite 7
- Sanity Client
- Tailwind CSS
Studio (apps/studio)
- Sanity Studio 5
- Custom schema types
- Document preview
Shared (packages/shared)
- Auto-generated Sanity types
- Shared utilities
- Type-safe enums
- Node.js ≥ 24
- npm (comes with Node.js)
- Sanity account with a configured project
cd /path/to/santan-monorepo
npm installFrontend:
cp apps/frontend/.env.example apps/frontend/.env.localEdit apps/frontend/.env.local:
VITE_SANITY_PROJECT_ID=your_project_id
VITE_SANITY_DATASET=production
VITE_SANITY_API_VERSION=2024-01-01
SESSION_SECRET=generate_a_random_secret_hereStudio:
cp apps/studio/.env.example apps/studio/.env.localEdit apps/studio/.env.local:
SANITY_STUDIO_PROJECT_ID=your_project_id
SANITY_STUDIO_DATASET=productionnpm run devThis starts:
- 🌐 Frontend at http://localhost:3000
- 🎨 Studio at http://localhost:3333
- 🔧 Shared package in watch mode (auto-recompiles on changes)
santan-monorepo/
├── apps/
│ ├── frontend/ # React frontend
│ │ ├── src/
│ │ │ ├── routes/ # TanStack Router routes
│ │ │ ├── components/ # React components
│ │ │ ├── sanity/ # Sanity queries and loaders
│ │ │ └── types/ # Frontend-specific types
│ │ ├── .env.local # Environment variables (not in git)
│ │ └── package.json # @santan/frontend
│ │
│ └── studio/ # Sanity Studio
│ ├── src/
│ │ ├── schemaTypes/ # Content schemas
│ │ ├── structure/ # Studio structure
│ │ └── scripts/ # Type generation scripts
│ ├── .env.local # Environment variables (not in git)
│ └── package.json # @santan/studio
│
├── packages/
│ └── shared/ # Shared package (auto-generated types)
│ ├── src/
│ │ ├── types/
│ │ │ ├── sanity.types.ts # Generated Sanity types
│ │ │ └── sanityTypeLiterals.ts # Type literal enums
│ │ └── index.ts # Main export
│ ├── dist/ # Compiled output (generated)
│ └── package.json # @santan/shared
│
├── turbo.json # Turborepo configuration
├── package.json # Root package with workspaces
├── README.md # This file
└── docs/
├── TYPE_MIGRATION.md # Type generation guide
└── PRODUCTION_READY.md # Production deployment guide
npm run devStarts all workspaces with hot reloading:
- Frontend dev server
- Studio dev server
- Shared package in watch mode (auto-rebuilds on changes)
# Frontend only
npm run dev --workspace=@santan/frontend
# Studio only
npm run dev --workspace=@santan/studio
# Shared package only (watch mode)
npm run dev --workspace=@santan/sharedThe @santan/shared package contains auto-generated Sanity types:
// Import in Frontend or Studio
import {
Post,
Category,
Author,
sanityTypeLiterals,
} from "@santan/shared/types";
// Type-safe document checking
if (doc._type === sanityTypeLiterals.post) {
// TypeScript knows doc is Post type
console.log(doc.title, doc.slug);
}npm run buildThis builds all packages in the correct order:
- Shared package → Compiles TypeScript to JavaScript
- Studio → Builds Sanity Studio (using shared types)
- Frontend → Builds React app (using shared types)
- Frontend:
apps/frontend/.output/(Nitro/Vite output) - Studio:
apps/studio/dist/(Sanity Studio build) - Shared:
packages/shared/dist/(Compiled types)
Frontend (Vercel/Netlify):
- Root directory:
apps/frontend - Build command:
npm run build - Output directory:
apps/frontend/.outputorapps/frontend/dist
Studio (Sanity):
cd apps/studio
npm run deployOr from root:
npm run deploy --workspace=@santan/studioSee packages/shared/PRODUCTION_READY.md for complete deployment guide.
Run type generation whenever you:
- Add a new document type in Sanity Studio
- Modify existing schemas
- Change field definitions
- Update portable text configurations
cd apps/studio
npm run generate-typesWhat this does:
- Extracts Sanity schema →
schema.json - Generates TypeScript types →
packages/shared/src/types/sanity.types.ts - Extracts type literals →
packages/shared/src/types/sanityTypeLiterals.ts
The shared package automatically rebuilds (if dev mode is running), making types instantly available to both Frontend and Studio.
See TYPE_MIGRATION.md for detailed type generation workflow.
| Command | Description |
|---|---|
npm run dev |
Start all apps in development mode |
npm run build |
Build all apps for production |
npm run type-check |
Type check all packages |
npm run lint |
Lint all packages |
npm run format |
Format code with Prettier |
npm run clean |
Clean build artifacts |
Run commands in specific packages:
# Pattern
npm run <command> --workspace=@santan/<package>
# Examples
npm run dev --workspace=@santan/frontend
npm run build --workspace=@santan/studio
npm run type-check --workspace=@santan/shared- TYPE_MIGRATION.md - Complete type generation and migration guide
- packages/shared/TYPES_README.md - Detailed shared package documentation
- packages/shared/PRODUCTION_READY.md - Production deployment guide
- GETTING_STARTED.md - Detailed setup instructions
- docs/FULLSLUG_SYSTEM.md - Sanity fullSlug system for hierarchical URLs
- docs/INDEX.md - Complete documentation index
If ports 3000 or 3333 are in use:
# Kill processes on specific ports
lsof -ti:3000 | xargs kill -9
lsof -ti:3333 | xargs kill -9
# Or kill all dev servers
pkill -f "npm run dev"Check your .env.local files:
- ✅
VITE_SANITY_PROJECT_IDmatches your Sanity project - ✅
VITE_SANITY_DATASETis correct (usually "production") - ✅
VITE_SANITY_API_VERSIONis valid
-
Regenerate types:
cd apps/studio npm run generate-types -
If dev mode is running, shared package should auto-rebuild
-
Otherwise, manually build:
cd packages/shared npm run build -
Restart TypeScript server in your IDE:
- VS Code:
CMD+Shift+P→ "TypeScript: Restart TS Server" - WebStorm: Should auto-reload
- VS Code:
Ensure dependencies are installed:
npm installIf issues persist, clean and reinstall:
npm run clean
rm -rf node_modules apps/*/node_modules packages/*/node_modules
npm installEnsure the shared package is built before other packages:
cd packages/shared && npm run build
cd ../..
npm run buildTurborepo should handle this automatically with the ^build dependency.
✅ Single clone - Get frontend and studio together
✅ Shared types - Auto-generated, always in sync
✅ Fast builds - Turborepo caches everything
✅ Hot reloading - Changes reflect immediately
✅ Type safety - Full TypeScript support
✅ Optimized builds - Only rebuild what changed
✅ Type-safe deployments - Compile-time type checking
✅ Atomic commits - Change frontend and studio together
✅ Single source of truth - One repo, one package.json
✅ Easier onboarding - Clone once, everything works
✅ Consistent tooling - Same linting, formatting, testing
✅ Simplified CI/CD - One pipeline for everything
✅ Better collaboration - See all changes in one place
- Turborepo: https://turbo.build/repo/docs
- Sanity: https://www.sanity.io/docs
- TanStack Router: https://tanstack.com/router
- Vite: https://vitejs.dev
MIT
Status: ✅ Production Ready
Last Updated: October 30, 2025