A production-ready monorepo starter for building enterprise web applications with headless CMS integration. Built with Next.js 14, TypeScript, Material-UI, and supports both Sanity and Contentful CMS (or file system for local development).
- Dual CMS Support: Works seamlessly with Sanity or Contentful (or neither for local dev)
- Next.js 14: Latest Next.js with App Router and React Server Components
- TypeScript: Full type safety across the entire monorepo
- Material-UI: Pre-built component library with theming
- GraphQL Layer: Unified GraphQL API that works with any CMS
- Monorepo: Turbo-powered workspace for efficient development
- Storybook: Component development and documentation
- Cypress: E2E and component testing
- BWS Secure: Secure environment variable management via Bitwarden
Ensure you have the following installed:
- Node.js 22.x (Download)
- pnpm 9.x (Installation Guide)
- Git (Download)
This is a Turborepo monorepo containing:
-
apps/web- Main Next.js application- API routes for GraphQL, preview, and webhooks
- Middleware for CSP headers and security
- Server and client components
-
apps/sanity-studio- Sanity CMS Studio- Custom schemas and document types
- Internationalization support
- Preview integration
-
packages/ui- React component library- 40+ reusable components
- Material-UI integration
- Storybook stories
- Cypress component tests
-
packages/graphql-sdk- GraphQL client and schema- Auto-generated TypeScript types
- GraphQL queries and mutations
- CMS-agnostic data layer
-
packages/graphql-extensions- Custom GraphQL resolvers- Field-level transformations
- CMS-specific logic
- Content type extensions
-
packages/eslint-config-custom- Shared ESLint configuration -
packages/tsconfig- Shared TypeScript configurations -
packages/jest-presets- Shared Jest configurations
git clone https://github.com/last-rev-llc/lastrev-starter-v2.git your-project-name
cd your-project-nameEnsure you're using the correct Node.js version:
nvm use # Uses .nvmrc fileThen install dependencies:
pnpm installThis project uses BWS Secure (Bitwarden Secrets Manager) for environment variable management. See the BWS Secure documentation section (managed by bws-update) for detailed setup instructions.
The starter supports both Sanity and Contentful (or neither for local development). The build process automatically detects which CMS you're using based on environment variables.
Set these environment variables (via BWS Secure or .env):
SANITY_STUDIO_SANITY_PROJECT_ID=your_project_id
SANITY_STUDIO_SANITY_DATASET=production
SANITY_STUDIO_SANITY_API_VERSION=2024-01-01
SANITY_TOKEN=your_sanity_token
USE_PREVIEW=false # Set to 'true' for preview modeSet these environment variables:
CONTENTFUL_SPACE_ID=your_space_id
CONTENTFUL_ENV=master
CONTENTFUL_DELIVERY_TOKEN=your_delivery_token
CONTENTFUL_PREVIEW_TOKEN=your_preview_token
CONTENTFUL_USE_PREVIEW=false # Set to 'true' for preview modeIf no CMS environment variables are set, the starter will use file system strategy for local development. This is useful for:
- Initial setup and development
- Testing without CMS access
- CI/CD environments without CMS credentials
If using a CMS, sync content from your CMS:
pnpm sync:cmsThis command:
- Detects which CMS you're using automatically
- Syncs content to
.cms-syncdirectory - Works with both Sanity and Contentful
- Gracefully handles missing CMS credentials
Start the development server:
pnpm devThis will:
- Start the Next.js app on
http://localhost:3000 - Start the GraphQL server on
http://localhost:8888 - Sync CMS content automatically
- Watch for changes and hot reload
For GraphQL development with auto-reload:
pnpm gql:devpnpm dev # Start all services (Next.js + GraphQL)
pnpm gql:dev # Start GraphQL server with CMS sync and watch mode
pnpm gql:start # Start GraphQL server only
pnpm gql:logs # View GraphQL server logs
pnpm sync:cms # Sync content from CMSpnpm build # Production build all packages
pnpm lint # Lint all packages
pnpm test # Run all tests
pnpm format # Format code with Prettier
pnpm clean # Clean all build artifactspnpm storybook # Start Storybook dev server (port 6006)
pnpm build-storybook # Build Storybook for deployment
pnpm cypress:open:ui # Open Cypress for UI component tests
pnpm cypress:open:web # Open Cypress for web E2E testspnpm sanity-studio-deploy # Deploy Sanity studio
pnpm sanity-contentful-export # Export from Contentful to Sanity
pnpm sanity-create-schema # Generate Sanity schemas
pnpm sanity-create-dataset # Create Sanity dataset
pnpm sanity-dataset-import # Import data into SanityPackages are linked using pnpm workspaces:
webdepends onui,graphql-sdk,graphql-extensionsgraphql-sdkdepends ongraphql-extensions- All packages share
eslint-config-customandtsconfig
The build process uses Turborepo for efficient caching:
- Dependencies: Builds packages in dependency order
- CMS Sync: Syncs content from CMS (if configured)
- GraphQL SDK: Generates TypeScript types from GraphQL schema
- Web App: Builds Next.js application
- Schema: Auto-generated from CMS schemas
- Client: Type-safe GraphQL client with generated hooks
- Resolvers: Custom field-level resolvers in
graphql-extensions - Server: Runs on
localhost:8888during development
The starter is configured for Netlify deployment:
- Connect Repository: Link your GitHub repository to Netlify
- Build Settings:
- Build command:
pnpm build - Publish directory:
apps/web/.next
- Build command:
- Environment Variables: Configure environment variables in Netlify (BWS Secure can sync these automatically)
- Build Hooks: Configure webhooks in your CMS to trigger builds
Required environment variables:
| Variable | Description | Required |
|---|---|---|
SITE |
Site identifier for the project | Yes |
DOMAIN |
Base URL for the environment | Yes |
DEFAULT_SITE_ID |
Default site ID | Yes |
SITE_SETTINGS |
Site settings ID | Yes |
| Variable | Description | Required |
|---|---|---|
SANITY_STUDIO_SANITY_PROJECT_ID |
Sanity project ID | If using Sanity |
SANITY_STUDIO_SANITY_DATASET |
Sanity dataset name | If using Sanity |
SANITY_STUDIO_SANITY_API_VERSION |
Sanity API version | If using Sanity |
SANITY_TOKEN |
Sanity API token | If using Sanity |
USE_PREVIEW |
Enable preview mode (true/false) |
Optional |
| Variable | Description | Required |
|---|---|---|
CONTENTFUL_SPACE_ID |
Contentful space ID | If using Contentful |
CONTENTFUL_ENV |
Contentful environment | If using Contentful |
CONTENTFUL_DELIVERY_TOKEN |
Contentful delivery token | If using Contentful |
CONTENTFUL_PREVIEW_TOKEN |
Contentful preview token | If using Contentful |
CONTENTFUL_USE_PREVIEW |
Enable preview mode (true/false) |
Optional |
| Variable | Description |
|---|---|
NEXT_PUBLIC_GTM_ID |
Google Tag Manager ID |
NEXT_PUBLIC_SENTRY_DSN |
Sentry DSN for error tracking |
REDIS_HOST |
Redis host for caching |
REDIS_PASSWORD |
Redis password |
REDIS_PORT |
Redis port |
GRAPHQL_RUNNER_STRATEGY |
GraphQL runner strategy (fs or cms) |
GRAPHQL_SERVER_TIMEOUT |
GraphQL server timeout |
pnpm test # Run all tests
pnpm test:watch # Run tests in watch modepnpm cypress:open:web # Open Cypress for E2E tests
pnpm cypress:regenerate-pages # Regenerate test page fixturespnpm cypress:open:ui # Open Cypress for component tests- Create component in
packages/ui/src/ - Add Storybook story in
packages/ui/stories/ - Export from
packages/ui/src/index.ts - Use in
apps/webvia@repo/uiimport
- Update CMS schema (Sanity or Contentful)
- Run
pnpm sync:cmsto sync changes - GraphQL schema auto-regenerates
- TypeScript types auto-update
- Preview Mode: Set
USE_PREVIEW=trueorCONTENTFUL_USE_PREVIEW=true - Content Sync: Run
pnpm sync:cmsafter content changes - GraphQL Queries: Use generated hooks from
@repo/graphql-sdk
- CLAUDE.md - AI assistant context for this repository
- SANITY_NOTES.md - Sanity-specific setup notes
- Turbo Documentation
- Next.js Documentation
- Material-UI Documentation
- Create a feature branch from
main - Make your changes
- Run
pnpm lintandpnpm test - Submit a pull request
See LICENSE file for details.
Issue: Build fails with "Environment variable X is required"
Solution:
- Check that required CMS variables are set
- The starter will use file system strategy if no CMS vars are present
Issue: GraphQL server connection errors during build
Solution:
- This is normal - builds don't require a running GraphQL server
- The build process uses serverless config automatically
Issue: sync:cms fails with missing variables
Solution:
- Check that your CMS environment variables are set correctly
- The sync will use file system strategy if no CMS vars are present
- Verify your CMS credentials are valid
Issue: Port already in use
Solution:
- Next.js: Change port with
PORT=3001 pnpm dev - GraphQL: Port is configured in
packages/graphql-sdk/config.js
Issue: Environment variables not loading
Solution:
- Check that environment variables are set correctly
- Verify BWS Secure configuration (see BWS Secure documentation section)
- Use
pnpminstead ofnpmoryarnfor consistency - Run
pnpm formatbefore committing - Check Storybook for component examples and props
- Use TypeScript for type safety - the entire codebase is typed
- GraphQL queries are auto-generated - don't edit
packages/graphql-sdk/src/generated/manually
Need help? Check the CLAUDE.md file for AI assistant context, or open an issue on GitHub.
This project uses BWS Secure for managing environment variables across different environments.
π 1. Visit the Bitwarden Machine Accounts section within your Vault.
- If you login directly to https://vault.bitwarden.com, you will need to navigate to the Machine Accounts section, within the Secrets Manager. The Secrets Manager is located in the left sidebar, typically at the bottom of the page.
- If you don't have access, please refer to the BWS Secure documentation or contact your team administrator
π±οΈ 2. Navigate to the Machine Accounts section, and follow these steps:
- Select the appropriate Client/Set of Machine Accounts from the list
- Click on the "Access Tokens" tab
- Click "+ New Access Token" button
- Give the token a meaningful name (e.g., "Your Name - Local Development")
- Click "Save" to generate the token
π 3. Copy the displayed token (you won't be able to see it again after closing)
πΎ 4. Add it to your .env file in your project root:
BWS_ACCESS_TOKEN=your_token_here
- BWS_ACCESS_TOKEN: Loads ALL projects associated with that token (recommended for multi-project setups)
- BWS_PROJECT_ID: Loads only a specific project (use for single-project or testing scenarios)
Example for single project:
BWS_PROJECT_ID=00000000-0000-0000-0000-000000000001
The project ID can be found in the Bitwarden Secrets Manager, within the list of projects.
- "No projects found": Verify your token has project access permissions in Bitwarden
- "Access denied": Check that the Machine Account has read permissions for the target projects
- Token not working: Ensure no extra spaces when copying from Bitwarden
- Multiple projects loading: This is normal with BWS_ACCESS_TOKEN - use BWS_PROJECT_ID for single project
To update BWS Secure to the latest version, you can use the convenient script that was added to your package.json:
npm run bws-update # Or use your project's package manager: yarn bws-update, pnpm bws-updateAlternatively, you can run the following command manually from your project root:
rm -rf scripts/bws-secure && git clone git@github.com:last-rev-llc/bws-secure.git scripts/bws-secure && rm -rf scripts/bws-secure/.git && bash scripts/bws-secure/install.sh