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(kindguide) andcontent/pages/{about,thesis,pitch,faq,glossary}.md(one file per singleton kind). loadEditorialContent()(server/editorialContent.ts) parses every file; onlystatus: approveddocuments entercontent.approvedand the manifest.statusmust bedraftorapproved(EDITORIAL_STATUSES).- A draft that fails validation is skipped with a warning; an approved file that fails stops the
build.
validateEditorialRoutes()inserver/seoRouteManifest.tsre-checks that every editorial route has an approved document, and that/guidesexists 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),assertPublicTextrestricted-term policy,{{facts.<key>}}placeholders limited toEDITORIAL_FACT_KEYS. - Preview drafts:
pnpm content:preview(scripts/preview-editorial.ts) renders every file, drafts included, throughrenderEditorialDocument()intodist/preview/editorial/{kind}/{slug}.html(never deployed) and prints status, word count, floor, errors and unresolved links. - Only the owner flips
status: drafttostatus: 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/guidesincontent/pages/site-titles.yaml. - React pages:
server/publicPages/{about,thesis,faq,glossary,lessons}.tswithclient/src/publicPages/{About,Thesis,Faq,Glossary,Lessons}Page.tsx,*Types.ts,styles/{about,thesis,faq,glossary,lessons}.css; copy incontent/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
/pitchonce 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./thesisReact 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 fromtargetQueries;FAQPagewhenfaqsexist;ogType: article; lastmod fromlastReviewed./guidesis a CollectionPage with an ItemList. /faqas a menu page addsFAQPagefromfaqPageQuestions. Menu-page descriptions come fromRECOVERY_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_KEYShas 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
- Implement
server/editorialContent.ts(schema, gates, approved filter, fact substitution). - In
createSeoRouteManifest()add/guidesplus oneguideroute per approved guide and one route per approved singleton; callvalidateEditorialRoutes()increateRenderContext(). - Add
renderEditorialDocumentandrenderGuidesIndexPageand dispatch them inrenderRouteDocument(); words incontent/pages/editorial-pages.yaml. - Add
scripts/preview-editorial.tsand thecontent:previewscript inpackage.json. - Build the React pages (
new-react-pageskill) for about, thesis, faq, glossary, lessons and map them inreactPageForRoute()/SINGLE_PAGES. - Write Markdown as
status: draft, runpnpm content:preview, wait for owner approval. deploy-gate, thenui-before-after, thenship-to-production.