> ## Documentation Index
> Fetch the complete documentation index at: https://docs.surnex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Marketing Site

> Setup and operations for the Surnex Astro marketing website at surnex.io.

## 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

```bash theme={null}
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.

## Links

* `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`
