Skip to main content
Docs

8. Backend & API

The API is a classic Express server. All routes are mounted in apps/api/src/index.ts.

8.1 Public Demo Endpoints (no auth, stateless mode compatible)#

MethodPathLimitPurpose
GET/healthStatus check (db, LLM availability)
POST/api/generate10/min/IPMarkdown → HTML (full pipeline)
POST/api/validate10/min/IPValidate MD without render
GET/api/templatesList of starter templates
POST/api/convert5/min/IPDOCX/PDF/… → Markdown
POST/api/convert/code-to-mermaid5/min/IPASCII → Mermaid DSL via LLM

8.2 Auth Endpoints#

MethodPathLimitAuthPurpose
POST/api/auth/register5/h/IPnoCreate account (argon2id)
POST/api/auth/login10/15min/IPnoCreate session (connect.sid)
POST/api/auth/logoutyesDestroy session
GET/api/auth/meyesCurrent user

8.3 Protected Endpoints (all require auth + DB)#

Projects:

  • GET /api/projects — List
  • POST /api/projects — New project (Limit: 10 per user)
  • PATCH /api/projects/:id — Update (name, designPack, languages, projectType, docsConfig, componentVariants)
  • DELETE /api/projects/:id, POST /api/projects/:id/duplicate

Pages (nested under projects):

  • GET /api/projects/:projectId/pages — List
  • GET /api/projects/:projectId/pages/manifest — Lightweight (for Sidebar)
  • POST /api/projects/:projectId/pages — New page
  • GET/PATCH/DELETE /api/projects/:projectId/pages/:pageId
  • POST .../duplicate, PATCH /api/projects/:projectId/pages/reorder
  • POST .../generate — the main action: renders the page
  • POST .../export — multi-language static export for Deploy

Translations:

  • GET/POST/PATCH/DELETE /api/projects/:projectId/pages/:pageId/translations[/:lang]
  • POST .../translate — Trigger LLM Translation

Media:

  • POST /api/projects/:projectId/media — Upload (multipart, max 100 Assets/Project)
  • GET /api/projects/:projectId/media — List
  • PATCH/DELETE .../media/:assetId
  • POST .../media/upload-url — Presigned R2-URL

Deploy & Domain:

  • POST /api/projects/:projectId/deploy — Cloudflare-Push (Cooldown: 60s)
  • GET .../deployments[/:id] — List/Detail
  • POST .../deployments/:id/rollback
  • POST/GET/DELETE .../domain — Custom Domain Management
  • GET .../analytics?range=7d|30d|90d — Cloudflare-Zone-Stats

Public Media-Serving:

  • GET /api/media/:projectId/:filename — 100/min/IP (for Preview-Iframes + Deploys)

8.4 Auth-Flow in Detail#

  • Session-Storage: in-memory MemoryStore in stateless mode; connect-pg-simple with the sessions table if DATABASE_URL is set
  • Cookie: connect.sid (httpOnly, sameSite=lax, maxAge 7 days)
  • Password Hashing: argon2id, memoryCost 65536, timeCost 3, parallelism 1
  • Middlewares: requireAuth (401 if no session), optionalAuth (User if present, otherwise continue)

8.5 Services — the Pipeline Layer#

ServicePurpose
llm-client.tsOpenAI-SDK to OpenRouter; capture'd Node-Native-Fetch (against JSDOM-Globals)
llm-service.tsMapper-Prompt-Wrapper, Cache via mdHash in llm_cache table
auto-detect-pipeline.tssanitize → sectionize → detect → extract → validate (Default for Landing-Pages)
docs-pipeline.tsAlternative path for layout: docs-pages (TOC, Sidebar, Article-Flow)
deterministic-mapper.tsLLM-Fallback if OPENROUTER_API_KEY is not set
mermaid-ssr.tsJSDOM-Pre-Render of Mermaid-Fences to inline SVG
code-to-mermaid.tsASCII → Mermaid DSL (Sonnet 4.5)
translation-engine.tsMarkdown-Translate (Gemini Flash)
lang-detect.tsLanguage-Auto-Detection (franc-min)
deploy-engine.tsCloudflare-Pages-Integration
media-storage.tsLocal FS / Cloudflare R2 with presigned-URLs
media-cleanup.tsCron-Job for orphaned uploads
custom-domain.tsDNS-Validation + Zone-Sync
analytics.tsCloudflare-Zone-Analytics-Pull