Skip to main content

Scope

Surnex now ships a dedicated, SEO/LLM-first marketing site:
  • Repository: apps/marketing
  • Public URL: https://surnex.io
  • Runtime: Vercel
  • API/runtime boundary: Marketing content is static/frontend only; API + Worker stay on Railway
The marketing site is intentionally separate from the API/worker stack to keep public content publishing fast and deployment stable while preserving existing API topology.

Architecture

  • Framework: Astro (with React islands for interactive components)
  • Deployment: Vercel static hosting
  • Content: Markdown content collections from apps/marketing/src/content/blog
  • Distribution: Public routes for homepage, info pages, blog index, and blog details
  • SEO artifacts:
    • sitemap.xml
    • robots.txt
    • rss.xml
    • llms.txt

Repository paths

  • App: apps/marketing
  • Pages: apps/marketing/src/pages
  • Blog routes: apps/marketing/src/pages/blog/*
  • Blog collection: apps/marketing/src/content/blog/*.md
  • Vercel configs:
    • apps/marketing/vercel.json (app-root deploy mode)
    • vercel.json (repo-root fallback/wrapper mode)

Content publishing flow

  1. A content platform sends POST /v1/webhooks/marketing/blog to API.
  2. API validates request, validates signature, and writes markdown to:
    • apps/marketing/src/content/blog/<slug>.md
    • branch: marketing
  3. Vercel build/rebuild runs and publishes updated pages.
Webhook fields include:
  • event_id (idempotency)
  • slug
  • title, description, excerpt
  • author, tags, status
  • published_at, updated_at
  • hero_image_url
  • content_markdown

Idempotency behavior

  • Retries with the same event_id should be safe.
  • Same event_id + content is expected to be idempotent for publish operations.

Required environment in API

Set these for webhook handling:
  • MARKETING_WEBHOOK_SECRET
  • MARKETING_GITHUB_TOKEN
  • MARKETING_GITHUB_OWNER
  • MARKETING_GITHUB_REPO
  • MARKETING_BRANCH=marketing (default)
  • MARKETING_PATH=apps/marketing/src/content/blog (default)

Vercel deployment settings

Use one of these configurations depending on project import mode:
  • App-root preferred (stable):
    • Project root: apps/marketing
    • Framework preset: Astro
    • Build command: pnpm --filter @surnex/marketing build
    • Output directory: apps/marketing/dist
  • Repo-root fallback:
    • Project root: repo root
    • Framework preset: Astro
    • Build command: pnpm --filter @surnex/marketing build
    • Output directory: dist (root vercel.json stages build artifacts from apps/marketing/dist)

Local development

pnpm --filter @surnex/marketing dev
pnpm --filter @surnex/marketing build

Verification checklist before publish

  1. Open https://surnex.io and confirm landing and core pages.
  2. Open https://surnex.io/blog and confirm latest published posts render.
  3. Open https://surnex.io/blog/<slug> for a recently updated post.
  4. Verify SEO artifacts:
    • https://surnex.io/sitemap.xml
    • https://surnex.io/robots.txt
    • https://surnex.io/rss.xml
    • https://surnex.io/llms.txt
  5. Exercise webhook in staging with sample payload from API contract tests and confirm successful artifact update.
  • README.md (marketing deployment section)
  • docs/quickstart.md (marketing pipeline section)
  • AGENTS.md (repo policy + documentation updates requirement)
  • OpenAPI: https://api.surnex.io/.well-known/openapi.json