Skip to content

feat(templates): render every Html document component (Html.Meta, Html.Scripts, Html.ScrollRestoration) - #1

Merged
ivogt merged 2 commits into
mainfrom
feat/html-namespace
Sep 28, 2026
Merged

ivogt merged 2 commits into
mainfrom
feat/html-namespace

Conversation

@ivogt

@ivogt ivogt commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

@rangojs/router 0.17.0, which includes rangojs/rango#937, is published; this PR moves the templates to it and republishes create-rango as 0.2.3.

Problem

rangojs/rango#937 groups the router's document components under one namespace and removes the old names: MetaTags becomes Html.Meta, Scripts becomes Html.Scripts, ScrollRestoration becomes Html.ScrollRestoration. Every template's Document imports MetaTags, so a template scaffolded against that release fails to compile.

create-rango rewrites the router pin to the registry's latest at scaffold time. So from the moment that router release is published, every new scaffold breaks until create-rango is republished with this change.

The templates also rendered only MetaTags: the Script handle had nowhere to render, and back/forward did not restore scroll.

Before / after

// before
import { Link, MetaTags, useNavigation, usePathname, useReverse } from "@rangojs/router/client";

<head>
  <MetaTags />
  …stylesheets
</head>
<body …>
  …nav + content
</body>
// after
import { Html, Link, useNavigation, usePathname, useReverse } from "@rangojs/router/client";

<head>
  <Html.Meta />
  <Html.Scripts />
  …stylesheets
</head>
<body …>
  <Html.Scripts position="body" />
  …nav + content
  <Html.ScrollRestoration />
</body>

A scaffolded app can now push ctx.use(Script)({ id, children }) from any handler without touching the Document, and back/forward returns to the scroll position the user left.

Code change

  • templates/{basic,basic-js,cloudflare,vercel}/src/components/Document.{tsx,jsx}: the full Html shell above.
  • Same files: the route-change accessibility focus is now contentRef.current?.focus({ preventScroll: true }). A plain focus() scrolled to #main-content, so every new navigation landed at scrollY 117 instead of the top, and it would fight the restored position. Focus still moves for screen readers; the router owns the scroll.
  • templates/*/README.md: the Document line names the three components and what each renders.

Test plan

Run against a router tarball packed from rangojs/rango main (231fe107, includes #937), wired in through a temporary pnpm-workspace.yaml overrides entry (not committed):

  • check:generated, typecheck, lint, format, build, test:unit, create-rango test:smoke.
  • test:runtime: all 4 templates, dev + production (asserts the <title> rendered by Html.Meta).
  • Scroll check, all 4 templates, dev + production: scroll to 2000, push to /about (lands at 0), back (restores 2000), forward (0). With the old focus(), push and forward land at 117.
  • Script probe (temporary head + body inline Script pushes in basic's HomePage): both render in the right element and execute, dev + production.
  • Red check: the old MetaTags Document against the new router fails typecheck with TS2305 … no exported member 'MetaTags'.
  • Against the published 0.17.0, full pnpm run check: check:generated, typecheck, lint, format, build, unit, create-rango smoke, test:pack (all 4 templates scaffold + install + build from the packed tarball, vercel runtime, basic production server), test:runtime (4 templates, dev + production).

Release checklist

  1. Publish @rangojs/router 0.17.0 (includes feat(router)!: group the document components under Html (Html.Meta, Html.Scripts, Html.ScrollRestoration) rango#937).
  2. Template pins ^0.12.3 -> ^0.17.0 (the bundled pin is create-rango's offline fallback).
  3. Lockfile: @vitejs/plugin-rsc 0.5.34 -> 0.5.35, which router 0.17.0 requires (pnpm peers check clean).
  4. pnpm run check, including test:pack.
  5. Merge, publish create-rango 0.2.3, tag v0.2.3.

Notes

  • The templates repo is still on router 0.12.x (a caret on 0.x never crosses a minor), so the step 2 bump also brings in every other change up to the release. The tarball run above already covers main as of 231fe107.

Prepares the templates for the @rangojs/router release that groups the
document components under `Html` (rangojs/rango#937), which removes
`MetaTags`. Every template's Document now renders the full shell:
`Html.Meta` and `Html.Scripts` in <head>, `Html.Scripts position="body"`
at the top of <body>, and `Html.ScrollRestoration` at its end, so the
Meta and Script handles and back/forward scroll restoration work out of
the box.

The Document's accessibility focus on route change now passes
`preventScroll: true`. A plain `focus()` scrolled to #main-content, so
every new navigation landed at scrollY 117 instead of the top, and it
would fight the restored position.

Template READMEs describe the three components.

Not mergeable until that router release is on npm: the template pins
(^0.12.3) resolve a router with no `Html`. Bump the pins in the same
change.
Template pins move to the router release that ships the Html namespace (0.17.0); the bundled pin is create-rango's offline fallback. The lockfile takes @vitejs/plugin-rsc 0.5.35, which router 0.17.0 requires. create-rango 0.2.3 publishes these templates.
@ivogt
ivogt marked this pull request as ready for review September 28, 2026 16:50
@ivogt
ivogt merged commit 40f4bf8 into main Sep 28, 2026
2 checks passed
@ivogt
ivogt deleted the feat/html-namespace branch September 28, 2026 16:58
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