Skip to content
x.md
Esc
navigateopen⌘Jpreview
On this page

Self-hosting

Run the service and its documentation from the same Vercel project.

Run locally

git clone https://github.com/pc-style/x-md.git
cd x-md
bun install
bun run dev

The Vite server runs the landing page and local API handlers. Run bun run docs:dev separately for the Blume documentation server.

Build and deploy

bun run build
vercel --prod

The build generates Blume docs, then the Vite landing page into dist. The included Vercel configuration serves /docs, the static assets, and the API rewrites together.

  • docs/
    • index.mdx
    • (api)/
      • posts.mdx
      • search.mdx
      • profiles.mdx
      • pagination.mdx
      • responses.mdx
      • reliability.mdx
      • meta.ts
    • agents.mdx
    • self-hosting.mdx
  • blume.config.ts
  • theme.css

Live search provider

Latest and Top try FxTwitter, then the custom-built live search provider, then an optional Firecrawl web fallback. Photos, Videos, and Users use the live provider directly and return 503 when it is not configured.

The provider is configured through X_SEARCH_SESSIONS_JSON; the expected shape is defined in lib/xsearch.ts. For local development, use the gitignored accounts.local.json. Treat its contents as secrets and keep them out of version control.

The provider budgets its own upstream capacity per 15-minute window, shared across post and user searches. Failed attempts and page walks count. Unhealthy entries are taken out of rotation in the current process and retried later; health is per instance.

Shared counters

Attach Upstash Redis through the Vercel marketplace or CLI. The service automatically uses either environment-variable pair:

  • KV_REST_API_URL and KV_REST_API_TOKEN
  • UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN

These share per-IP and provider counters across instances. Without them, counters fall back to process memory. Live-provider checks fail closed when the counter store is unavailable, protecting the shared pool; the general request limiter still fails open. Redeploy after connecting environment variables.

Historical statistics

PostHog is optional. Connect its Vercel Marketplace integration to the production environment, choose your data region, and review its billing terms. It supplies NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN and NEXT_PUBLIC_POSTHOG_HOST; the API reads these on the server only. Alternatively, set POSTHOG_PROJECT_TOKEN and POSTHOG_HOST (for example, https://eu.i.posthog.com). Redeploy after configuring them.

Production API functions send a request_completed event with the route category, method, HTTP status, duration in milliseconds, application-cache result, key-validation status, public/key access, and degraded-search flag. Use these for request volume by endpoint, error and 429 rates, latency percentiles, and application-cache hit rate. Delivery runs in the background with a three-second timeout; failures do not change API responses.

request_completed events contain no search text, URLs, client IPs, bearer tokens, or key labels. Verified keys use a pseudonymous ID derived from their internal ID and the PostHog project token; rotating that token changes the pseudonyms. Public requests have a new ID per event, so distinct-user counts and anonymous retention are not meaningful. Person profiles, geolocation enrichment, and session replay are not enabled by this instrumentation.

These statistics cover completed function responses, not requests served by Vercel’s CDN, aborted requests, or platform errors before the handler runs. They are not billing-grade totals. Local development, previews, admin routes, and CORS preflights are excluded. Redis remains the source of truth for live limits and capacity; PostHog is only for historical analysis.

Landing-page web analytics

Set VITE_POSTHOG_KEY to the project token and VITE_POSTHOG_HOST to its ingestion host or managed reverse proxy (this deployment uses https://p.pcstyle.dev). These are public build-time values, not personal API credentials. Rebuild after changing them. Capture requires a production build with VERCEL_ENV=production; local development and previews do not send events. The SDK’s ui_host points to EU PostHog. In PostHog’s Web Analytics settings, add your public site URL (for this deployment, https://x.pcstyle.dev).

The landing page sends pageviews, page leaves, conversion_requested, and skill_install_command_copied. Anonymous browser IDs persist in local storage to measure returning visitors; session and browser/device properties support Web Analytics. No person profiles are created. Event URLs contain only the landing-page origin and /, without query strings or fragments. Referrers, form contents, automatic clicks, errors, and recordings are excluded; traffic-source attribution and geographic reports are therefore limited. The proxy receives the browser’s source IP, while event properties disable IP-based enrichment.

This covers the landing page only, not docs, converted posts, or admin. API events remain separate from browser visits. Existing Vercel Web Analytics on the public landing page is unchanged. The admin dashboard includes no analytics scripts.

Optional configuration

Variable Purpose
FIRECRAWL_API_KEY Conversion fallback and degraded Latest/Top search
CONTEXT_DEV_API_KEY Additional post-conversion fallback
CACHE_TTL_SECONDS Cache lifetime; default 3600
CACHE_DISABLED Disable application caching
CACHE_PERSIST Control persistent application caching

Last updated on September 9, 2026

Was this page helpful?