create-ailk 0.30.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -4
- package/component-catalog.json +524 -8
- package/component-catalog.md +8 -5
- package/dist/body-heading.d.ts +13 -0
- package/dist/body-heading.js +19 -5
- package/dist/cli.js +99 -0
- package/dist/cutover.d.ts +114 -0
- package/dist/cutover.js +511 -0
- package/dist/design-presets.js +20 -4
- package/dist/export-content.d.ts +55 -0
- package/dist/export-content.js +303 -0
- package/dist/inventory.d.ts +216 -0
- package/dist/inventory.js +833 -0
- package/dist/language-import.d.ts +127 -0
- package/dist/language-import.js +451 -0
- package/dist/lib/env-catalog.js +1 -1
- package/dist/lib/import-mdx.d.ts +38 -0
- package/dist/lib/import-mdx.js +445 -65
- package/dist/lib/render-comparison.d.ts +251 -0
- package/dist/lib/render-comparison.js +573 -0
- package/dist/mdx-braces.d.ts +73 -0
- package/dist/mdx-braces.js +285 -0
- package/dist/migrate-content.d.ts +6 -2
- package/dist/migrate-content.js +62 -14
- package/dist/programmatic.js +2 -8
- package/dist/seed-workspace.d.ts +3 -1
- package/dist/seed-workspace.js +45 -16
- package/dist/site-manifest.js +6 -38
- package/dist/site-roster.d.ts +46 -3
- package/dist/site-roster.js +124 -4
- package/dist/surfaces.d.ts +8 -0
- package/dist/surfaces.js +16 -0
- package/dist/topology.d.ts +12 -0
- package/dist/topology.js +24 -10
- package/dist/update.d.ts +21 -1
- package/dist/update.js +142 -11
- package/package.json +3 -3
- package/templates/.claude/cloudparity-repo-hooks.json +5 -0
- package/templates/.claude/hooks/content-source-guard.sh +75 -0
- package/templates/.claude/settings.json +9 -0
- package/templates/.github/workflows/ci.yml +4 -0
- package/templates/CLAUDE.md +5 -0
- package/templates/apps/mcp/.env.example +7 -1
- package/templates/apps/mcp/CLAUDE.md +8 -4
- package/templates/apps/web/.env.example +4 -2
- package/templates/apps/web/CLAUDE.md +16 -5
- package/templates/apps/web/__tests__/setup.ts +9 -0
- package/templates/apps/web/app/[locale]/[slug]/[detail]/__tests__/page.test.tsx +156 -4
- package/templates/apps/web/app/[locale]/[slug]/[detail]/page.tsx +45 -2
- package/templates/apps/web/app/[locale]/[slug]/__tests__/page.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/about/__tests__/about-routes.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/site-contact-lines.test.ts +49 -0
- package/templates/apps/web/app/[locale]/contact/site-contact-lines.ts +6 -4
- package/templates/apps/web/app/[locale]/events/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/events/__tests__/program-event.test.tsx +120 -0
- package/templates/apps/web/app/[locale]/events/page.tsx +11 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/FlowStepperClient.tsx +44 -5
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.thanks-by-tier.test.tsx +306 -0
- package/templates/apps/web/app/[locale]/layout.tsx +122 -27
- package/templates/apps/web/app/[locale]/pricing/[slug]/__tests__/page.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/pricing/__tests__/offerings.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/pricing/__tests__/page.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/pricing/__tests__/unconnected.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/team/__tests__/team-routes.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/thanks/[slug]/__tests__/page.test.tsx +21 -2
- package/templates/apps/web/app/[locale]/thanks/[slug]/page.tsx +1 -0
- package/templates/apps/web/app/llms.txt/route.ts +16 -9
- package/templates/apps/web/app/sitemap.xml/route.ts +3 -0
- package/templates/apps/web/jest.config.cjs +46 -1
- package/templates/apps/web/lib/__tests__/bot-check.test.ts +247 -4
- package/templates/apps/web/lib/__tests__/in-page-magnet-self-request.test.ts +92 -0
- package/templates/apps/web/lib/__tests__/page-chrome.test.ts +93 -0
- package/templates/apps/web/lib/__tests__/relay.test.ts +33 -8
- package/templates/apps/web/lib/__tests__/site-identity-feature-list.test.ts +196 -0
- package/templates/apps/web/lib/__tests__/structured-data.test.tsx +145 -11
- package/templates/apps/web/lib/bot-check.ts +113 -13
- package/templates/apps/web/lib/in-page-magnet.ts +4 -1
- package/templates/apps/web/lib/page-chrome.ts +65 -5
- package/templates/apps/web/lib/relay.ts +22 -3
- package/templates/apps/web/lib/site-identity.ts +75 -24
- package/templates/apps/web/messages/en.json +5 -1
- package/templates/apps/web/next.config.mjs +15 -1
- package/templates/apps/web/package.json +1 -1
- package/templates/apps/web/scripts/assert-content-bundled.ts +36 -8
- package/templates/apps/web/scripts/content-snapshot.ts +33 -0
- package/templates/apps/web/src/lib/routes.ts +5 -3
- package/templates/package.json +3 -1
- package/templates/tools/body-heading.ts +440 -0
- package/templates/tools/check-content-source.ts +108 -0
- package/templates/tools/check-mdx-body.ts +123 -0
- package/templates/tools/mdx-braces.ts +303 -0
- package/versions.json +48 -48
package/README.md
CHANGED
|
@@ -393,6 +393,15 @@ merge-file` against the recorded version's own copy as the base. A clean
|
|
|
393
393
|
**Added**, unless it sits under a route or directory the site deliberately
|
|
394
394
|
does not carry (a gated-off surface, a spoke exclusion, or a directory you
|
|
395
395
|
deleted entirely) — those are left alone.
|
|
396
|
+
- A surface no module owns (such as `projects`) that a page row of the
|
|
397
|
+
site's `.ailk-site-manifest.json` names, but `architecture.yaml` does not
|
|
398
|
+
declare, is in scope for adding: its route files are **Added** and
|
|
399
|
+
recorded, and `architecture.yaml` is regenerated to declare it. Reported
|
|
400
|
+
as **Surfaces declared from the roster**.
|
|
401
|
+
- A code-route row (`kind: "route"`) of `.ailk-site-manifest.json` that no
|
|
402
|
+
page file under `apps/web/app/[locale]/` serves (a spoke's `/sign-in`) is
|
|
403
|
+
dropped from the roster after the writes, every other byte of the file
|
|
404
|
+
kept. Reported as **Roster rows dropped, no route serves them**.
|
|
396
405
|
|
|
397
406
|
A file outside the gated-off surfaces and spoke exclusions the site's scope
|
|
398
407
|
no longer covers is **Skipped**, as is one that exists on disk but was never
|
|
@@ -425,7 +434,8 @@ never a shell. Fetching an old template version (when it is not the running
|
|
|
425
434
|
package's own) reads the public npm registry at
|
|
426
435
|
`https://registry.npmjs.org`, overridable with `AILK_NPM_REGISTRY_URL` for a
|
|
427
436
|
mirror. `update` never touches content, except to give an mdx-body page
|
|
428
|
-
with no `# ` heading its title and description
|
|
437
|
+
with no `# ` heading its title and description and to escape a bare `{` on
|
|
438
|
+
an mdx-body page (both below), nor env files,
|
|
429
439
|
`.claude/`, lockfiles or any `package.json` — those stay `add-module`'s and
|
|
430
440
|
the consumer version bump's job. Commit before running `update`, and review the diff after: a
|
|
431
441
|
clean merge is still worth reading.
|
|
@@ -444,6 +454,27 @@ folded `>` block, say), is listed under **Needs review** for you to fix.
|
|
|
444
454
|
Which pages are mdx-body is read from your own `apps/web/app` routes, and the
|
|
445
455
|
step runs again harmlessly on every update.
|
|
446
456
|
|
|
457
|
+
**Placeholder braces (#10773).** MDX reads a `{` in a page body as
|
|
458
|
+
JavaScript, so on an mdx-body page a bare placeholder such as
|
|
459
|
+
`{First engagement}` fails the page with a 500, and one that parses
|
|
460
|
+
(`{Tagline}`) renders as nothing. After the heading step, `update` writes a
|
|
461
|
+
`\` before every bare `{` on each mdx-body page — never in frontmatter, fenced
|
|
462
|
+
or inline code, a JSX tag or a `{/* … */}` comment — and keeps the page's
|
|
463
|
+
change only when your site's own MDX parser (the `@mdx-js/mdx` its
|
|
464
|
+
`next-mdx-remote` uses) then reads the page with no expression left but
|
|
465
|
+
comments. Each such page is listed under **Placeholder brace escaped**; one
|
|
466
|
+
byte per brace changes and nothing else. A page it cannot escape safely (a
|
|
467
|
+
mangled `{/ … /}` comment, or another MDX error the escape does not reach)
|
|
468
|
+
is left alone and listed under **Needs review** with the line, and so is
|
|
469
|
+
every page with a bare brace while the site's dependencies are not installed
|
|
470
|
+
(run `pnpm install`, then `update` again). A fresh scaffold also runs
|
|
471
|
+
`pnpm mdx-body:check` in `preflight` and CI, which names each bare brace by
|
|
472
|
+
file, line and column before a deploy. A site scaffolded before it gains the
|
|
473
|
+
check by copying `tools/check-mdx-body.ts`, `tools/mdx-braces.ts` and
|
|
474
|
+
`tools/body-heading.ts` from a fresh scaffold and adding
|
|
475
|
+
`"mdx-body:check": "tsx tools/check-mdx-body.ts"` to its `package.json`
|
|
476
|
+
scripts and `preflight`.
|
|
477
|
+
|
|
447
478
|
### Adopting an existing site
|
|
448
479
|
|
|
449
480
|
A site that create-ailk did not scaffold, or that was scaffolded before
|
|
@@ -558,7 +589,9 @@ On a site with an Admin (the `workspace` or `multi-tenant` module), the
|
|
|
558
589
|
starter's pages are also rows in the site's workspace, so the Admin's Docs
|
|
559
590
|
lists Home, About, Contact and every other roster page on first open.
|
|
560
591
|
`seed-workspace` writes them there: each `content/en/<Type>/<slug>.mdx` page
|
|
561
|
-
becomes one
|
|
592
|
+
becomes one `text/page` Artifact, set Live when it has no Live version. A page
|
|
593
|
+
already Live is never published over: a newer draft stays a draft for the
|
|
594
|
+
owner to set Live in the Admin.
|
|
562
595
|
|
|
563
596
|
```bash
|
|
564
597
|
AILK_AGENT_KEY=<agent key> create-ailk seed-workspace ./my-site --api-url <api origin> --workspace <wksp_id>
|
|
@@ -570,7 +603,9 @@ AILK_AGENT_KEY=<agent key> create-ailk seed-workspace ./my-site --api-url <api o
|
|
|
570
603
|
and the origin's source, before any request.
|
|
571
604
|
- The agent key is read from `AILK_AGENT_KEY` only — never a flag or a file —
|
|
572
605
|
and never printed. An owner issues it in the Admin with the `content-edit`
|
|
573
|
-
|
|
606
|
+
and `content-publish` grants. After the first refused publish, the rest of
|
|
607
|
+
the pages are saved as drafts and fail `not published`; a re-run with a
|
|
608
|
+
granted key publishes them.
|
|
574
609
|
- Each page prints `created`, `updated`, `unchanged`, `skipped` or `failed`,
|
|
575
610
|
then a count line. A re-run creates nothing and reports every page
|
|
576
611
|
`unchanged`. An agent writes ten times a minute, so a first seed of about
|
|
@@ -580,6 +615,15 @@ AILK_AGENT_KEY=<agent key> create-ailk seed-workspace ./my-site --api-url <api o
|
|
|
580
615
|
- The API must run with `content-write` and a tenancy module (`workspace` or
|
|
581
616
|
`multi-tenant`) in `AILK_ENABLED_MODULES`. Without them the content routes
|
|
582
617
|
are not served and every page fails `404`.
|
|
618
|
+
- When every page is in the workspace and Live, the site switches to the
|
|
619
|
+
database: `CONTENT_ADAPTER=database` is written to `apps/web/.env.local`
|
|
620
|
+
(which the web app reads) and to `apps/api/.env` (which the API that serves
|
|
621
|
+
the pages reads). Each app keeps a `CONTENT_ADAPTER` it already sets. A
|
|
622
|
+
skipped, refused or partial seed writes neither, and the site stays on
|
|
623
|
+
`content/` until a re-run succeeds.
|
|
624
|
+
- The API then serves the pages only when it runs on the database it was
|
|
625
|
+
seeded through (its `DATABASE_URL`) and its site resolves to the seeded
|
|
626
|
+
workspace.
|
|
583
627
|
- Exit 0 when every page was seeded, 1 when any failed, 2 on a refusal (no
|
|
584
628
|
`.ailk-site-manifest.json`, a spoke, a missing key, workspace id or origin,
|
|
585
629
|
the adapter not installed), which sends nothing.
|
|
@@ -610,6 +654,22 @@ scaffold time — a site with no `.ailk-site-manifest.json`, or a spoke — into
|
|
|
610
654
|
a workspace: each `content/en/<Type>/<slug>.mdx` page, and each legacy
|
|
611
655
|
`content/<Type>/<slug>.mdx` page, becomes one draft `text/page` Artifact.
|
|
612
656
|
|
|
657
|
+
When the site has the docs-blog tree `apps/web/content`, its posts and docs
|
|
658
|
+
are imported too (#10701): `apps/web/content/en/blog/<slug>.mdx` and
|
|
659
|
+
`blog/<slug>/index.mdx` become `BlogPosting/<slug>`, or one series down,
|
|
660
|
+
`blog/<series>/<post>.mdx` (or `<post>/index.mdx`), as a `BlogPosting/<post>`
|
|
661
|
+
whose `parent` is the series (#10775) — served at `/blog/<series>/<post>`, the
|
|
662
|
+
URL its file serves at; the same under `docs` become `DocsDetail/<slug>`, and
|
|
663
|
+
each directory's own `index.mdx` becomes its `BlogList/index` or
|
|
664
|
+
`DocsList/index` — replacing a `content/` teaser of that type. A blog post's
|
|
665
|
+
`parent` comes from its path, never its frontmatter, and a file the walk skips
|
|
666
|
+
is listed with the rule it failed. Their fumadocs frontmatter is mapped to
|
|
667
|
+
the stored fields (`date` →
|
|
668
|
+
`publishedAt`, `updated` → `updatedAt`); keys the store does not keep from a
|
|
669
|
+
caller (`featured`, `sidebar`, `tags`) are not sent, and `--apply` names them
|
|
670
|
+
in one line per file. Each outcome carries `root: "content"` or
|
|
671
|
+
`root: "editorial"`, and an editorial line is printed prefixed `editorial: `.
|
|
672
|
+
|
|
613
673
|
```bash
|
|
614
674
|
AILK_AGENT_KEY=<agent key> create-ailk migrate-content ./my-site --api-url <api origin> --workspace <wksp_id>
|
|
615
675
|
AILK_AGENT_KEY=<agent key> create-ailk migrate-content ./my-site --apply --api-url <api origin> --workspace <wksp_id>
|
|
@@ -669,6 +729,50 @@ diff -r before after && echo "live site unchanged"
|
|
|
669
729
|
A non-empty diff is a finding: stop and report it before migrating another
|
|
670
730
|
site.
|
|
671
731
|
|
|
732
|
+
### Cutting a site over to the database
|
|
733
|
+
|
|
734
|
+
Once a site's pages are in its workspace, three commands move it from its
|
|
735
|
+
page files to the database and back (#10648). Each reads the workspace with
|
|
736
|
+
`AILK_AGENT_KEY` (the `content-edit` grant), `--api-url`/`AILK_API_URL` and
|
|
737
|
+
`--workspace`/`AILK_WORKSPACE_ID`, as `migrate-content` does; a spoke also
|
|
738
|
+
needs `AILK_SPOKE_KEY`.
|
|
739
|
+
|
|
740
|
+
```bash
|
|
741
|
+
# 1. Freeze what the site serves today, and audit it. Commit both files.
|
|
742
|
+
create-ailk inventory . --origin https://example.com
|
|
743
|
+
# → .ailk-cutover/inventory.json (written once; --refreeze crawls again)
|
|
744
|
+
# → .ailk-cutover/audit.json (every run: per page, words in Markdown? published?)
|
|
745
|
+
|
|
746
|
+
# 2. Plan the cutover, then run it against a preview reading the database.
|
|
747
|
+
create-ailk cutover . --before https://example.com --after https://preview.example.com
|
|
748
|
+
create-ailk cutover . --before https://example.com --after https://preview.example.com --apply
|
|
749
|
+
|
|
750
|
+
# Rollback: every published page back to its file, published edits kept.
|
|
751
|
+
create-ailk export-content .
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
`inventory` freezes every URL the sitemap, a crawl and the route roster name,
|
|
755
|
+
with each page's prose status and images, and joins each page to its
|
|
756
|
+
workspace page — by the inventory's operator-written `joins`, the roster,
|
|
757
|
+
then `/blog` and the docs path. It exits 1 when any prose page is not
|
|
758
|
+
published or its words are not in its Markdown.
|
|
759
|
+
|
|
760
|
+
`cutover` runs import → publish → inventory → comparison → set env → deploy →
|
|
761
|
+
verify → remove files, in that order, and stops at the first step that fails.
|
|
762
|
+
The comparison renders every frozen page on both origins at 1440 and 390 wide
|
|
763
|
+
and records a text, JSON-LD and screenshot verdict for each, then sweeps every
|
|
764
|
+
frozen URL for a direct 200; it needs Playwright's Chromium in the site
|
|
765
|
+
(`pnpm add -D @playwright/test && pnpm exec playwright install chromium`).
|
|
766
|
+
Without `--apply` it sends only reads and writes and spawns nothing. The kit
|
|
767
|
+
never publishes: the publish step names the pages to publish in Admin. Step 8
|
|
768
|
+
stages the imported files' removal with `git rm`; you commit it. Each run's
|
|
769
|
+
record and screenshots go to `.ailk-cutover/runs/` (gitignored).
|
|
770
|
+
|
|
771
|
+
`export-content` writes each published page to the file `migrate-content`
|
|
772
|
+
reads it from, with its words moved back into its sections, so a re-run of
|
|
773
|
+
`migrate-content` reports every page `unchanged`. The full sequence, the
|
|
774
|
+
evidence each step leaves and each step's rollback are in the cutover runbook.
|
|
775
|
+
|
|
672
776
|
### A spoke's declared environment
|
|
673
777
|
|
|
674
778
|
A spoke scaffold's `pnpm preflight` and CI run `pnpm env:declared`: every
|
|
@@ -755,7 +859,7 @@ The network invariant (#6759 D6), in full:
|
|
|
755
859
|
3. Substitutes `workspace:*` references in every `package.json` with the matching `@working-theory/*` semver from npm — versions are pinned at npm-publish time.
|
|
756
860
|
4. Substitutes `{{PROJECT_NAME}}`, `{{COMPANY_NAME}}`, `{{COMPANY_DOMAIN}}` markers in `templates/README.md` from the target directory name (and CLI flags / interactive prompts in future versions).
|
|
757
861
|
5. Derives and writes `architecture.yaml` (the site's code-boundary config) from the selected module set — see below.
|
|
758
|
-
6. On a site with an Admin, seeds the starter's pages into its workspace when `--install` ran and `AILK_API_URL`, `AILK_WORKSPACE_ID` and `AILK_AGENT_KEY` are set, else prints why not and the `seed-workspace` command — see [Seeding the workspace](#seeding-the-workspace).
|
|
862
|
+
6. On a site with an Admin, seeds the starter's pages into its workspace when `--install` ran and `AILK_API_URL`, `AILK_WORKSPACE_ID` and `AILK_AGENT_KEY` are set, sets each page Live and, when every page is Live, switches `apps/web` and `apps/api` to `CONTENT_ADAPTER=database`; else prints why not and the `seed-workspace` command that seeds and switches later — see [Seeding the workspace](#seeding-the-workspace).
|
|
759
863
|
7. Prints next steps: `cd <dir> && pnpm install && pnpm dev`.
|
|
760
864
|
|
|
761
865
|
## `architecture.yaml` is derived from the module set
|