V1 Web PWA · Surface walkthrough

Newsletter Builder · Veritas

A per-surface walkthrough of the V1 Web PWA customer surface: layout, states, interactions, data, and cross-references.

walked
9sections6 minread

On this page

Context. surface customer · domain veritas · route /domains/veritas/newsletter · auth signed-in · source apps/oshun/web/src/app/domains/veritas/newsletter/page.tsx

Last walked. 2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data (2xx), console/page-errors, expected content, screenshot verified; live screen-reader, touch, offline, and telemetry-delivery checks pending a manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md. 2026-06-28 Codex Newsletter Builder addendum — authenticated template selection, keyboard close, editor section expansion/reorder/remove/add, edited email details, preview stats/render, send-preview state, export affordances, reduced motion, standalone PWA restore, offline mobile use, and horizontal overflow checks are covered by the E2E evidence below. 2026-06-30 Codex export addendum — HTML export now generates a standalone newsletter document and copies it to the clipboard with a download fallback, PDF export invokes the browser print pipeline against the rendered preview, and both paths are covered by the E2E evidence below.

Purpose#

The Veritas Newsletter Builder is a full-screen, fixture-backed editor for assembling truth digests. A signed-in user chooses a newsletter template, edits subject/preheader details, reviews and rearranges local section content, adds section types, previews the rendered email, and triggers a simulated preview send. From preview, the user can also copy/download a standalone HTML export or open the browser print flow for PDF output.

Entry Points#

  • Direct URL / bookmark/domains/veritas/newsletter (auth required)
  • /domains/veritas index — internal Veritas tool grid
  • Shell navigation history — opening after /library lets the Close control return with router.back()

Layout Regions#

page.tsx is a client route that renders an sr-only <h1> ("Newsletter Builder · Veritas · OSHUN") and mounts <VeritasNewsletterBuilder onClose={() => router.back()} />.

  • Overlay root: [data-veritas-newsletter-builder] with current data-veritas-newsletter-view, selected template, template/section/item counts, send state, sent state, and reduced-motion state.
  • Header: [data-veritas-newsletter-header], title, tablist [data-veritas-newsletter-tabs], view tabs, and [data-veritas-newsletter-close].
  • Templates view: [data-veritas-newsletter-templates-view] with template cards from SAMPLE_NEWSLETTER_TEMPLATES. Cards are keyboardable and expose frequency/section counts.
  • Editor view: [data-veritas-newsletter-editor-view] with Back/Preview actions, subject and preheader inputs, section editor rows, and add-section controls.
  • Preview view: [data-veritas-newsletter-preview-view] with Back to Editor, Send Preview state, stats, rendered email preview, and HTML/PDF export controls.

States#

  • Authenticated render — route opens through the signed-in shell and renders [data-veritas-newsletter-builder].
  • Templates populated — template-card count matches SAMPLE_NEWSLETTER_TEMPLATES.
  • Templates with no selectioneditor and preview tabs are disabled until a template is selected.
  • Template selected — selecting a card seeds subject, preheader, and section state from the template, then switches to editor view.
  • Editor populated — section count and item count match the selected template fixture.
  • Section expanded — expanded rows reveal content, item headlines, verdict/source/confidence metadata, and local trust labels.
  • Section reordered / removed / added — move, remove, and add-section actions update local section order/count and the root state attributes.
  • Preview populated — preview stats and rendered email sections reflect the current editor state, including edited preheader text.
  • Send preview pending / sent — Send Preview flips sending state, then shows the sent badge after the local timer completes.
  • HTML export copied / downloaded — HTML export generates a standalone document from the active draft, writes it to the clipboard when available, falls back to a .html download, and records export state through [data-veritas-newsletter-export-status].
  • PDF print requested — PDF export marks pdf-print-requested state and invokes the browser print pipeline with print CSS scoped to the rendered preview panel.
  • Offline — standalone mobile test switches the browser context offline and still selects a template, edits/expands sections, previews, and sends from local fixture state.
  • Standalone PWAmockStandaloneLaunch() restores directly into the route from /?surface=pwa.
  • Reduced motion — template/section/preview animations collapse to none under prefers-reduced-motion.
  • Mobile horizontal overflow — standalone/offline test asserts no document overflow at 390×844.

Interactions#

  • Close[data-veritas-newsletter-close] has accessible name "Close Newsletter Builder", a 44×44 target, keyboard activation, and returns to /library in the desktop path.
  • Tabstemplates, editor, and preview expose active state through data-veritas-newsletter-tab-active; editor/preview are disabled until selection.

