Skip to content

Add the marketing site, an API reference, a real icon, and search/answer-engine metadata - #9

Merged
cmm-cmm merged 5 commits into
mainfrom
claude/forgedialog-library-mhkpak
Sep 2, 2026
Merged

cmm-cmm merged 5 commits into
mainfrom
claude/forgedialog-library-mhkpak

Conversation

@cmm-cmm

@cmm-cmm cmm-cmm commented Sep 1, 2026 •

Copy link
Copy Markdown
Owner

Summary

Forge Dialog had a README and a manual test page, but nothing to point people at. This adds site/: a landing page with an interactive appearance playground, a full API reference, a real mark, and the metadata that search engines and answer engines read — plus the Cloudflare configuration that actually deploys it.

It is plain HTML, CSS, and browser JavaScript with no dependencies and no framework — the site carries the same constraint as the library it advertises. Nothing is added to dependencies or devDependencies.

No library code changed. Nothing under src/ was touched, so there is no API, runtime, or accessibility impact on the published package.

Naming

The product is Forge Dialog, two words, and every page and document now says so. Identifiers keep the one-word spelling because that is what they are: the npm package (forgedialog), the browser global (ForgeDialog), the custom element (forge-dialog), and the repository. Runtime strings inside src/ were deliberately left alone so the published behaviour is unchanged.

Documentation

site/docs.html is a 23-section reference written against the reviewed API report in etc/, not from memory: entry points, DialogOptions, DialogInstance, appearance, shadows, radius, hover, dragging, drawers, forms, wizards, toasts, the command palette, theming, CSS variables, i18n, plugins, framework adapters, and the TypeScript/SSR/CSP notes.

The shared chrome (version badge, theme toggle, copy buttons) moved out of site.js into common.js, so both pages use it without the landing page's demo wiring.

Icon

site/icon.svg is the source of truth and the favicon browsers load. scripts/build-icons.mjs renders the committed apple-touch-icon.png (180×180) and og-image.png (1200×630) from it through Chromium, which is already a dev dependency for the e2e tests. Run it with npm run site:icons only when the icon changes — neither the site build nor a deploy runs it.

Two decisions worth calling out: the touch variant squares off the mark's ground via #ground { rx: 0 }, because iOS applies its own rounded mask and would otherwise round it twice; and the first draft of the OG image used a gradient and cost 296 KB, so it now uses a flat ground that looks identical at preview size and costs 37 KB.

SEO

canonical, og:url, and og:image are absolute, pointing at https://forgedialog.konexforge.com. The canonical tag in index.html is the single source of truth for the domain: scripts/build-site.mjs reads it back to generate sitemap.xml, robots.txt, and llms.txt, so moving the site means editing the canonical tags in the two HTML files and nothing else.

Both pages carry JSON-LD — WebSite + SoftwareApplication + FAQPage on the landing page, TechArticle + BreadcrumbList on the reference. The FAQ entries are generated from the visible questions and answers, so the markup and the page cannot disagree.

New "At a glance" and FAQ sections state the facts in self-contained sentences, which is what both search snippets and answer engines quote. The size figures come from the enforced budgets (≈15 KB gzipped full, ≈5.5 KB alert-only), not from estimates.

Answer engines

llms.txt follows the llmstxt.org convention and states the facts models most often get wrong — including the Forge Dialog / forgedialog / ForgeDialog distinction — with the version read from package.json so it cannot drift.

robots.txt names the AI crawlers explicitly rather than leaving them to the default, and deliberately does not disallow /vendor/: blocking a site's own CSS and JavaScript is what breaks rendering for search crawlers.

Two layout bugs fixed

Both pre-existing, both found by measuring rather than reading:

  • The header row never wrapped, so at 380px the page scrolled sideways by 102px.
  • The playground's grid track had an automatic minimum of min-content, which the long code lines inside .snippet pushed wide open — 812px of horizontal overflow at 320px. Capping the track at minmax(0, 1fr) and giving .snippet min-width: 0 fixes it.

Both pages now fit at 320, 380, 480, and 768px with zero horizontal overflow.

