Skip to content

feat: plain Astro support, and the smoke suite run against the packed package - #17

Merged
kieronlanning merged 5 commits into
mainfrom
feat/plain-astro-support
Nov 6, 2026
Merged

kieronlanning merged 5 commits into
mainfrom
feat/plain-astro-support

Conversation

@kieronlanning

Copy link
Copy Markdown
Contributor

What this does

Three things in one PR, because they share one test story: the package can now be
used from plain Astro, the dev-only hydration bug is fixed, and test:site
proves both from the packed tarball instead of from dist/ sitting beside the
repository.

1. @purview-dev/astroc4/integration — plain Astro, first class

src/integration.ts holds everything that was always Astro-only: LikeC4's Vite
plugin, the fence transform, the Windows preload, the react/compiler-runtime fix.
src/index.ts is now the Starlight layer that calls it (i18n injection,
expressiveCode, Starlight's plugin context). Both entry points therefore cannot
drift.

import astroc4 from '@purview-dev/astroc4/integration';
export default defineConfig({ integrations: [expressiveCode(), astroc4(), mdx()] });

Three Starlight assumptions had to go:

  • Astro.locals.t is read as unknown — App.Locals is an empty interface
    without Starlight's augmentation, so a site that type-checks the components
    without Starlight now passes instead of failing with TS2339.
  • Colours moved to a --likec4-* layer that defaults to --sl-color-* and to
    scheme-neutral fallbacks, so a plain page is legible rather than transparent.
  • Integration-time warnings go through Astro's logger
    (logger.fork('likec4-fences')), not console.

The integration also adds @astrojs/react when the site has not, because the
islands are client:only="react". It deliberately does not add
@astrojs/mdx or astro-expressive-code: those change the host's content types
and every code block, so they stay the site's decision (and a fence in a .md
page now says "add MDX" instead of "rename the page", which could not work).

examples/astro is a runnable plain-Astro site — bun run dev:astro, port 4322 —
with a project view, an inline fence and ec.config.mjs highlighting.

2. The dev-only hydration bug

likec4/react is React-Compiler-built and imports c from React 19's CommonJS
react/compiler-runtime; dev served it raw and every island died with
does not provide an export named 'c' while astro build stayed green. The
integration now adds the dependency to vite.optimizeDeps.include (only entries
the site lacks — Astro concatenates Vite arrays).

3. test:site runs the real smoke suite on the packed package

It installs the tarball into copies of both host sites — playground/ and
examples/astro/ — and then runs astro check, astro build, the full
scripts/smoke.ts suite against the Starlight copy on its preview server, a
dev-server hydration check against the plain-Astro copy, and a rebuild of that copy
with the exact config astro add writes. scripts/hydration.ts is the shared
browser check (rendered node, no visible placeholder, no console errors, frame is
styled).

Verified locally

Check Result
bun run test 136 passed, 2 skipped
bun run check playground 37 files 0 errors · examples/astro 19 files 0 errors · tsc scripts clean
bun run build + bun scripts/smoke.ts passed
bun run test:site both consumer sites: check, build, full smoke suite on the packed Starlight copy, hydration on the plain copy, astro add shape
Negative test with the optimizeDeps entry removed and .vite cleared, the check reports the three does not provide an export named 'c' errors, 0 nodes and a visible placeholder
Negative test with the Astro.locals cast reverted, examples/astro's astro check fails with TS2339: Property 't' does not exist on type 'Locals'

Notes for reviewers

  • package.json is bumped to 1.0.0-prerelease.5, so merging this publishes
    the prerelease and tags it (release.yml).
  • astro add works now. The default export carries the Astro
    astro:config:setup hook as well as the Starlight plugin hooks; the two sets are
    disjoint, so integrations: [astroc4()] (what the CLI writes) renders diagrams,
    and a Starlight site that ends up with that shape gets a warning naming
    starlight({ plugins: [astroc4()] }).
  • A previous claim is corrected, not just re-documented: astroc4() and
    astroExpressiveCode() work in either order (tested), and examples/astro now
    lists Expressive Code first so it stays true.
  • @astrojs/starlight is an optional peer now; a plain Astro site never loads it.

