Internal ProcessPublishing Surface
Canonical · VerifiedUpdated 2026-05-03Verified against code 2026-05-03

Publishing Surface

This file documents the decision on where the knowledge hub is rendered and shared. Linear: NUD-246.

Decision (2026-05-03)

Single surface: Nextra on Vercel, password-protected.

Source of truth lives here, in this repo (docs/knowledge/). The Nextra site reads from this directory and renders it to a polished web hub at an internal URL.

Why this and not the alternatives

OptionVerdictReason
Nextra on Vercel + Password Protection✅ ChosenStack-aligned (Next.js, Vercel — same as our 3 frontends). Vercel Pro deployment protection is included in our existing plan: $0 incremental cost. Single shared password = no per-seat friction for non-eng team. ~2 hr scaffold.
GitHub Pages (private)❌ RejectedRequires GitHub Enterprise Cloud (~$21/user/month, +$1,400/yr for our team). Pages on Free/Pro/Team plans are public on the internet even from a private repo. Not worth the upgrade for one capability.
GitHub Pages (public)❌ RejectedHub contains internal-only content (sales playbook, competitor research, MEMORY-grade detail). Not suitable for public exposure.
Notion mirror❌ SkippedWould have been the GTM-friendly option, but the team isn’t on Notion. Nextra serves both audiences if formatted for mixed readership.
Public /learn site on nudg3.ai⏸️ DeferredRight surface for geo/ and guides/ content once those epics ship. Not now — empty nav tabs hurt more than no site. Will revisit when NUD-242 + NUD-243 produce ≥10 customer-facing docs.

Architecture

docs/knowledge/             ← source of truth (markdown + frontmatter)
  product/, architecture/, geo/, guides/, reference/, _meta/

            ▼  (git submodule or sync script)
nudg3-knowledge-site/       ← separate standalone repo, Nextra app
  content/  → reads from docs/knowledge
  _meta.json files → sidebar nav order + labels
  components/StatusBadge.tsx → renders frontmatter status/accuracy as coloured pill

            ▼  (Vercel auto-deploy on push)
learn.internal.nudg3.ai     ← password-protected Vercel deployment

Why standalone repo, not inside nudg3-frontend-combined

Considered putting this as apps/knowledge inside the existing Turborepo. Decided standalone for three reasons:

  1. Submodule of nudg3-docs-internal is much cleaner in a single-purpose repo. Submoduling into one workspace of a Turborepo fights pnpm workspace resolution and surprises any engineer running git clone --recursive on the wrong thing.
  2. Different editorial workflow. Content writers edit markdown in nudg3-docs-internal; the Nextra repo itself only gets touched twice a year for theme/version bumps. Doesn’t belong next to React product code that ships weekly.
  3. Blast radius isolation. A bad next.config.mjs here can’t break the dashboard, admin, or landing builds.

When the public nudg3.ai/learn surface eventually ships (Phase 3, deferred), that one does belong in nudg3-frontend-combined — it’s brand-coupled and shares design system with landing. Likely as apps/learn or a route on apps/landing. Two surfaces, two repos, two audiences.

Auth model

Cloudflare Access (free tier) at the domain layer in front of Vercel:

  • Identity provider: One-time PIN (Cloudflare emails a 6-digit code; no external IdP needed)
  • Policy: emails ending in @nudg3.ai and @agenticza.com allowed
  • Session: 24 hours, then re-auth
  • Free for up to 50 users
  • $0 incremental cost
  • DNS: learn.internal.nudg3.ai CNAME → Vercel target, proxy ON (orange cloud) so Cloudflare can intercept
  • Cloudflare SSL mode: Full (strict) — CF validates Vercel’s TLS cert; user sees CF’s edge cert

Why not the alternatives:

  • Vercel Password Protection: paywalled at $150/mo (Advanced Deployment Protection add-on, verified 2026-05-03)
  • Vercel Standard Protection (Vercel team auth): free on Pro but requires every reader to be on the Vercel team; new seats $20/mo each
  • Next.js middleware basic auth (initial approach): worked, but the browser-modal UX (username:password) felt clunky for non-eng team. Removed in favour of CF Access magic-link UX.

The raw *.vercel.app deployment URL bypasses CF Access (CF only protects the custom domain). Acceptable risk for an internal docs site since the URL is unguessable and never shared. If it becomes a concern, re-add middleware with SITE_PASSWORD env var as a backstop, or restrict Vercel deployments to the custom domain only.

Sync model

Two viable patterns; pick one when standing the site up:

  1. Git submodulenudg3-knowledge-site repo includes this docs repo as a submodule. Vercel build pulls latest on every deploy. Cleanest; one source of truth, zero copy.
  2. Manual copy — copy verified docs across when a doc is promoted from draftverified. Fine for the first few weeks while content moves slowly.

Default to submodule once the site is live. Manual is the bootstrap.

Promotion workflow

When a doc moves from draftverified in this repo:

  1. Update frontmatter (status, accuracy, verified_against_code)
  2. Commit + push to docs master
  3. Trigger a Vercel redeploy (manual button or auto on submodule update)
  4. Drop a one-line note in #docs Slack channel

That’s the entire publishing pipeline. No CMS, no review queue, no separate publishing branch.

Status badge convention

Every page in the rendered Nextra site shows a coloured pill at the top derived from frontmatter:

StatusAccuracyPillMeaning
canonicalverified🟢 greenTrustworthy. Quote freely internally.
reviewverified🔵 blueVerified content, awaiting second-pair-of-eyes review. Trustworthy in spirit.
draftunverified🟡 yellowUnder construction. Read for context, do not quote externally.
anyoutdated🔴 redBehaviour changed since this was written. Do not trust.

Implemented as a single MDX component in the Nextra site reading the frontmatter exposed by nextra/page-map. Rough scope: ~20 lines.

What this is NOT

  • Not a public website. That’s a separate decision (NUD-246 follow-up) for when GEO + Guides content matures.
  • Not a CMS. Edits happen in markdown files in this repo, in your editor, like any other code.
  • Not a customer-facing surface. Customers eventually see a different, public-facing hub built from a curated subset of this content.

Action checklist (separate ticket)

Tracked in NUD-246. Roughly:

  1. Scaffold Nextra app under nudg3-knowledge-site/ (~1 hr)
  2. Wire _meta.json for sidebar nav (~15 min)
  3. Build StatusBadge.tsx MDX component (~30 min)
  4. Push to GitHub under NUDG3-AI org
  5. Connect to Vercel + enable Password Protection
  6. Add learn.internal.nudg3.ai custom domain (DNS in Cloudflare)
  7. Pin URL + password in #general or #gtm Slack