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 is a pnpm monorepo containing two independent packages: backend and frontend. Each package has its own package.json, dependencies, and scripts, but they share a common root for tooling and CI.
pyqdeck/
├── backend/              # Express.js API server
├── frontend/             # Next.js 15 application
├── docs/                 # Mintlify documentation
├── .github/workflows/    # CI/CD pipelines
├── render.yaml           # Render deployment config
├── pnpm-workspace.yaml   # Monorepo configuration
└── package.json          # Root package.json

Design Principles

  1. Independent deployability - Each package can be built and deployed independently
  2. Clear boundaries - The only coupling is the API contract (openapi.json)
  3. Shared tooling - Root-level scripts for linting, formatting, and CI

Backend Package

Tech Stack: Express 5, MongoDB (Mongoose 9), ES Modules

Architecture (Layered)

backend/src/
├── app.js                # Express app setup, route mounting
├── index.js              # Entry: Sentry, DB connect, graceful shutdown
├── config/               # Configuration (DB, mail, env)
├── controllers/          # Request handlers (13 controllers)
├── services/             # Business logic (13 services)
├── repositories/         # Data access layer (14 repositories)
├── models/               # Mongoose schemas (13+ models)
├── middlewares/          # Auth, error handling, validation
├── routes/               # Route definitions (13 route files)
├── utils/                # Shared utilities
└── docs/swagger.js       # OpenAPI spec generation

Key Dependencies

CategoryPackages
Auth@clerk/express
Validationzod, express-validator
Error Tracking@sentry/node, @sentry/profiling-node
Logging@logtail/winston, winston
Emailresend
File Storage@uploadthing/node
Securityhelmet, cors, express-rate-limit

Frontend Package

Tech Stack: Next.js 15, React 19, Tailwind CSS 4, shadcn/ui

Directory Structure

frontend/src/
├── app/                  # Next.js App Router
├── components/
│   ├── ui/               # UI component library (55+ components)
│   └── ...               # Feature components
├── hooks/                # React hooks (useApi, etc.)
├── lib/                  # Utilities, API SDK (api-generated.ts)
└── styles/               # Global styles

Key Dependencies

CategoryPackages
Auth@clerk/nextjs
UIRadix UI, shadcn/ui components
StylingTailwind CSS 4
API ClientAxios (via generated SDK)
Storybook@storybook/nextjs-vite

API Contract: The Only Coupling

The only dependency between frontend and backend is the OpenAPI spec:
backend/openapi.json  →  frontend/src/lib/api-generated.ts
This is enforced in CI:
  1. Backend tests run
  2. CI verifies openapi.json hasn’t drifted
  3. Frontend build runs gen:api to regenerate the SDK
  4. If any step fails, the PR is blocked
This means:
  • Frontend never writes manual fetch calls - everything goes through the generated SDK
  • Backend changes are always type-safe - the SDK regenerates on every build
  • No shared code - the packages communicate only via HTTP

CI/CD Pipeline

The monorepo has 8 GitHub Actions workflows:
WorkflowTriggerPurpose
monorepo-ci.ymlPush/PR to mainFull 5-stage CI/CD pipeline
lighthouse.ymlPR (frontend/)Lighthouse performance audit
bundle-analysis.ymlPR (frontend/)Bundle size analysis
storybook.ymlPush to main (frontend/)Deploy Storybook to GitHub Pages
load-test.ymlPush/PR (backend/)k6 load testing
codeql-analysis.ymlPush/PR/scheduleSecurity analysis
release-drafter.ymlPush/PRAuto-draft release notes
pr-size-labeler.ymlPRLabel PRs by size

5-Stage Pipeline (monorepo-ci.yml)

1. Security   → pnpm audit --prod (both packages)
2. Quality    → eslint + prettier checks
3. Backend    → vitest + contract check
4. Frontend   → gen:api + next build
5. Deploy     → Docker build + Render deploy

Deployment

PackagePlatformMethod
BackendRenderDocker (multi-stage build)
FrontendVercelVercel GitHub integration
StorybookGitHub PagesGitHub Actions
DocsMintlifyGitHub Actions

Adding a New Package

If you need to add a new package (e.g., shared/ for common utilities):
  1. Create the directory with its own package.json
  2. Add it to pnpm-workspace.yaml
  3. Reference it in other packages via workspace protocol: "@pyqdeck/shared": "workspace:*"
However, our current philosophy is to keep packages independent and communicate only via the API contract. Only add shared packages if there’s a compelling reason.

Next Steps