Deployment

The site ships as a Workers static-assets project — no Worker script, every request answered straight from site/.

The first deploy attempt built npm run build and ran wrangler deploy --assets ./dist, which uploaded 97 files of compiled library (.mjs, .cjs, .d.ts, .css) with no index.html among them, so the domain served nothing. wrangler.jsonc now pins the assets directory to site/ — the directory npm run site:build fills — so the configuration lives in the repository instead of a dashboard field. A deploy command that passes --assets overrides it, so docs/website.md says to drop the flag and use the Workers Builds settings it lists.

The docs page is /docs, not /docs.html

Verifying the routing turned up a defect worth its own note. Workers Assets serves foo.html at /foo and 307s the extension form; serve, which npm run site uses, behaves the same way. Every URL naming /docs.html — the canonical tag, og:url, the TechArticle and BreadcrumbList nodes, the sitemap entry, the llms.txt link, and the in-page links — therefore pointed at a URL that redirects, and a canonical or sitemap entry that redirects is a conflicting signal to a search engine. /docs is now the URL everywhere, and the docs page links home with ./ rather than ./index.html.

Response headers

site/_headers ships a strict CSP limited to same-origin scripts and styles, which the library already satisfies. Workers static assets supports _headers natively. The inline JSON-LD survives the policy because an application/ld+json block is data, not an executable script — verified in the browser rather than assumed.

Verification

  • npm run validate
  • npm run format:check
  • npm run test:e2e — not run locally (the pinned Playwright wants a browser build this container does not have); it covers the library and demo/, and no library code was touched. CI runs it.
  • Added or updated tests covering the change — the site is static presentation with no library behaviour of its own; the appearance API it drives is already covered by unit and browser tests.

Driven in Chromium against wrangler dev, so the routing and the production _headers CSP are the real ones:

  • /, /docs, /robots.txt, /sitemap.xml, /llms.txt, /icon.svg, /apple-touch-icon.png, /og-image.png, /styles.css, and /vendor/index.global.js all return 200 with correct content types
  • Every relative link on both pages resolves with a 200 — no redirect hops left
  • No console errors and no failed requests on either page
  • Inline JSON-LD present and parseable in the live DOM under script-src 'self'; all five schema types found
  • FAQ schema questions match the visible <h3>s one for one
  • All 23 sidebar links resolve to real sections; scroll-spy tracks the section being read
  • Hero alert still gets role=&#34;alertdialog&#34; with aria-modal=&#34;true&#34;, Escape closes it, focus returns to #try-alert
  • Version badge renders v0.7.0 from the library's own export
  • Zero horizontal overflow at 320/380/480/768px on both pages

Checklist

  • Added a changeset (npm run changeset) for user-facing changes — not applicable: nothing in the published package changes. files is unchanged and neither site/ nor wrangler.jsonc is published.
  • Refreshed API reports — not applicable, the public surface is untouched.
  • Raised a gzip budget — not needed; npm run size and the tarball check pass unchanged (120.2 KiB, 71 files).
  • Refreshed the visual baseline — not needed; demo/ only had its title and heading renamed.

Housekeeping: site/vendor, the generated robots.txt/sitemap.xml/llms.txt, and Wrangler's .wrangler/ local state are git-ignored and prettier-ignored; site, site:build, and site:icons scripts added.

Screenshots

Verified visually during the browser run: the docs page with its sticky sidebar, the "At a glance" table and FAQ, the rendered OG card, and the landing page at 390px with the header wrapping onto a second row.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MtJ3nDatGiv7dHjvZL1uZ4

ForgeDialog had a README and a manual test page but nothing to point people
at. site/ is a landing page with an interactive appearance playground,
written in plain HTML, CSS, and browser JavaScript so the site carries no
dependencies of its own, matching the library it advertises.

The page runs the build from this checkout rather than a CDN:
scripts/build-site.mjs copies dist/index.global.js and dist/index.css into
site/vendor/, which is git-ignored. It uses only Node built-ins and rewrites
no source files. The version badge reads the library's own VERSION export at
runtime, so nothing has to be kept in sync by hand.

