Thank you for contributing! This guide covers the development workflow, code standards, and release process.
- Contributing to Monorepo
The fastest way to get started is using the included dev container, which provides a fully configured development environment with all required tools.
Prerequisites:
- Docker Desktop (or Docker Engine on Linux)
- VS Code with Dev Containers extension
Setup:
- Clone the repository:
git clone https://github.com/JimmyPaolini/monorepo.git - Open the folder in VS Code
- Open the command palette (
Ctrl/Cmd+Shift+P) → Dev Containers: Reopen in Container - Select a configuration when prompted:
- Monorepo Devcontainer (Local) — local machine (Docker-outside-of-Docker, recommended)
- Monorepo Devcontainer (Cloud) — GitHub Codespaces or when full Docker isolation is needed (Docker-in-Docker)
- Wait for container build (~2-3 minutes first time)
- Start developing!
Included Tools:
| Tool | Version | Purpose |
|---|---|---|
| Node.js | 22.20.0 | JavaScript runtime |
| pnpm | 10.20.0 | Package manager |
| Terraform | latest | Infrastructure provisioning (Linode) |
| Supabase CLI | latest | Database migrations, type generation |
| kubectl | latest | Kubernetes cluster management |
| Helm | latest | Kubernetes package manager |
| GitHub CLI | latest | Repository operations |
| Docker | DooD (local) / DinD (cloud) | Docker-outside-of-Docker on local; Docker-in-Docker in cloud |
Port Forwarding:
| Port | Service | Auto-Forward |
|---|---|---|
| 3000 | Lexico Dev Server | Notify |
| 3001 | Open WebUI | Notify |
| 8889 | SearxNG | Notify |
| 11434 | Ollama API | Silent |
| 54321 | Supabase API | Silent |
| 54322 | PostgreSQL | Silent |
| 54323 | Supabase Studio | Notify |
| 54324 | Inbucket (Email) | Silent |
| 54325 | Analytics | Silent |
See .devcontainer/README.md for detailed configuration and troubleshooting.
For local development without containers:
Prerequisites:
- macOS with Homebrew installed
- Git: Latest stable version
- Docker Desktop: Required for SearxNG, Open WebUI, and caelundas containers
Setup:
Run the setup script to install all dependencies:
git clone https://github.com/JimmyPaolini/monorepo.git
cd monorepo
./scripts/local/setup.shThis script:
- Installs nvm, Node.js (22), pnpm, uv, Python (3.11+), Ollama (+ pulls
gemma4:e2b) - Installs Terraform, Supabase CLI, Helm, kubectl, GitHub CLI, jq, yamllint
- Creates
.envfiles from.env.defaulttemplates (root, lexico, caelundas) - Sets
LOCAL_WORKSPACE_FOLDERfor docker-compose volume mounts - Runs
pnpm installanduv sync(Python venv for affirmations)
monorepo/
├── applications/ # Deployable applications
│ ├── affirmations/ # Python LangChain + Ollama affirmation generator
│ ├── caelundas/ # CLI ephemeris calendar generator
│ ├── lexico/ # TanStack Start + Supabase web app
│ └── JimmyPaolini/ # Personal website
├── packages/ # Shared libraries
│ └── lexico-components/ # React component library (shadcn/ui)
├── documentation/ # Guides and references
├── infrastructure/ # Helm charts, Terraform
└── tools/ # Build tools and generators
# Create feature branch (see branch naming conventions)
git checkout -b feat/lexico-your-feature
# Run development server
nx run <project>:develop # caelundas, lexico, JimmyPaolini
# Run tests
nx run <project>:test # All tests
nx run <project>:test:watch # Watch mode
nx run caelundas:test:unit # Specific type
# Code quality (use --all for all projects)
nx run-many --target=lint --all # or :lint:write to fix
nx run-many --target=typecheck --all
nx run-many --target=format:check --all # or :format:write
nx run-many --target=spell-check --all
nx run-many --target=markdown-lint --all # or :markdown-lint:write
nx run-many --target=knip --all # or :knip:write (caution!)
nx run-many --target=code-analysis --all # Run all checks
# Affected projects only
nx affected --target=test- TypeScript: Explicit return types, no
any, type imports (import { type T }), strict null checks - Imports: Auto-sorted (Node built-ins → external → workspace → relative → types)
- Naming: PascalCase (types/classes), camelCase (variables/functions), UPPER_CASE (constants), kebab-case (files)
- React: React 19, TanStack Router, shadcn/ui via
@monorepo/lexico-components, Tailwind CSS - Documentation: TSDoc for public APIs, update docs with code changes
See eslint.config.base.ts for complete rules.
Three Husky hooks enforce quality gates locally. Never bypass them with --no-verify — fix the underlying issue instead.
| Hook | Trigger | What it runs | Config |
|---|---|---|---|
pre-commit |
git commit |
lint-staged: format, lint, typecheck, spell-check, and more on staged files | lint-staged.config.ts |
commit-msg |
git commit |
commitlint: validates Conventional Commits format (<type>(<scope>): <subject>) |
commitlint.config.ts |
pre-push |
git push |
validate-branch-name: enforces <type>/<scope>-<description> pattern |
validate-branch-name.config.cjs |
If a hook fails, the git operation is blocked until you fix the error. See the config files linked above for details on what each hook checks.
Required format: <type>/<scope>-<description> (lowercase, kebab-case)
Examples: feat/lexico-user-auth, fix/monorepo-routing, docs/caelundas-api
Validated by Husky pre-push hook and GitHub Actions. See checkout-branch skill for details.
Use Conventional Commits: <type>(<scope>): <gitmoji> <subject> (max 128 chars, imperative mood, lowercase)
Types: feat (minor release), fix/perf/refactor/build (patch), docs/test/ci/chore (no release)
Scopes: monorepo, caelundas, lexico, lexico-components, JimmyPaolini, documentation, dependencies, infrastructure, ci
Breaking changes: Add ! after type or BREAKING CHANGE: in footer (triggers major release)
Examples:
feat(caelundas): add moon phase calculation
fix(lexico): resolve mobile layout overflow
feat(api)!: redesign authentication # Breaking changeCommits are validated by commitlint + Husky. See commit-code skill for details.
- Create PR:
git push origin feat/your-feature && gh pr create --fill - PR title: Use Conventional Commits format (e.g.,
feat(lexico): add search) - Automated checks: Lint, typecheck, tests, format, spell-check, markdown-lint (all must pass)
- Code review: Requires
@JimmyPaoliniapproval (CODEOWNERS) - Merge: Squash and merge with Conventional Commits message, delete branch
Releases use semantic-release - fully automated on merge to main.
Version bumps: BREAKING CHANGE → major, feat → minor, fix/perf/refactor/build → patch, docs/test/ci/chore → none
Workflow: Merge PR to main → automated release runs → analyzes commits → bumps version → updates CHANGELOG.md → creates tag & GitHub release
Test locally: pnpm semantic-release:dry-run
Prevent release: Use docs/test/ci/chore types or no-release scope
See release.config.cjs for complete configuration and guide.
All files are owned by @JimmyPaolini (see .github/CODEOWNERS).
Pull requests require owner approval before merging.
Each project uses .env.default files as templates for required environment variables. Copy .env.default to .env in each directory and fill in values.
| Variable | Purpose |
|---|---|
MONOREPO_ENVIRONMENT |
Environment: local, devcontainer-local, or devcontainer-cloud |
OLLAMA_HOST |
Ollama server URL (default: http://localhost:11434) |
SEARXNG_HOST |
SearxNG server URL (default: http://localhost:8889) |
TF_VAR_linode_token |
Linode API token for Terraform provisioning |
TF_VAR_linode_kubernetes_engine_cluster_id |
LKE cluster ID for deployments |
| Variable | Default | Purpose |
|---|---|---|
LATITUDE |
39.949309 |
Observer latitude for ephemeris calculations |
LONGITUDE |
-75.17169 |
Observer longitude for ephemeris calculations |
START_DATE |
(dynamic) | Calculation start date (YYYY-MM-DD) |
END_DATE |
(dynamic) | Calculation end date (YYYY-MM-DD) |
OUTPUT_DIRECTORY |
./output |
Directory for generated calendar files |
MAX_RETRIES |
5 |
NASA JPL API retry attempts |
INITIAL_DELAY_MS |
1000 |
Initial retry backoff delay |
MAX_DELAY_MS |
30000 |
Maximum retry backoff delay |
BACKOFF_MULTIPLIER |
2 |
Exponential backoff factor |
| Variable | Purpose |
|---|---|
SUPABASE_URL |
Supabase project URL |
SUPABASE_ANON_KEY |
Supabase anonymous/public key (safe for client) |
SUPABASE_SERVICE_ROLE_KEY |
Supabase service role key (server-side only, never expose) |
Weekly automated dependency updates are handled by the dependency-updates.yml workflow:
- Schedule: Runs every Monday at 6:00 UTC
- Detection: Uses
npm-check-updatesto find outdated dependencies - PR creation: Automatically creates a PR with the updates
- Review: All CI checks run against the update PR
- Merge: Requires manual review and approval before merging
To check for updates manually:
pnpm outdated # See which packages are outdated
pnpm update # Update within semver ranges
pnpx npm-check-updates -u # Update to latest versions (breaking changes possible)- Commit Messages Guide
- Semantic Release Config
- GitHub Actions Guide - CI/CD workflows and composite actions
- Gitmoji Reference
- Nx Documentation
- Conventional Commits
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Owner: @JimmyPaolini
MIT License. Copyright (c) Jimmy Paolini.