feat(docs): community Q&A widget on every page — MERGE AFTER api#262 DEPLOYS - #13
Draft
CosmoBlk wants to merge 2 commits into
Draft
feat(docs): community Q&A widget on every page — MERGE AFTER api#262 DEPLOYS#13CosmoBlk wants to merge 2 commits into
CosmoBlk wants to merge 2 commits into
Conversation
Post-build injector (the only repo-controlled every-page injection point — Sourcey templates live in node_modules): inject-qa.js appends a marker- idempotent, self-contained vanilla-JS widget before </body> on every dist HTML file and fails loudly on a missing or empty dist. The widget reads the normalized pathname as page_key (matrix mirrors the API: decode once, lowercase, collapse slashes, strip trailing slash and .html, / -> /introduction), fetches GET /v1/public/questions, renders in the docs theme (.dark-aware), URL-encodes the Ask deep link into the app, and removes only its own container on any fetch/render failure. Every user/LLM-originated string is inserted via createTextNode only — no innerHTML or attribute sinks (the DOM test's innerHTML setter throws). verify-qa-injection.mjs gates the Vercel build: every generated HTML file must carry exactly one marker (zero and 2+ both fail), with an explicit allowlist for any future </body>-less files. inject-qa.test.mjs covers the injector, the verifier, and the widget XSS/normalization contract with node stdlib only. MERGE NOTE (binding release order): deploy only after the api release is verified live returning 200-empty on GET /v1/public/questions — Cloudflare negative-caches 404s for a year.
The community-qa contract's deep link is https://app.nitrosend.com/my/learn?ask=1&page_key=<encoded> (LC route name my-learn) — /learning/community/ask does not exist and is not planned. Tests now pin the full href.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
CosmoBlk
marked this pull request as draft
July 22, 2026 11:17
Member
Author
|
⏸️ Hold — not ready for review yet. George wants to test this on staging first. Converting to draft; will mark ready + re-ping once staging QA clears. (Applies to the whole batch: api#261, app#149, api#262, docs#13, app#150.) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GET https://api.nitrosend.com/v1/public/questions?page_key=/quickstartmust return 200{"questions":[]}live BEFORE this merges. Cloudflare negative-caches 404s for a year — a docs deploy ahead of the API route poisons the cache. Rollback is docs-first for the same reason.Summary
scripts/inject-qa.js) appends a self-contained Q&A widget before</body>on every built page — the only repo-controlled every-page injection point Sourcey allows (templates live in node_modules).dark-aware, page_key from pathname, quiet empty state, "Ask a question" deep-links toapp.nitrosend.com/my/learn?ask=1&page_key=…, any failure removes only the widgetverify-qa-injection.mjsgates the build: every generated HTML file must carry exactly one marker (54/54 today)vercel.jsonbuildCommand chains build → inject → verifyTest plan
17 node-stdlib tests (idempotency, marker guard, empty-dist failure, hand-rolled DOM stub proving
<img onerror>, split-</script>,<svg onload>render as text) + full real build verified twice (idempotent re-run: 0 injected, 54 skipped).Reviews
Built with
/devpipeline: scafld spec → codex plan review → harden → TDD → codex adversarial gate