This is a starter application using NextJS and Convex, managed with NX for monorepo capabilities.
- Node.js 22 or later
- pnpm package manager
- Convex account - Register at https://www.convex.dev/
-
Run
pnpm installto install the dependencies -
Run
pnpm run setupto initialize the Convex backend and configure the webappThis script will:
- Check and update branding - Detects if you're using template branding and prompts you to customize:
- Application name and short name
- App description
- Landing page title
- Package name
- Initialize the Convex backend using
npx convex dev --once - Extract the CONVEX_URL from the backend's .env.local file
- Create/update the webapp's .env.local file with the NEXT_PUBLIC_CONVEX_URL
The setup script is idempotent - you can run it multiple times safely. It will:
- Show ✅ CONFIGURED for branding that's already customized
- Show
⚠️ TEMPLATE for branding that still uses default values - Only prompt for updates if template values are detected
Non-Interactive Mode: For CI/CD or automated setups:
node scripts/setup.js --non-interactive \ --app-name "My App" \ --app-short-name "MyApp" \ --app-description "Description" \ --landing-page-title "Welcome" \ --package-name "my-app" # Or skip branding entirely node scripts/setup.js --skip-branding # Show all options node scripts/setup.js --help
- Check and update branding - Detects if you're using template branding and prompts you to customize:
-
Run
pnpm devin the root directory to start the NextJS application and Convex backend
If you prefer to set up manually:
- Go to
services/backendand runnpx convex dev --once- this should prompt you to login to Convex and create a new project. Note: This will create a .env.local file with the CONVEX_URL environment variable. - Create a
.env.localfile in theapps/webappdirectory and add the following:NEXT_PUBLIC_CONVEX_URL=<your-convex-project-url> # copy this from the backend .env.local file
- Run
pnpm devin the root directory to start both services
To create a system administrator:
- Login anonymously via the login page
- Set admin privileges in Convex Dashboard:
- Go to Data >
userstable - Find your user record and set
accessLevelto"system_admin"
- Go to Data >
- Access admin dashboard by clicking your username → "System Admin"
System admins can configure Google OAuth, manage authentication providers, and access system settings.
To enable Google OAuth authentication:
- Configure Google OAuth in your app's admin dashboard:
- Login with your system admin account
- Go to your username → "System Admin" → "Google Auth Config"
- Follow the instructions to set up Google OAuth credentials
- Transfer admin role to Google account (Recommended):
- After Google Auth is configured, sign in with your Google account
- In Convex Dashboard, go to Data >
userstable - Find your Google account user record and set
accessLevelto"system_admin" - Remove the
system_adminaccess level from the temporary anonymous account
This ensures your system admin access is tied to a verified Google account for better security.
apps/webapp: The frontend NextJS applicationservices/backend: The Convex backend service
To run both the frontend and backend in parallel:
pnpm run devThis will start:
- The webapp at http://localhost:3000
- The Convex backend development server
This project uses Vitest for testing across both frontend and backend.
Run all tests:
pnpm testRun tests in watch mode:
pnpm test:watchFor comprehensive testing guidelines, conventions, and examples, see the Testing Guide.
This project uses NX to manage the monorepo and run tasks in parallel. The main configuration files are:
nx.json: Main NX configurationapps/webapp/project.json: Webapp project configurationservices/backend/project.json: Backend project configuration
The dev command is configured to run both services in parallel without dependencies between them, allowing for independent development.
To add a new project to the monorepo:
- Create the project in the appropriate directory (
apps/orservices/) - Add a
project.jsonfile to define the project's targets - Update the root
package.jsonto include the new project in the dev command if needed
To deploy your Convex backend to production:
-
Generate a deployment key from the Convex dashboard:
- Go to your project in the Convex dashboard
- Navigate to Settings > URL & Deploy Key
- Create a new deployment key
-
Add the deployment key to GitHub Secrets:
- Go to your GitHub repository
- Navigate to Settings > Secrets and variables > Actions
- Click "New repository secret"
- Name:
CONVEX_DEPLOY_KEY_PROD - Value: Your deployment key from the Convex dashboard
-
The GitHub Action workflow included in this template will handle deployment of your Convex backend automatically when you push to the main branch.
This setup allows for secure automated deployments of your Convex functions and schema without exposing your credentials.
To deploy your NextJS frontend to Vercel:
-
Navigate to your Convex dashboard:
- Go to Convex dashboard
- Navigate to Settings > URL & Deploy Key
- Copy the Deployment URL
-
Set up the Vercel deployment
- Go to the Vercel dashboard
- Navigate to Project Settings > Build and Deployment > Root Directory
- Set the Root Directory to
apps/webapp
- Set the Root Directory to
- Navigate to Project Settings > Environment Variables
- Add a new variable:
- Name:
NEXT_PUBLIC_CONVEX_URL - Value: Paste the Deployment URL you copied from Convex
-
Deploy your NextJS application to Vercel as usual.
Convex is chosen as the backend service for the following reasons:
-
Simplicity of code generation and architecture
Convex follows a reactive paradigm that allows reactive queries from the client to cause automatic re-renders when a dataset has been updated. This significantly reduces complexity and amount of code required, while solving the problem of cache invalidation.
Simple and less code required for a feature also means fewer chances for AI generated code to be incorrect.
-
Transactionality and consistency
All convex mutations run "inside" of the database. Any error thrown in the mutation will result in an automatic rollback. This ensures that we are able to use a single language for both querying data and business logic, while maintaining transactionality.
-
Simple end to end reactivity
Many platforms offer subscription to DB events (e.g. firebase, supabase). However, it still leaves a significant amount of code to transform the event into the actual state for your application. Convex solves this by simply providing the full state for the query's data, and does a re-render of that state when the data has been updated.
-
Single language for frontend and backend