This guide provides detailed instructions for setting up the codexcrmapp monorepo, configuring authentication and database access, implementing the first feature (Clients), and adding basic tests. Follow these steps sequentially.
Phase 0: Prerequisites & Initial Setup
Make sure you have the necessary tools installed and your current code is saved.
Check System Tools:
Goal: Ensure your development machine has Node.js, pnpm, and the Supabase CLI installed.
Action: Open your terminal and run the following commands to check versions. If any are missing, install them.
node -v
pnpm -v # If missing: npm install -g pnpm
supabase -v # If missing: npm install -g supabase
Log in to Supabase CLI: Ensure you're authenticated with Supabase.
supabase login
Commit Current Code:
Goal: Save the current state of your project before making major structural changes.
Action: Navigate inside your existing project folder (likely shadcn-supabase-app) and commit.
# Make sure you are inside the shadcn-supabase-app directory
git add .
git commit -m "chore: pre-monorepo refactor commit"
Navigate to Repository Root:
Goal: Position your terminal in the parent directory (codexcrmapp) to perform actions on the project folder.
Action: Move one level up from your project folder.
cd ..
# Your terminal should now be in the 'codexcrmapp' directory,
# which contains the 'shadcn-supabase-app' folder.
Phase 1: Monorepo Structure & Configuration
Establish the core multi-package workspace structure.
Initialize Monorepo Directory Structure:
Goal: Create the standard apps and packages directories and move your existing Next.js app into apps/web. Also, set up the initial directories for shared packages.
Action: Run these commands from the codexcrmapp root directory:
# Create top-level folders
mkdir apps packages
# Move and rename your existing Next.js app
mv shadcn-supabase-app apps/web
# Create standard package directories
mkdir -p packages/server packages/db packages/jobs packages/ui
Relocate Root-Level Configuration:
Goal: Ensure configuration specific to Supabase CLI and GitHub Actions resides at the repository root, not within the apps/web package.
Action: Check if supabase or .github directories exist within apps/web. If so, move them to the codexcrmapp root. Run these from the root:
# Check if apps/web/supabase exists, if yes, move it:
[ -d apps/web/supabase ] && mv apps/web/supabase .
# Check if apps/web/.github exists, if yes, move it:
[ -d apps/web/.github ] && mv apps/web/.github .
[ -d path ] checks if a directory exists. && runs the next command only if the check is true. . refers to the current directory (the root).Define pnpm Workspace:
Goal: Tell pnpm which directories contain the packages belonging to the monorepo workspace.
Action: Create a file named pnpm-workspace.yaml in the codexcrmapp root directory with the following content:
# pnpm-workspace.yaml
packages:
- 'apps/*'
- 'packages/*'
Initialize Individual Packages:
Goal: Create a package.json file in each of the new directories within packages/ so pnpm recognizes them as distinct packages.
Action: Run the following commands from the codexcrmapp root directory. The y flag accepts default settings for pnpm init.
cd packages/server && pnpm init -y && cd ../..
cd packages/db && pnpm init -y && cd ../..
cd packages/jobs && pnpm init -y && cd ../..
cd packages/ui && pnpm init -y && cd ../..
package.json files later to adjust names (e.g., @codexcrm/server), entry points (main, types), etc., as needed.)Understand Folder Responsibilities & Secrets:
Goal: Internalize the purpose of each new directory and where sensitive information (API keys) should be managed.
Context:
apps/web: Next.js UI. Secrets: Only public keys (NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY). Loaded via .env* files prefixed with NEXT_PUBLIC_ or Vercel public env vars.packages/server: tRPC backend logic. Secrets: Server-side only keys (SUPABASE_SERVICE_ROLE_KEY, OPENAI_API_KEY). Loaded via non-prefixed env vars (NEVER expose these to the client).packages/db: Drizzle schema, migrations, DB types. Secrets: Generally none, except maybe DATABASE_URL in .env for local Drizzle Kit commands.packages/jobs: Supabase Edge Functions. Secrets: Server-side keys, managed via Edge Function secrets or env vars.supabase/: Supabase CLI config, SQL migrations. Secrets: None directly in files. CLI uses login tokens or env vars like SUPABASE_ACCESS_TOKEN.Action: Create a .gitignore file at the codexcrmapp root (if one doesn't exist) and ensure it includes lines like:
# Environment variables
.env
.env.*
!.env.example
# Node
node_modules/
dist/
.next/
out/
# IDE / OS files
.DS_Store
*.code-workspace
.vscode/
Configure TypeScript Path Aliases:
import { db } from '@codexcrm/db').Create/edit the root tsconfig.json (codexcrmapp/tsconfig.json) with base settings and path aliases:
// codexcrmapp/tsconfig.json
{
"compilerOptions": {
"target": "es2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true, // Root tsconfig usually doesn't emit
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
// Path Aliases
"baseUrl": ".",
"paths": {
// Adjust '/src/' part if your packages don't use a 'src' subfolder
"@codexcrm/server/*": ["packages/server/src/*"],
"@codexcrm/db/*": ["packages/db/src/*"],
"@codexcrm/jobs/*": ["packages/jobs/*"], // May not have src/
"@codexcrm/ui/*": ["packages/ui/src/*"],
"@codexcrm/web/*": ["apps/web/*"] // Alias for the app itself
}
},
"include": [], // Keep minimal; packages manage their own files
"exclude": ["node_modules", "dist"]
}
Modify the app's tsconfig (apps/web/tsconfig.json) to extend the root config and keep its app-specific settings:
// apps/web/tsconfig.json
{
// Extend the root configuration
"extends": "../../tsconfig.json",
"compilerOptions": {
// App-specific options override or add to the base
"baseUrl": ".", // Keep if using "@/*" alias below
"paths": {
// Keep app-internal aliases like src -> @/*
"@/*": ["./src/*"] // Adjust if you don't use a src folder in apps/web
},
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"noEmit": true, // Next.js handles emitting
"module": "esnext", // Ensure compatibility with Next.js
// ... other Next.js specific options like plugins
"plugins": [{ "name": "next" }]
},
// Include files specific to the Next.js app
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/**/*.ts", "src/**/*.tsx"], // Be specific
"exclude": ["node_modules"]
}
Install Dependencies & Link Workspace:
Goal: Install all dependencies listed in the package.json files across the workspace (apps/web, packages/*) and link the local packages together according to the pnpm-workspace.yaml definition.
Action: Run the following command from the codexcrmapp root directory:
pnpm install
package.json files, downloads necessary dependencies into a shared root node_modules folder, and creates symlinks so that imports like @codexcrm/db correctly resolve to your local packages/db code.Update Import Paths (Iterative Task):
apps/web (and potentially other packages later) that previously used relative paths to access code now located in one of the packages/* directories.Identify Shared Code: Look through apps/web (especially lib/, utils/, components/ if they contain non-UI logic) for code that should be shared (e.g., Supabase client setup, core data types, utility functions).
Move Files: Move these identified files to the appropriate package directory (e.g., DB client setup to packages/db/src, shared types perhaps to packages/db/src or packages/server/src, utility functions to packages/ui/src or a new packages/utils). Remember to create src subdirectories if needed and defined in your tsconfig.json paths.
Update Imports: Go through the files in apps/web (and any files you moved) and update import statements. Replace relative paths (../../lib/db) with the new workspace aliases (@codexcrm/db).
AI Assistance Tip: Use an AI code assistant (like GitHub Copilot Workspace, Cursor) with a prompt similar to this:
"I have restructured my project into a pnpm monorepo. Files previously in apps/web/lib/supabase are now in packages/db/src/supabase, and shared types from apps/web/types are in packages/db/src/types. My root tsconfig.json defines path aliases like @codexcrm/db/* pointing to packages/db/src/. Please scan the apps/web directory and update all relative import paths that should now use these @codexcrm/ aliases."
pnpm tsc --noEmit (possibly via turbo run typecheck) frequently to catch type errors caused by incorrect paths.(Optional but Recommended) Implement Shared ESLint Config:
Create the shared config package:
# Run from codexcrmapp root
mkdir packages/eslint-config-custom
cd packages/eslint-config-custom
pnpm init -y
# Create config file (e.g., index.js or eslint.config.js)
touch index.js
# Add base rules (copy/adapt from apps/web's old config)
# Example content for index.js (CommonJS format):
# module.exports = { extends: ['eslint:recommended', ...], rules: {...} };
cd ../..
Add as dev dependency to workspaces:
pnpm --filter @codexcrm/web add -D eslint @codexcrm/eslint-config-custom
pnpm --filter @codexcrm/server add -D eslint @codexcrm/eslint-config-custom
# ... repeat for db, jobs, ui if linting them
Configure individual package ESLint files (e.g., apps/web/eslint.config.js) to extend the shared config:
// Example: apps/web/eslint.config.js
module.exports = {
root: true,
extends: ['@codexcrm/eslint-config-custom', 'next/core-web-vitals'],
// Add web-specific overrides here
};
Add lint scripts to relevant package.json files (e.g., "lint": "eslint . --ext .ts,.tsx").