Skip to content
← All starter build updates

Marketing starter

Launchpad

A crisp product launch site for a new developer-tools startup.

Live on VuraUpdated

Product-facing releases, transparent rate assumptions and distinct tour evidence make the startup reference substantive. Its static pages, islands and no-JS content passed new release checks.

Launchpad: actual released desktop product view after the shared typography refinement.
Preview captured · Explore the product ↗

Build phase

  1. PlannedComplete
  2. BuildingComplete
  3. Local checks passedComplete
  4. In reviewComplete
  5. Live on VuraCurrent phase

This tracks the recorded release phase. The checks below include later findings and ongoing refinements.

Product scope and intended patterns

The following describes the intended reference. Features are not a verification claim; recorded check results below define what has actually been tested.

Build-time rendered public content with client-mounted interactive islands.

Learning journal

How to read this starter

Launchpad is a static startup marketing site with small What islands for pricing and product-tour interaction.

Source map

Server renderer

src/server/render.mjs

Static pages render through h() and renderToString() so the Node build never imports compiled browser JSX.

Client islands

src/client/main.jsx

The pricing calculator and tour island mount into server-rendered placeholders.

Output checker

scripts/check.mjs

The build fails if a route is missing, has multiple h1 elements or renders undefined/null text.

Responsive application stylesheet

src/shared/site.css

The timeline pseudo-element consumes --bar rather than inventing fixed decorative widths.

Code patterns worth copying

Clamp persisted pricing inputs before making signals

src/client/main.jsx

The UI never starts from NaN or out-of-range persisted values, and range inputs reuse the same coercion path.

const retention = useSignal(coerceRange(saved.retention, 7, 90, 30));

Treat static route generation as a contract

scripts/check.mjs

A marketing starter can still have build-time quality gates. Here route output, semantics and manifest shape are checked before packaging.