Templates View#

  • Template card[data-veritas-newsletter-template-card="<template-id>"] is keyboardable, labelled Use <template name>, exposes fixture frequency/section count, and switches to editor view.

Editor View#

  • Back to templates[data-veritas-newsletter-action="back-to-templates"] switches back to the template gallery.
  • Subject / preheader inputs[data-veritas-newsletter-subject-input] and [data-veritas-newsletter-preheader-input] edit local email detail state.
  • Preview[data-veritas-newsletter-action="preview"] switches to preview with current editor state.
  • Section toggle[data-veritas-newsletter-section-toggle="<section-id>"] expands/collapses [data-veritas-newsletter-section-content="<section-id>"].
  • Section reorder[data-veritas-newsletter-section-move="<section-id>"] with data-veritas-newsletter-section-move-direction="up|down" swaps local order.
  • Section remove[data-veritas-newsletter-section-remove="<section-id>"] removes the row from local section state.
  • Add section[data-veritas-newsletter-add-section-type="<section-type>"] appends an empty section of that type.

Preview View#

  • Back to editor[data-veritas-newsletter-action="back-to-editor"] returns to editor and preserves local edits.
  • Stats[data-veritas-newsletter-preview-stat="sections|items|estimated-read-time|template|frequency"] exposes preview values from the active draft.
  • Rendered email[data-veritas-newsletter-preview-panel] and [data-veritas-newsletter-preview-section="<section-id>"] render the current sections/items.
  • Send preview[data-veritas-newsletter-action="send-preview"] exposes pending state and then [data-veritas-newsletter-sent-badge].
  • HTML export[data-veritas-newsletter-export="html"] has accessible name "Copy newsletter HTML export", generates the current draft as standalone HTML, writes to navigator.clipboard.writeText() when available, falls back to a downloaded HTML file, and surfaces data-veritas-newsletter-export-state="html-copied|html-downloaded|failed".
  • PDF export[data-veritas-newsletter-export="pdf"] has accessible name "Open browser print dialog for PDF export", sets data-veritas-newsletter-export-state="pdf-print-requested", and calls window.print() so the browser can save/print the rendered preview.

Data & Contracts#

  • Reads: SAMPLE_NEWSLETTER_TEMPLATES from apps/oshun/web/src/lib/veritas/veritas-extended-simulation.ts.
  • Types: NewsletterTemplate, NewsletterSection, and NewsletterSectionType from veritas-extended-types.ts.
  • Writes: local React state only (view, selectedTemplate, editSections, editSubject, editPreheader, sending, sent, exportState).
  • Realtime / external network: none for the core route; the builder remains usable while the browser context is offline.
  • Send behavior: simulated client timer only; no email job is queued.
  • Export behavior: local client export only. HTML export builds escaped, standalone markup from the selected template/current editor draft and writes it to the Clipboard API when available; if clipboard write is unavailable or rejected, it downloads veritas-<template>.html. PDF export uses browser-native print/save-as-PDF by invoking window.print() and print CSS that isolates the preview panel. No server render job or asset persistence is queued.
  • Telemetry: no route-local telemetry import or event dispatch.
  • Auth/role check: shell middleware gates /domains/veritas/*.
  • Page metadata: no Metadata export in this client page; the screen-reader <h1> reads "Newsletter Builder · Veritas · OSHUN".

Current E2E Evidence#

  • apps/oshun/web/e2e/veritas-newsletter-builder.spec.ts
    • Desktop templates: fixture total, disabled tabs before selection, accessible 44×44 close, reduced-motion card animation, keyboard template selection, and keyboard close.
    • Editor: seeded subject/preheader, section expansion with item metadata, reorder, remove, add-section, edited details, preview transition, preview stats, edited preheader rendering, and return-to-editor state preservation.
    • Preview/send/export: selected-template stats, rendered preview sections, sending state, sent badge, copied standalone HTML payload containing the template/section/item content, HTML export state, PDF print-request state, and the browser print invocation.
    • Standalone/offline mobile: PWA relaunch, offline template selection, section expansion, preview, simulated send, reduced motion, and no horizontal overflow at 390×844.

Cross-References#

Open Questions / Known Gaps#

  • Drafts, removed sections, reordered sections, and sent state are session-local only; they do not persist through reload or sync to a user Library/subscription store.
  • Send Preview is a simulated timer and does not enqueue an email job.
  • No telemetry currently records template selection, editor changes, preview, send, or export intent.
  • The reader component VeritasNewsletter remains adjacent to this builder; confirm whether it is the subscriber-facing counterpart or a legacy preview surface.