Posts API (Option B): host published blog and seed from CL8Y-web #2
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Ship Option B (approved):
cl8y-researchis the source of truth for published blog posts. A public read API serves list/post/RSS/hero.CL8Y-webstops taking per-post MDX merge requests. Seed the store from the existing cl8y.com post in~/repos/CL8Y-web.Companion consumer work lives in CL8Y-web and is blocked until this API is up (
GET /v1/postsreturns the seeded roadmap post and/healthis green).Gap analysis:
gaps/GAP_1788152435.md§3.3. Original worker: #1.Current codebase
CL8Y-webis a static Vite SPA. Posts are MDX insrc/blog/posts/*.mdx, indexed byimport.meta.glob+virtual:blog-post-meta, prerendered to/blogand/blog/:slug, RSS viascripts/generate-rss.mjs.There is one published post:
cl8y-roadmap-cmm-bridge-yieldomega(2026-05-10)CL8Y-web/src/blog/posts/cl8y-roadmap-cmm-bridge-yieldomega.mdxCL8Y-web/public/images/blog/cl8y-roadmap-cmm-bridge-yieldomega-hero.jpgThis worker emits
runs/<week>/post.mdx+publish-mr.mdcopy instructions.src/publish.rsbuilds an in-memoryDraftMr(auto_merge: false) and never talks to GitLab. There is no HTTP server, nopoststable, no publish approval command.wordCountis computed at site build today. After Option B it must be computed at publish in this repo (still never authored by the model).Why this is needed
Every weekly draft is a marketing-site MR, full
yarnCI, Puppeteer prerender, and review of 2000-word MDX in a repo whose job is positioning and token directory. That is the time sink. Hosting approved posts here keeps secrets and generation off the SPA and letsCL8Y-webstay a fetcher.Existing visitors must not lose the roadmap post when the glob goes away. Import it (body + frontmatter + hero bytes) as the first
publishedrow.Constraints / guardrails
status = publishedonly. Drafts stay private (operator/CLI). Humanpublish(CLI or authenticated admin) is required.CL8Y-webmainor auto-merge. Per-post MDX MRs are retired after the consumer issue ships; this issue does not edit the Vite app except via the linked CL8Y-web ticket.RETIRED_HOMEPAGE_MODULESor rewriteCL8Y_WHITEPAPER.md.title,description,slug,date,author,image,tags. Never store authoredwordCount; compute it on publish from body./images/blog/<slug>-hero.jpg(API may serve the bytes). Neversrc/blog/assets.published.REPLICATE_,BOT_TOKEN,api_key,BEGIN).https://cl8y.comandhttps://www.cl8y.comonly (plus localhost for dev). Rate-limit public GETs.Relevant files
src/publish.rssrc/mdx.rssrc/lint.rssrc/pipeline.rspost.mdx+publish-mr.mdsrc/store.rs/migrations/001_init.sqldocs/blog-contract.mdCL8Y-web/src/blog/blogIndex.tsCL8Y-web/src/blog/posts/cl8y-roadmap-cmm-bridge-yieldomega.mdxCL8Y-web/public/images/blog/cl8y-roadmap-cmm-bridge-yieldomega-hero.jpgRecommended direction
--features postgres(or aserverfeature): bindAPI_BIND(default0.0.0.0:8080).posts(slugunique,statusdraft|published, frontmatter columns,body_mdx,word_count,published_at,hero_bytesor object storage path). Reuse Postgres from the store issue.GET /healthandGET /ready(see Coolify/health issue; stub here if that issue is later)GET /v1/posts— published list, newest firstGET /v1/posts/:slug— published body + metaGET /v1/rss.xmlGET /v1/images/blog/:slug-hero.jpgcl8y-research import-web --from <CL8Y-web checkout>seeds the roadmap post as published.cl8y-research publish --slug <s>promotes a pipeline draft after lint.runs/+ ingest) instead of instructing an MDX copy.Do not put Replicate/Telegram tokens on public routes.
Acceptance criteria
GET /v1/postslists the seededcl8y-roadmap-cmm-bridge-yieldomegawith required meta (nowordCountauthored in MDX; numericwordCountin JSON is computed).GET /v1/posts/cl8y-roadmap-cmm-bridge-yieldomegareturns body equivalent to the current MDX (modulo computed fields).GET /v1/images/blog/cl8y-roadmap-cmm-bridge-yieldomega-hero.jpgreturns a JPEG (image/jpeg).GET /v1/rss.xmlincludes that item with title, description,/blog/<slug>link (canonical host configurable).publish.curlagainst compose./healthis 200 and the seeded post is listed.Test plan — functional paths
reqwestto bound server).weekly-secret; public GET list/get/RSS omit it; 404 on get.Origin: https://cl8y.comallowed;Origin: https://evil.testnot./health200 without DB;/ready200 only with DB (or document if combined).Test plan — attack, hack, and abuse
statusfilter query that returns drafts.GET /v1/images/blog/../../.envrejected.<script>that sanitize would have stripped; Content-Typeapplication/json(not HTML) for post GET.javascript:links.REPLICATE_API_TOKEN=fails publish.Hostfrom the client./health.--force.Verification criteria
A reviewer can:
docker compose up -d+ migrate +import-webfrom a CL8Y-web checkout (or fixture).curllist/get/RSS/hero and see the 2026-05-10 roadmap post.weekdraft is absent from public GET until publish.mentioned in issue #4
mentioned in issue CL8Y-web#7
marked as related to CL8Y-web#7
marked as related to #7
marked as related to #9