for (const route of routes) {
  const file = route.path === '/' ? 'dist/static/index.html' : `dist/static${route.path}/index.html`;
  if (!existsSync(file)) {
    fail(`missing ${file}`);
    continue;
  }
  const html = readFileSync(file, 'utf8');

Read tour evidence at the selected stage

src/client/main.jsx

Stage-specific evidence is authored in content records and is rendered reactively; the static first-stage fallback remains useful without JavaScript.

<ul class="build-list">{() => current().evidence.map(item => <li>{item}</li>)}</ul>

Keep timeline fill driven by authored data

src/shared/site.css

The timeline pseudo-element consumes --bar rather than inventing fixed decorative widths.

.build-timeline li::before { content: ""; position: absolute; inset: 0 auto 0 0; width: var(--bar); background: #1a2b47; }

Real issues and fixes

Pricing pages need the same hero spacing as the rest of the site

Problem
The pricing route used the interactive calculator correctly but missed the page-hero headline class, so the headline and calculator crowded each other.
Fix
Render the pricing section with the shared page-hero class and keep the route-specific calculator mount inside that frame.
Proof
The smoke check requires at least 24px between the headline box and calculator panel at both 1440px and 390px.
Takeaway
Static route classes are part of the component contract when a client island mounts inside them.

Persisted controls can poison the first render

Problem
Saved localStorage values may be missing, malformed or outside the product range.
Fix
Every saved range passes through coerceRange before a signal is created, and denied storage falls back to an in-memory Map.
Proof
The build and smoke check complete with static pages plus browser islands, and no route renders nullish text.
Takeaway
Static-first does not mean state-free; persisted island state still needs input hygiene.

A tour needs evidence for each stage

Problem
The tour repeated shallow copy and displayed an unsupported time-saved claim.
Fix
Put distinct evidence on every tour record and replace the unsupported metric with the count of named owners. Read current evidence inside a reactive function child.
Proof
Product-depth checks require distinct records; browser checks switch stages, measure desktop/mobile layout and open static routes with JavaScript disabled.
Takeaway
Product claims should come from visible authored evidence, not decorative metrics.

Retain data-driven duration bars during style changes

Problem
Flattening decorative backgrounds can also erase a timeline fill that encodes an authored duration record.
Fix
Keep the build-timeline pseudo-element width driven by --bar while simplifying surrounding surfaces and headings.
Proof
The server renderer writes item.percent into --bar and displays item.duration; the stylesheet retains width: var(--bar).
Takeaway
Distinguish decoration from a data encoding before removing a visual treatment.

What went smoothly

  • Keeping route metadata in one content module made sitemap, llms text and page generation come from the same data.
  • Server-safe h() rendering and browser-only JSX islands kept the static build understandable for agents.
  • The existing tour island could display richer evidence from the same records without adding requests or another state layer.
  • Quiet dark surfaces keep release evidence readable while the timeline still reads its bar widths from authored duration records.

Boundaries to preserve

  • The pricing calculator is an anonymous local estimate, not billing or entitlement logic.
  • All application pages are static HTML with client islands; there is no request-time backend in this starter.

Verification record

Build journal

  1. · Live on Vura

    Shared typography release captured from production

    Published shared typography and responsive control refinements are tied to the exact live deployment and source revision. Actual released captures replace the previous gallery preview; existing product behavior and source-grounded lessons are retained.

  2. · Live on Vura

    Product-depth iteration released and exercised

    Product-facing releases, transparent rate assumptions and distinct tour evidence make the startup reference substantive. Its static pages, islands and no-JS content passed new release checks.

  3. · Live on Vura

    Reviewed source ready for release verification

    Unique product identities and deeper workflows are implemented and independently reviewed. Existing releases remain accessible while new source is published and fresh deployments are exercised.

  4. · Live on Vura

    Product-depth iteration in progress

    Deepening product-facing pricing, changelog and documentation with distinct worked tour scenarios. The current source and deployment links still identify the previous verified release.

  5. · Live on Vura

    Live corrections verified after independent follow-up

    The release timeline leads the product story; pricing uses the actual scoped hero class. Live headline-to-calculator clearance is40px desktop and32px mobile.

  6. · Live on Vura

    Design refinement released for live workflow review

    A sample build timeline leads the product story; pricing hierarchy and mobile navigation have been refined. Static pages, the pricing calculator and linked source are live.

  7. · Live on Vura

    Independent live design review started

    The existing public app remains available while a new design review examines hierarchy, typography, navigation and workflow clarity. Actual findings and before/after repairs will be recorded as they are verified.

  8. · Live on Vura

    Hosted reference rechecked after documentation review

    Public source, green CI and the live app were checked together after the clean-machine documentation pass. Lessons and limitations now reflect the implemented code rather than pending pre-release work.

  9. · Live on Vura

    Final source and CI checkpoint verified

    The public source and build reference match the released learning journal, and the source workflow is green. The demo remains live at the same verified deployment; README and CI-only refinements did not change application code.

  10. · Live on Vura

    Clean-machine browser setup documented

    The README now installs the locked Chromium engine after npm ci and explains the Linux system-library prerequisite. The hosted application is unchanged; code examples, repair notes and boundaries remain source-backed.

  11. · Live on Vura

    Public template and Vura release

    The reviewed implementation is available from its independent repository and real hosted URL. Detailed code examples and actual repair notes are linked below.

  12. · In review

    Design review cleared; release verification underway

    The local implementation is complete and revised visual evidence has passed review. Source and demo links will appear only after publication and hosted verification.

  13. · In review

    Local implementation ready for review

    The first implementation is available locally. It is not yet a published source reference or a verified Vura deployment.

Implementation lessons

Known limitations

Remaining work and blockers

No release blockers are recorded for this snapshot.

Using this as an agent reference

Read the public README and BUILD.md, reproduce the recorded checks and inspect the source before adapting the starter. A live demo, where available, provides separate deployed evidence.