Checklist

  • bun run test
  • bun run check
  • bun run build and bun scripts/smoke.ts
  • bun run test:site (needs Chromium)
  • Docs updated: README, guide/Plain-Astro.md, Components, Configuration
    Reference, Getting Started, Architecture, Local Development, Repository
    CI/CD, AGENTS.md, CHANGELOG

`@purview-dev/astroc4/integration` is now a published entry point: the same LikeC4
Vite plugin, fence transform, Windows preload and dependency fix the Starlight
plugin installs, because both call the new `src/integration.ts`. The default export
keeps working for `starlight({ plugins: [astroc4()] })` and also carries the Astro
`astro:config:setup` hook, so the `integrations: [astroc4()]` that `astro add`
writes produces a working site — and warns when it lands on a Starlight site,
where the translations and the highlighting cannot run.

Three Starlight assumptions had to go: `Astro.locals.t` is read as `unknown`
because `App.Locals` is an empty interface without Starlight's augmentation,
colours moved to a `--likec4-*` layer that falls back to scheme-neutral values so
a plain Astro page is still legible, and the fence warning goes through
`logger.fork('likec4-fences')` instead of `console`. The integration also adds
`@astrojs/react` when the site has not, since the islands are
`client:only="react"` and a site without a renderer builds and then draws nothing.
`@astrojs/mdx` and `astro-expressive-code` stay the site's decision.

`examples/astro` is a runnable plain-Astro site (`bun run dev:astro`, port 4322):
one page, one model, an inline fence and `ec.config.mjs` highlighting.

Bumps to 1.0.0-prerelease.5.
`test:site` installs the tarball into copies of both host sites instead of into a
hand-written page: `playground/` (Starlight) and `examples/astro/` (plain Astro).
The Starlight copy gets `astro check`, `astro build` and then the full
`scripts/smoke.ts` suite on its preview server — hydration, drawn nodes, icons,
highlighting colours, the loading placeholder and both locales — so those are
proven on the artifact a user installs, not on `dist/` beside the repository. It
then rebuilds the plain-Astro copy with the exact config `astro add` writes.

`scripts/hydration.ts` is the shared browser check: it waits for a rendered LikeC4
node, fails while the `.likec4-loading` placeholder is still visible, fails on any
console error, and can assert the frame is styled. The CI site job installs
Chromium for it.
The README and a new `guide/Plain-Astro.md` cover the two registrations and say
what `astro add` writes; `guide/Components.md` documents the `--likec4-*` tokens,
`guide/Configuration-Reference.md` marks `highlighting` as Starlight-only, and the
contributing pages record the two entry points, the logger convention, the
integrations-library keywords and the new `test:site`.

Also corrects the claim that `astroc4()` must precede `astroExpressiveCode()`:
tested, they work in either order (Astro applies a processor's mdast plugins and
the site's `markdown.rehypePlugins`), and `examples/astro` now lists Expressive
Code first so that stays true. The changelog records the release as
1.0.0-prerelease.5.
The job installs the tarball into copies of both host sites, builds them, runs the full smoke suite, a dev-server hydration check and the astro add rebuild, and finishes in about 85 seconds on ubuntu-latest. The 35-minute ceiling was sized from a Windows run, where two bun installs alone take half a minute each.
The smoke suite itself takes about nine seconds on ubuntu-latest; the browser download in front of it is the slowest and only variable step (twenty seconds usually, minutes when the CDN stalls, which is what held the first run of this PR open). Both jobs now restore ~/.cache/ms-playwright keyed on the lockfile, so whichever runs second downloads nothing.
@kieronlanning
kieronlanning merged commit ec7a375 into main Nov 6, 2026
4 checks passed
@kieronlanning
kieronlanning deleted the feat/plain-astro-support branch November 6, 2026 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant