Contributing Guide

Developer5 min read

Contributing to nyxCore

Prerequisites

  • Node.js >= 18
  • Docker (for PostgreSQL + Redis)
  • npm (package manager)

Environment Setup

  1. Clone the repo and install dependencies:
git clone <repo-url>
cd nyxcore-systems
npm install
  1. Copy .env.example and fill in required values:
cp .env.example .env

Environment Variables

Variable Required Description
DATABASE_URL Yes PostgreSQL connection string. Default: postgresql://nyxcore:nyxcore_dev@localhost:5432/nyxcore?schema=public
REDIS_URL Yes Redis connection string for rate limiting. Default: redis://localhost:6379
AUTH_SECRET Yes NextAuth session secret. Generate with openssl rand -base64 32
AUTH_URL Yes NextAuth base URL. Default: http://localhost:3000
ENCRYPTION_KEY Yes 32-byte base64 key for AES-256-GCM API key encryption. Generate with openssl rand -base64 32
RESEND_API_KEY No Resend API key for transactional emails
EMAIL_FROM No Sender address for emails. Format: Name <email@domain.com>
NODE_ENV No development (default), production, or test
GITHUB_CLIENT_ID No GitHub OAuth app client ID
GITHUB_CLIENT_SECRET No GitHub OAuth app client secret
KIMI_BASE_URL No Override base URL for Kimi K2 / Moonshot AI provider
GRAFANA_ADMIN_PASSWORD No Grafana admin password (production monitoring)
HETZNER_API_KEY No Hetzner DNS API token for Traefik ACME TLS
STRIPE_SECRET_KEY No Stripe API secret key for billing
STRIPE_WEBHOOK_SECRET No Stripe webhook signing secret
NEXT_PUBLIC_APP_URL No Public app URL for Stripe redirects. Default: http://localhost:3000
  1. Start infrastructure and database:
npm run docker:up          # Start PostgreSQL 16 (pgvector) + Redis 7
npm run db:push            # Apply Prisma schema to database
npm run db:generate        # Generate Prisma client
npm run db:seed            # Seed default tenant + personas
  1. Apply Row-Level Security policies:
psql $DATABASE_URL -f prisma/rls.sql
  1. Start the dev server:
npm run dev
# Or use the all-in-one script:
./scripts/dev-start.sh     # Starts docker + dev server together

Available Scripts

Script Command Description
dev next dev Start Next.js development server with hot reload
build next build Create optimized production build
start next start Start production server (requires build first)
lint next lint Run ESLint on the codebase
typecheck tsc --noEmit TypeScript type checking without emit
test vitest run Run all unit tests (Vitest)
test:watch vitest Run tests in watch mode
test:e2e playwright test Run end-to-end tests (Chromium + Mobile)
db:generate prisma generate Regenerate Prisma client after schema changes
db:push prisma db push Push schema changes to DB (no migration file)
db:migrate prisma migrate dev Create and apply a named migration
db:seed prisma db seed Seed database with default tenant and personas
db:seed:init tsx prisma/seed-init.ts Initial seed (default tenant only)
db:studio prisma studio Open Prisma Studio GUI at localhost:5555
docker:up docker compose up -d Start PostgreSQL + Redis containers
docker:down docker compose down Stop containers (data persisted in volumes)

Helper Scripts

Script Description
scripts/dev-start.sh Start docker + dev server in one command
scripts/deploy.sh Production deployment script
scripts/db-backup.sh Database backup utility
scripts/db-migrate-safe.sh Safe production migration (filters destructive DDL)
scripts/memory-pull.sh Pull .memory/ letter files from GitHub
scripts/run-analysis.ts Run code analysis pipeline via CLI
scripts/copy-to-ckb-nyx.ts Copy files to CKB container
scripts/md2pdf.py Convert Markdown files to PDF
scripts/run-persona-eval.ts Run persona evaluation pipeline
scripts/analyze-persona-results.ts Analyze persona evaluation results
scripts/harden-persona-prompts.ts Harden persona system prompts

Development Workflow

Schema Changes

After editing prisma/schema.prisma:

npm run db:push       # Apply schema to DB
npm run db:generate   # Regenerate Prisma client types

For production-tracked changes, use npm run db:migrate instead of db:push.

Adding a New tRPC Router

  1. Create router in src/server/trpc/routers/<name>.ts
  2. Register in src/server/trpc/router.ts
  3. Use protectedProcedure (auth + tenant) or llmProtectedProcedure (+ LLM rate limit)
  4. Access via trpc.<router>.<procedure> in client components

Adding a New Dashboard Page

  1. Create src/app/(dashboard)/dashboard/<feature>/page.tsx with "use client"
  2. Use tRPC hooks: const { data } = trpc.<router>.<method>.useQuery()
  3. Follow spacing/header conventions: space-y-6, uppercase tracking-wider titles

Testing

Unit Tests

npm run test                                    # All tests
npx vitest run tests/unit/crypto.test.ts        # Single file
npm run test:watch                              # Watch mode
  • Location: tests/unit/*.test.ts
  • Framework: Vitest with globals enabled
  • Setup: tests/setup.ts (mocks env vars)
  • Path alias: @/ maps to ./src/

E2E Tests

npx playwright install                          # Install browsers (first time)
npm run test:e2e                                # Run all E2E tests
  • Location: tests/e2e/*.spec.ts
  • Framework: Playwright (Chromium + Mobile viewports)

Pre-Commit Checks

Before committing, run:

npm run typecheck && npm run lint && npm run test

Infrastructure

Service Image Port Purpose
PostgreSQL pgvector/pgvector:pg16 5432 Primary database with vector extension
Redis redis:7-alpine 6379 Rate limiting (fail-open)
CKB ghcr.io/simplyliz/ckb:latest Code Knowledge Base (repository analysis)

Data is persisted in Docker volumes (postgres_data, redis_data). docker:down stops containers but preserves data.

Code Style

  • TypeScript strict mode
  • Radix UI primitives + CVA variants in src/components/ui/
  • CSS variables with nyx-* namespace, dark mode via .dark class
  • Utility: cn() (clsx + tailwind-merge)
  • LLM providers use BYOK pattern — tenant API keys encrypted at rest (AES-256-GCM)