sahin.io

All skills and agents

page-editorial

The owner-reviewed editorial pages on sahin.io/angel-investments (Guides index and guides, Thesis, About, FAQ, Glossary, Pitch, Lessons) and the editorial status gate (Markdown drafts publish only with status approved; preview with pnpm content:preview). Use when writing, approving, building, rebuilding or changing any of these pages or the editorial pipeline.

Source file
.claude/skills/page-editorial/SKILL.md
Routes covered
/guides/guides/*/thesis/about/faq/glossary/pitch/lessons

Editorial pages

Routes

URL Kind today Render
https://sahin.io/angel-investments/guides guidesIndex static (renderGuidesIndexPage)
https://sahin.io/angel-investments/guides/{slug} (3 today) guide static (renderEditorialDocument)
https://sahin.io/angel-investments/thesis thesis both: static article + React thesis page above it
https://sahin.io/angel-investments/about reactPage React about (SINGLE_PAGES)
https://sahin.io/angel-investments/faq legacyFeature React faq
https://sahin.io/angel-investments/glossary legacyFeature React glossary
https://sahin.io/angel-investments/lessons legacyFeature React lessons
https://sahin.io/angel-investments/pitch none until content/pages/pitch.md is approved static

Today's approved guides: angel-investment-methodology, founder-research, portfolio-outcomes. Kinds depend on approval: an approved singleton (about, thesis, pitch, faq, glossary) takes its path from the menu (reviewedSingletonPaths in createSeoRouteManifest()), so its kind becomes the editorial kind. React wins the body whenever reactPageForRoute() returns a page; the approved article is then embedded under it (editorialArticle() in server/publicReactDocument.ts).

The editorial status gate

  • Source: Markdown with YAML frontmatter in content/guides/*.md (kind guide) and content/pages/{about,thesis,pitch,faq,glossary}.md (one file per singleton kind).
  • loadEditorialContent() (server/editorialContent.ts) parses every file; only status: approved documents enter content.approved and the manifest. status must be draft or approved (EDITORIAL_STATUSES).
  • A draft that fails validation is skipped with a warning; an approved file that fails stops the build. validateEditorialRoutes() in server/seoRouteManifest.ts re-checks that every editorial route has an approved document, and that /guides exists only with at least one approved guide.
  • Gates on every file: frontmatter keys (slug, kind, title, description, h1, targetQueries, faqs, sources, factsUsed, lastReviewed, status), title at most 60 and description at most 155 characters, word floors (EDITORIAL_WORD_FLOORS: guide 1200, about 800, thesis 2000, pitch 700, faq 1200, glossary 1200), assertPublicText restricted-term policy, {{facts.<key>}} placeholders limited to EDITORIAL_FACT_KEYS.
  • Preview drafts: pnpm content:preview (scripts/preview-editorial.ts) renders every file, drafts included, through renderEditorialDocument() into dist/preview/editorial/{kind}/{slug}.html (never deployed) and prints status, word count, floor, errors and unresolved links.
  • Only the owner flips status: draft to status: approved. Never approve on his behalf.

Files

  • Pipeline: server/editorialContent.ts (loadEditorialContent, approvedGuides, findEditorialDocument, substituteEditorialFacts, resolveInternalLinks, FAQ_SLOT).
  • Static renderers in server/seoRouteManifest.ts: renderEditorialDocument, renderGuidesIndexPage, renderEditorialCta, renderThesisRecognition.
  • Chrome words: content/pages/editorial-pages.yaml (eyebrows, nav labels, CTA, FAQ and sources headings, guides index); title for /guides in content/pages/site-titles.yaml.
  • React pages: server/publicPages/{about,thesis,faq,glossary,lessons}.ts with client/src/publicPages/{About,Thesis,Faq,Glossary,Lessons}Page.tsx, *Types.ts, styles/{about,thesis,faq,glossary,lessons}.css; copy in content/pages/{about,thesis,faq,glossary,lessons}.yaml.
  • Menu entries: content/shared/navigation.yaml (thesis, lessons, glossary, faq).

Sections on the page

  • Static article: breadcrumb (hub, Guides for guides), eyebrow, H1, "Updated {date}", answer-first intro, thesis recognition aside, prose with FAQ at the FAQ slot, sources list, CTA (to /pitch once it exists, else hub plus deck email), related public pages, back link.
  • /guides: list of approved guides with title, description, updated date; CTA; related pages.
  • /thesis React part: stat tiles, public companies, market and stage mix, notable companies; the approved essay sits under it.
  • /about, /faq, /glossary, /lessons: sections defined by their YAML shapes.

SEO

  • Editorial kinds: page entity Article (pageEntityType) with headline, dates, word count, keywords from targetQueries; FAQPage when faqs exist; ogType: article; lastmod from lastReviewed. /guides is a CollectionPage with an ItemList.
  • /faq as a menu page adds FAQPage from faqPageQuestions. Menu-page descriptions come from RECOVERY_SURFACE_BY_PATH / MENU_DESCRIPTION_FEATURES.
  • Drafts are never in the sitemap, llms files or IndexNow.

Rules

  • Editorial gate above; numbers in prose only via {{facts.*}} placeholders (portfolio-counts-single-source). EDITORIAL_FACT_KEYS has no return figure, so Markdown prose never states one; never a per-company return.
  • Prose links only to manifest routes; unresolved links are rewritten to the hub.
  • No private deal data (private-data-boundary); copy in YAML/Markdown (page-content-yaml).

Tests

server/editorial-content.test.ts, server/seo-route-manifest.test.ts, server/keyword-[redacted].test.ts, server/content-in-yaml.test.ts, server/public-link-graph.test.ts, server/llms-text.test.ts, server/sitemap.test.ts.

Rebuild from scratch

  1. Implement server/editorialContent.ts (schema, gates, approved filter, fact substitution).
  2. In createSeoRouteManifest() add /guides plus one guide route per approved guide and one route per approved singleton; call validateEditorialRoutes() in createRenderContext().
  3. Add renderEditorialDocument and renderGuidesIndexPage and dispatch them in renderRouteDocument(); words in content/pages/editorial-pages.yaml.
  4. Add scripts/preview-editorial.ts and the content:preview script in package.json.
  5. Build the React pages (new-react-page skill) for about, thesis, faq, glossary, lessons and map them in reactPageForRoute() / SINGLE_PAGES.
  6. Write Markdown as status: draft, run pnpm content:preview, wait for owner approval.
  7. deploy-gate, then ui-before-after, then ship-to-production.