The playground calls instance.update() on every control change, so the dialog
restyles while it is open, and it prints the matching source alongside, so the
demo doubles as documentation for the appearance API.

site/_headers ships a strict CSP for Cloudflare Pages limited to same-origin
scripts and styles, which the library already satisfies: test:csp enforces
that dist contains no eval or new Function. docs/website.md covers local use
and the Cloudflare build settings.

Verified in Chromium: no console errors or failed requests, the alert traps
focus and returns it to the trigger on Escape, the playground applies a 30px
radius and casts its shadow right at 90 degrees, live updates reach an open
dialog, and the theme toggle drives the library and the page together.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtJ3nDatGiv7dHjvZL1uZ4
@coderabbitai

coderabbitai Bot commented Sep 1, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 648a1b8d-f7fb-4ce0-9345-e789fb73ae11


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…ise for search and answer engines

The site had a landing page and an emoji favicon; it now has a full API
reference, a real mark, and the metadata that search engines and answer
engines read.

Naming: the product is Forge Dialog, two words, and every page and document
now says so. Identifiers keep the one-word spelling because that is what they
are: the npm package (forgedialog), the browser global (ForgeDialog), the
custom element (forge-dialog), and the repository. Nothing under src/ changed,
so the published API and its runtime strings are untouched.

Docs: site/docs.html is a 23-section reference written against the reviewed
API report in etc/, covering every option, method, and entry point. The shared
chrome (version badge, theme toggle, copy buttons) moved out of site.js into
common.js so both pages use it without the landing page's demo wiring.

Icon: site/icon.svg is the source of truth and the favicon browsers load.
scripts/build-icons.mjs renders the committed apple-touch-icon.png and
og-image.png from it through Chromium, which is already a dev dependency. The
touch variant squares off the mark's ground because iOS applies its own mask.
The first draft of the OG image used a gradient and cost 296 KB; a flat ground
looks the same at preview size and costs 37 KB.

SEO: canonical, og:url, and og:image are absolute. The canonical tag in
index.html is the single source of truth for the domain — build-site.mjs reads
it back to generate sitemap.xml, robots.txt, and llms.txt, so moving the site
is an edit to the canonical tags and nothing else. Both pages carry JSON-LD;
the FAQ entries are generated from the visible questions so the markup and the
page cannot disagree.

Answer engines: llms.txt follows the llmstxt.org convention and states the
facts models most often get wrong, with the version read from package.json so
it cannot drift. robots.txt names the AI crawlers explicitly rather than
leaving them to the default, and deliberately does not disallow /vendor/ —
blocking a site's own CSS and JS is what breaks rendering for crawlers.

Two layout bugs found while measuring, both pre-existing:

- The header never wrapped, so at 380px the page scrolled sideways by 102px.
- The playground's grid track had an automatic minimum of min-content, which
  the long code lines inside .snippet pushed open — 812px of horizontal
  overflow at 320px. Capping the track at minmax(0, 1fr) and giving .snippet
  min-width: 0 fixes it.

Both pages now fit at 320, 380, 480, and 768px with zero horizontal overflow.

Verified in Chromium against the production CSP: no console errors and no
failed requests on either page, the inline JSON-LD survives script-src 'self'
(it is a data block, not an executable script), all 23 sidebar links resolve
to real sections, scroll-spy tracks the section being read, the hero alert
still gets role="alertdialog" with focus returning to its trigger, and
robots.txt, sitemap.xml, llms.txt, and all three icons serve with the right
content types. npm run validate and format:check pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtJ3nDatGiv7dHjvZL1uZ4
@cmm-cmm cmm-cmm changed the title Add a dependency-free marketing site with an appearance playground Add the marketing site, an API reference, a real icon, and search/answer-engine metadata Sep 1, 2026
The Cloudflare Worker was built with `npm run build` and deployed with
`wrangler deploy --assets ./dist`, so it uploaded 97 files of compiled
library — .mjs, .cjs, .d.ts, .css — with no index.html among them. Workers
Assets had nothing to answer `/` with, which is why the domain served
nothing.

