Skip to content

Author bespoke HTML on the fly (freeform mode) + self-contained validator - #6

Merged
vibhusharma101 merged 2 commits into
mainfrom
feat/dynamic-html-generation
Jul 10, 2026
Merged

Author bespoke HTML on the fly (freeform mode) + self-contained validator#6
vibhusharma101 merged 2 commits into
mainfrom
feat/dynamic-html-generation

Conversation

@vibhusharma101

Copy link
Copy Markdown
Owner

Why

Every explainer was capped by the same 12-block template and 4 preset skins, so different inputs produced the same page in new colors. This PR makes the AI author a complete, unique interactive HTML per subject — its own layout, visual system, and an interactive model of the subject's real mechanic.

What changed

Freeform is now the default generation mode

  • core/instructions/FREEFORM.md — the rubric. Core mandate: "What's the one dynamic that, if the reader could play with it, they'd finally get it?" → build a working model of it using the source's real logic (real constants/thresholds/states). Plus a hard variety rule (different palette/layout/motif every time) and the self-contained safety constraints.
  • core/build/check-html.mjs — zero-dep safety gate: rejects any external resource load (external <script>/<link>/<img>, @import, remote url()), requires the CSP <meta> + doctype, allows <a href> hyperlinks. Replaces schema validation for freeform.
  • .claude/commands/think-in-html.md + CLAUDE.md updated: default = freeform; --blocks = legacy templated engine.

Two worked references at the quality bar

  • examples/novus-pricing-desk.freeform.html — AI price-clamp shown on a live number line (ask the AI, toggle "rogue," watch the clamp reel it into the safe band).
  • examples/novus-rate-limit.freeform.html — fixed-window limiter as an ops dashboard (ring gauge to 30, 200→429, counter resets each window, "infra down" fails open).

These look and behave nothing alike — proof the variety mandate works.

Legacy blocks mode kept (--blocks), now upgraded with an AI-authored design theme (palette/fonts/mascot/freeform CSS) applied safely via runtime sanitizers + textContent, plus per-block className hooks. Defense-in-depth: CSP + sanitizers + textContent + build-time escaping.

Tests

npm test18 passing:

  • both freeform examples validate as self-contained;
  • the validator rejects external scripts/stylesheets/url() and allows hyperlinks;
  • design shape validation + the bespoke-theme build path are covered;
  • all prior block/validator guards still pass.

Verification done

  • Adversarial sanitizer checks (breakout, external fetch, script injection, attribute breakout) all neutralized.
  • Both reference HTMLs opened in a browser and driven end-to-end.
  • Full suite green.

vibhusharma101 and others added 2 commits July 8, 2026 21:50
… validator

Every explainer was capped by the same 12-block template + 4 preset skins, so
outputs only ever differed by color. This makes the AI author a complete,
unique interactive HTML per subject instead.

- Freeform is now the default: core/instructions/FREEFORM.md guides the AI to
  build a full self-contained page whose interactive centerpiece models the
  subject's real logic (real constants/thresholds/states), with a hard variety
  mandate so no two outputs look alike.
- core/build/check-html.mjs: zero-dep gate that rejects any external resource
  load (external <script>/<link>/<img>, @import, remote url()), requires the CSP
  meta + doctype, allows <a href> links. Replaces schema validation for freeform.
- Two worked references at the quality bar: examples/novus-pricing-desk.freeform.html
  (AI price-clamp on a number line) and examples/novus-rate-limit.freeform.html
  (fixed-window limiter dashboard).
- Legacy templated engine kept as --blocks, now with an AI-authored `design`
  theme (palette/fonts/mascot/freeform CSS) applied safely via sanitizers +
  textContent, plus per-block className hooks.
- Tests extended (18 passing): freeform examples are self-contained; the
  validator rejects external scripts/stylesheets/url() and allows hyperlinks;
  design shape validation and the bespoke-theme build path are covered.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…examples

The CLI (bin/cli.mjs) was still entirely on the pre-freeform blocks-only flow:
`instructions` and the adapters written by `init` never mentioned FREEFORM.md,
so a fresh `npx think-in-html init` would not actually deliver the new default
bespoke-HTML generation added in the freeform-mode work — it would silently
fall back to the legacy templated engine. This fixes the gap before publish.

- bin/cli.mjs: `instructions` now prints FREEFORM.md + mode guidance by
  default; `--blocks` opts into the legacy ANALYZE.md + schema flow. Added a
  `check <file>` command wrapping check-html.mjs's self-contained validator.
  Updated the Claude Code / Cursor / Codex adapter templates written by `init`
  to describe the freeform-first flow, with `--blocks` as the explicit legacy
  path.
- package.json: ship `examples/` in the npm tarball (FREEFORM.md references
  examples/*.freeform.html as a study reference) and refresh the description.
  PUBLISHING.md's expected `npm pack --dry-run` file list updated to match.
- examples/index.html: the two freeform reference examples (pricing-desk,
  rate-limit) were generated but never added to the live gallery — added
  cards for both so the headline feature is actually visible when people
  click through from the README.
- README.md: leads with bespoke/freeform generation, documents the `check`
  command and --blocks legacy flag, links both freeform gallery examples, and
  adds a placeholder for the future landing-page/waitlist link.
- .gitignore: ignore a local-only LANDING-PLAN.md planning doc.

Verified: npm test (18/18), `npm pack --dry-run` includes examples/, and
`think-in-html check` correctly passes a good file and rejects a crafted file
with an external <script src>.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@vibhusharma101

Copy link
Copy Markdown
Owner Author

Addendum: reviewed this PR ahead of the public launch and found the CLI itself was out of sync with its own headline feature — npx think-in-html init / instructions still only produced the legacy blocks-only flow, silently skipping freeform generation entirely. Pushed a fix:

  • bin/cli.mjsinstructions now defaults to FREEFORM.md + mode guidance (--blocks opts into the legacy flow); added a check <file> command wrapping the self-contained validator; updated the Claude Code/Cursor/Codex adapter templates written by init to match.
  • package.json — ships examples/ in the npm tarball (FREEFORM.md references a .freeform.html as a study example, which wasn't shipping before); PUBLISHING.md updated to match.
  • examples/index.html — added gallery cards for both freeform examples (they were generated but never linked from the gallery).
  • README.md — leads with freeform/bespoke generation, documents check, links both freeform examples, adds a placeholder for the upcoming landing page.

Verified: npm test (18/18), npm pack --dry-run includes examples/, think-in-html check passes a good file and rejects one with an external <script src>. CI green on Node 18/20/22.

@vibhusharma101
vibhusharma101 merged commit cebd224 into main Jul 10, 2026
3 checks passed
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