Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.pyqdeck.in/llms.txt

Use this file to discover all available pages before exploring further.

Overview

PyqDeck uses a 5-stage CI/CD pipeline on GitHub Actions, with separate deployment targets for the backend (Render), frontend (Vercel), and Storybook (GitHub Pages).

CI/CD Pipeline Stages

Stage 0: Security Audit

pnpm audit --prod   # Backend
pnpm audit --prod   # Frontend
Scans all production dependencies for known vulnerabilities. Fails the pipeline if any critical or high vulnerabilities are found.

Stage 1: Quality & Linting

# Backend
pnpm install
pnpm run lint           # ESLint
pnpm run format:check   # Prettier

# Frontend
pnpm install
pnpm run lint           # ESLint
pnpm run format:check   # Prettier
Ensures code style consistency. All PRs must pass linting and formatting checks.

Stage 2: Backend Tests & API Contract

# Install MongoDB binary for test environment
# Run tests with coverage
pnpm run test:coverage

# Verify OpenAPI spec hasn't drifted
pnpm run openapi:export
git diff --exit-code backend/openapi.json
This is the most critical stage:
  1. Vitest runs all backend tests with an in-memory MongoDB (MongoMemoryServer)
  2. Coverage is uploaded to Codecov — minimum thresholds: 80% lines/functions/statements, 70% branches
  3. Contract Check verifies that openapi.json is in sync with the route code. If a developer changes an API route without updating the JSDoc annotations (or vice versa), the build fails

Stage 3: Frontend Build & SDK Validation

pnpm install    # Both packages
pnpm run gen:api   # Regenerate SDK from openapi.json
pnpm run build     # Next.js build
This stage validates that:
  • The SDK generates successfully from the current OpenAPI spec
  • The frontend builds without errors using the generated SDK
  • TypeScript types are all satisfied
If a backend change breaks the frontend types, this stage catches it.

Stage 4: Docker Build

docker build -t pyqdeck-backend ./backend
Builds the backend Docker image to verify it compiles and packages correctly. The image is not pushed — this is a validation step only.

Stage 5: Deployment

Only triggers on push to main (not on PRs), after all previous stages pass. Backend (Render):
curl -X POST $RENDER_DEPLOY_HOOK
Fires a Render deploy webhook. Render pulls the latest code, builds the Docker image, and deploys to production. Frontend (Vercel): Vercel’s native GitHub integration handles this separately — it detects changes to the frontend/ directory and deploys automatically.

Deployment Targets

ServicePlatformMethodURL
Backend APIRenderDocker (webhook)backend.pyqdeck.in
Frontend WebVercelGitHub integrationpyqdeck.in
StorybookGitHub PagesGitHub Actionsstorybook.pyqdeck.in
API DocsSwagger UIServed by backendbackend.pyqdeck.in/api-docs
Engineering DocsMintlifyGitHub integrationdocs.pyqdeck.in
Status PageBetterUptimeExternal monitoringpyqdeck.betteruptime.com

Render Configuration

File: render.yaml
services:
  - name: pyqdeck-backend
    type: web
    runtime: docker
    plan: free
    region: singapore
    healthCheckPath: /api/v1/health
    envVars:
      - key: NODE_ENV
        value: production
      - key: PORT
        value: 3000
      # Sensitive vars set in Render dashboard:
      # MONGODB_URI, CLERK keys, RESEND_API_KEY, etc.
Docker context is set to ./backend, so Render builds from the backend directory.

Docker Configuration

File: backend/Dockerfile Multi-stage build for minimal image size:
StagePurpose
depsInstall production dependencies only (pnpm install --prod --frozen-lockfile)
runnerCopy node_modules, package.json, and src/
Security measures:
  • Non-root user (nodeuser, UID 1001)
  • No dev dependencies in the final image
  • Slim base image (node:20-slim)
EXPOSE 3000
CMD ["node", "src/index.js"]

GitHub Actions Workflows

Beyond the main pipeline, there are 7 additional workflows:
WorkflowTriggerPurpose
Lighthouse CIPR on frontend/**Performance audit — ensures Lighthouse scores stay above 90
Bundle AnalysisPR on frontend/**Tracks Next.js bundle size changes with PR comments
CodeQLPush/PR to main + weekly cronStatic security analysis for JavaScript
Load TestPush/PR on backend/**k6 smoke test against a live API with MongoDB service container
PR Size LabelerPR opened/syncedAuto-labels PRs by changed lines (XS/S/M/L)
Storybook DeployPush to main on frontend/**Builds and deploys Storybook to GitHub Pages
Release DrafterPush to mainDrafts release notes from merged PRs
All workflows use cancel-in-progress: true to avoid redundant builds on the same branch.

Environment Variables

Backend (Render)

VariablePurpose
NODE_ENVproduction
PORT3000
MONGODB_URIMongoDB connection string
CLERK_PUBLISHABLE_KEYClerk auth public key
CLERK_SECRET_KEYClerk auth secret key
CLERK_WEBHOOK_SECRETSvix webhook secret
RESEND_API_KEYResend email API key
MAIL_FROMSender email address
SENTRY_DSNSentry error tracking DSN
LOGTAIL_SOURCE_TOKENBetter Stack logging token
UPLOADTHING_TOKENUploadThing file storage token
RATE_LIMIT_WINDOW_MSRate limit window (default: 900000)
RATE_LIMIT_MAXMax requests per window (default: 100)

Frontend (Vercel)

VariablePurpose
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYClerk public key
NEXT_PUBLIC_API_URLBackend API URL (defaults to production)

Concurrency Strategy

All workflows are configured with path filtering so that:
  • Changes to backend/** only trigger backend workflows
  • Changes to frontend/** only trigger frontend workflows
  • Changes to docs/** only trigger docs deployment
  • Full monorepo CI runs on any change
This keeps CI fast and efficient.

Next Steps