← Changelog

Initial pass at a Lossless Flavored Markdown splash page

LFM gets its own GitHub Pages landing page — three-stage STC diagram, asymmetric hero, manuscript-flavored type, and a package boundary that won't let the splash bleed into JSR.

Why Care?

A README is a starting line, not a story. LFM has a real one — a polyglot extended-markdown pipeline that lets authors keep authoring in whatever syntax their tool prefers, and that converges every variation onto one canonical AST your renderer can dispatch on. That story doesn’t fit in a code block.

So LFM now has a splash. A small Astro site at splash/ that ships to GitHub Pages on every push to main, gives the package its own public face, and renders the changelog/ and context-v/ directories alongside the marketing copy. Free hosting, fast deploys, and — critically — zero risk to the JSR or npm package. Both publish allowlists exclude splash/ by construction.

The splash also lets us show what LFM is for, not just tell. The hero centerpiece is a three-stage diagram of what we’re calling the STC paradigm — Syntax → Trigger → Component — with a worked example panel underneath that’s collection-driven, so adding the next live example is a single markdown file under src/content/stc-examples/. Today’s example: video embeds (bare YouTube share URL or :::youtube-share[...] directive → remark-link-preview.ts → a YouTube embed component).

What’s New?

  • splash/ directory at the repo root with a complete Astro site: hero, STC diagram, curated feature gallery (7 cards), changelog list + detail, context-v list + detail (grouped by subdirectory).
  • A STC paradigm diagram component (StcDiagram.astro) with the three-stage flow, printer’s-mark corner ticks, and a worked-example panel populated from a content collection.
  • A two-tier-token + three-mode theme following the Astro Knots convention — but visually distinct from sibling splashes:
    • Light is the default (“writer’s mode”). LFM is a reading + writing tool first; paper makes sense first.
    • Dark is the operator mode. Vibrant is the demo mode.
    • Brand spine pivots away from cyan: ink-violet, sienna, moss.
    • Type pivots away from Inter/Fraunces: Newsreader serif headlines, Manrope body, JetBrains Mono kept.
  • Lenient content schemas (zod preprocessors) so frontmatter that’s been authored across many months doesn’t make a single bad date crash the build. If a schema can’t validate, the loader stores raw frontmatter and warns instead of throwing.
  • A tiny YAML-subset frontmatter parser (src/loaders/frontmatter.ts, ~150 lines, no gray-matter) honoring the Astro Knots tech hierarchy: fewer dependencies is always better.
  • GitHub Pages workflow at .github/workflows/pages.yml — actions/deploy-pages@v4 with enablement: true so the workflow bootstraps Pages on first run.
  • Repo-root .gitignore — the package didn’t have one yet, and dist/ + node_modules/ had been showing as untracked.

Both builds verified locally: pnpm build (parent tsup) produces the same 12-entry dist/ it did before; pnpm build (splash) produces 5 HTML pages cleanly.

How the splash stays out of the published package

This was the design constraint that mattered most. LFM publishes to JSR (canonical) and a GitHub Packages npm mirror — both with explicit allowlists, so nothing under splash/ ever ships to a registry:

ChannelDefined inAllowlistSplash files?
JSR (canonical)deno.json → publish.includesrc/**/*.ts, src/**/*.md, deno.json, LICENSE, README.mdexcluded
npm mirrorpackage.json → "files"src, dist, README.md, LICENSEexcluded
Build (tsup)tsup.config.ts → entryhard-coded src/...ts pathsexcluded

splash/package.json carries "private": true as defense-in-depth — keeps the directory off any registry even if npm publish were ever run from inside it. The boundary is enforced by the allowlists, not by private; the private flag is the suspenders to the allowlist’s belt.

The shape on disk

lfm/
├── .gitignore                          ← new (repo had none)
├── .github/workflows/pages.yml         ← deploy splash on push to main
└── splash/
    ├── astro.config.mjs                base: '/lossless-flavored-markdown-package/'
    ├── package.json                    private: true · "lfm-splash"
    ├── tsconfig.json                   path aliases
    ├── README.md                       local dev, deploy, curation
    ├── public/favicon.svg              ¶ mark in violet-ink
    └── src/
        ├── content.config.ts           lenient schemas; reads ../changelog & ../context-v
        ├── loaders/frontmatter.ts      ~150-line YAML-subset parser
        ├── lib/{seo.ts, date.ts}
        ├── styles/{theme.css, prose.css}
        ├── layouts/BaseLayout.astro
        ├── components/
        │   ├── Header.astro
        │   ├── MetaTags.astro
        │   ├── ModeToggle.astro
        │   ├── StcDiagram.astro        ← the centerpiece
        │   └── FeatureCard.astro
        ├── pages/
        │   ├── index.astro             hero + STC + gallery + recent
        │   ├── changelog/{index, [...slug]}.astro
        │   └── context-v/{index, [...slug]}.astro
        └── content/
            ├── feature-highlights/     7 cards
            └── stc-examples/           1 today (video-embeds)

Visual divergence — and why

Sibling splashes lean dark-by-default with a cyan-led brand spine, radial-mesh backgrounds, and centered hero composition. LFM’s splash deliberately diverges:

  • Asymmetric hero — copy left, STC diagram dominant on the right at desktop widths. The diagram is the message; the diagram gets the real estate.
  • Manuscript margin — a single hairline rule at the left edge of the viewport (hidden on narrow screens). It’s a tiny ornament that signals: this is a reading surface.
  • Squarer card chrome — --radius-md: 4px (the sibling splashes use 8–12px). Cards feel printed instead of glassy. Printer’s-mark corner ticks on the STC panel reinforce that.
  • Italic display weight on the brand line — Newsreader’s italic at weight 400 sets a different tone than memopop-site’s bold sans headlines.

Same data-mode contract. Same lenient schemas. Same content collection structure. Same component composition. Different voice.

Open follow-ups

  • First deploy — push to main and flip the GitHub Pages source to “GitHub Actions” in repo settings. The workflow uses enablement: true so it’ll bootstrap, but the source toggle is one-time-manual.
  • Seed context-v/ — there’s no context-v/ directory yet; the splash renders an empty-state gracefully and will start grouping by subdirectory (specs / habits / prompts / explorations) the moment files land there. We have legacy LFM context to pull in.
  • Render through LFM itself — currently the splash uses Astro’s built-in render(entry).Content for changelog/context-v bodies. Wiring it to render through remarkLfm would be a satisfying dogfooding loop and a tracked roadmap candidate.
  • More STC examples — callouts, citations, bare-link unfurls. Each one is a src/content/stc-examples/<name>.md file plus a swap of the featured flag.
  • Pagefind? — sibling splash memopop-site has it; we skipped it for v1 because LFM’s surface is small. Easy to add later.

See also

  • The habit: lossless-monorepo/context-v/habits/Maintain-a-Github-Splash-Page-for-each-Repo.md
  • The reference splash: content-farm/splash/
  • The first-instance splash (predates the habit): ai-labs/memopop-ai/apps/memopop-site/