wrangler.jsonc now pins the assets directory to `site/`, the directory
`npm run site:build` actually fills, so the configuration lives in the
repository rather than in a dashboard field. A deploy command that passes
`--assets` overrides it, so docs/website.md says to drop the flag.

While verifying the routing, the docs page turned out to be reachable only
by redirect. Workers Assets serves `foo.html` at `/foo` and 307s the
extension form, and `serve` (which `npm run site` uses) does the same, so
every URL naming `/docs.html` — the canonical tag, og:url, the TechArticle
and BreadcrumbList nodes, the sitemap entry, the llms.txt link, and the
in-page links — pointed at a URL that redirects. A canonical or sitemap
entry that redirects is a conflicting signal, so `/docs` is now the URL
everywhere, and the docs page links back to `./` rather than
`./index.html`.

Verified against `wrangler dev` with the production `_headers` CSP: both
pages and every asset return 200, every relative link resolves without a
redirect, the pages load with no console errors or failed requests, the
JSON-LD parses, and the hero alert still opens as `role="alertdialog"` and
closes on Escape.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtJ3nDatGiv7dHjvZL1uZ4
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 2, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
forge-dialog 22c0c65 Sep 02 2026, 05:00 AM

A repo-wide pass before the worker is recreated from scratch.

An unmatched path got the platform's bare 404, so site/404.html now answers
for them through not_found_handling. It links its assets root-relative
rather than with "./" because it also answers for nested paths, where a
relative href would resolve against the missing directory, and it carries
noindex with no canonical tag since it has no URL of its own.

The sitemap stamped every entry with the build date, which told crawlers
both pages change daily. lastmod now comes from the last commit that
touched each page's HTML. A build with no reachable git history writes the
entry without a lastmod rather than with a plausible-looking date.

npm run check:release reported what the docs had not caught up with:
forgedialog 0.7.0 was published on 1 September. docs/releasing.md still
said the package was unpublished and framed the manual first publish and
the E404 troubleshooting entry as the likely path; both are now scoped to a
fork starting from an unpublished name. package.json homepage moves from
the README anchor to the site, listed under Unreleased because 0.7.0 is
already out and cannot carry it.

README no longer calls the deployment Cloudflare Pages.

Verified against wrangler dev with the production _headers: /, /docs and
every asset return 200; /nope and /deep/nested/nope return 404 with the
site's own page, its assets loading and the CSP applied; both pages and the
404 render with no console errors, no failed requests, and zero horizontal
overflow at 320, 380, 480 and 768px. npm run validate passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtJ3nDatGiv7dHjvZL1uZ4
main added a wrangler.jsonc pointing `assets.directory` at `./dist`, which
is the compiled library — .mjs, .cjs, .d.ts and .css with no index.html —
so a deploy from it serves nothing at /. This branch's version, pointing at
`./site`, is kept.

The conflict is also why CI stopped running here: workflows triggered by
`pull_request` build the merge ref, and GitHub cannot compute one for a
conflicting PR, so no run was created for the last two pushes. Merging the
base back in restores it.

"$schema" is left out rather than carried over: it resolves into
node_modules, and wrangler is deliberately not a dependency of this
package — deploys invoke it through npx.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtJ3nDatGiv7dHjvZL1uZ4
@cmm-cmm
cmm-cmm marked this pull request as ready for review September 2, 2026 05:44
@cmm-cmm
cmm-cmm merged commit 631f43c into main Sep 2, 2026
12 checks passed
cmm-cmm pushed a commit that referenced this pull request Sep 2, 2026
PR #9 was squashed onto main as 631f43c, so this branch was restarted from
main and the demo work sits on top of it. The remote branch still points at
the pre-squash commits, whose content main already carries; recording them as
a parent lets this push fast-forward without discarding the branch history a
force push would have rewritten.

The tree is unchanged by this merge.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtJ3nDatGiv7dHjvZL1uZ4
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.

2 participants