Repository navigation
v1.6.0
- Added
routing.typedRoutesto check URL strings in links, navigation, and rewrites. Enabled by default in new Pages apps. - Added automatic
aria-currentanddata-void-activeindicators toLink, withactiveMatch="prefix"for nested pages. - Added
data-void-pendingtoLinkwhile its destination is loading. - Added
prefetch.defaultStrategyto configure a default prefetch strategy for everyLink. - Improved
Linkprefetching to skip external URLs, respect data saver and 2G connections, and wait 300 ms before prefetching visible links. - Added
{ resolveOn: 'data' }to Reactrouter.visit()androuter.refresh()to avoid deadlocks when awaiting navigation inside Actions or transitions. - Added a
threadingoption tosendEmail()so replies sent later can stay in the same conversation. - Added rotating refresh tokens for connected apps, allowing access to be renewed without hourly sign-in prompts.
- Added
--runtime-logs minimalfor self-hosted platforms to omit request URLs and log and exception messages from runtime telemetry. - Improved native Cloudflare deploys to serve static files and prerendered pages without Worker invocations when no server processing is needed.
- Fixed page middleware breaking loader and action responses and dropping validator types.
- Fixed query-only and relative navigation URLs resolving against the site root instead of the current page.
- Fixed Vue
Linktypes rejecting standard attributes and listeners such astarget,download, and@click. - Fixed Svelte
useForm()clearing errors written directly in an input handler. - Fixed action errors showing a generic status instead of the message from a plain-text 4xx response.
- Fixed forms and actions scrolling to the top after updating the current page in place.
- Fixed custom response headers in local development and native deploys without overriding private authentication cache policy.
- Fixed missing Sandbox and Container Durable Object bindings in the dev server.
- Fixed Markdown client scripts missing from production builds when no
.island.file was present. - Fixed invalid Markdown frontmatter stopping the dev server. Errors now identify the affected file, and other pages keep working.
- Fixed platform setup requiring DNS Edit permission when using an existing compatible DNS record.
- Fixed resumed platform installations ignoring replacement runtime tokens and leaving already deployed Workers with old credentials.
Thanks to @0froq, @Dazzanova, @dvkam, @iPLAYCAFE-dev, @karthickeyan-dev, @morinokami, @serkodev, @sglyon, @ubugeeei, and @yangshun for their contributions!
New Features
Typed Routes
New Pages apps enable typed route URLs automatically. To enable them in an existing app:
// void.config.ts
import { defineConfig } from 'void/config';
export default defineConfig({
routing: { typedRoutes: true },
});TypeScript then checks URL strings passed to Link, router methods, and c.rewrite() against your app's routes.
Active and Pending Links
Style the current page and a navigation in progress with CSS:
a[data-void-active] {
font-weight: 600;
}
a[data-void-pending] {
opacity: 0.6;
transition: opacity 0.15s 0.1s;
}Use activeMatch="prefix" to keep a section's link active on nested pages:
<Link href="/users" activeMatch="prefix">Users</Link>Prefetch Defaults
Configure prefetching once in your framework adapter:
voidReact({ prefetch: { defaultStrategy: 'hover' } });The same option works with voidVue, voidSvelte, and voidSolid. Individual links can override it:
<Link href="/reports" prefetch="visible">Reports</Link>
<Link href="/exports" prefetch={false}>Exports</Link>Visible links wait 300 ms before prefetching. Automatic prefetching skips when the browser reports data saver or a 2G connection.
Awaiting Navigation in React Actions
Pass resolveOn: 'data' when awaiting navigation inside a React Action or transition:
startTransition(async () => {
await saveUser();
await router.refresh({ resolveOn: 'data' });
});This lets the Action finish once page data is ready, allowing React to commit the update.
Email Threading
Save an incoming message's ID and use it when sending a reply later, such as from a queue job:
await sendEmail({
to: ticket.from,
subject: `Re: ${ticket.subject}`,
text: 'We fixed it.',
threading: { inReplyTo: ticket.messageId },
});Connected-App Refresh Tokens
Connected apps can renew access by posting grant_type=refresh_token and their refresh token to /oauth/token, using HTTP Basic client authentication.
Minimal Runtime Logs
Choose minimal logging when installing or upgrading a self-hosted platform:
void platform install --runtime-logs minimal
void platform upgrade --runtime-logs minimalUpgrade Guide
Form types are stricter in this release:
- Form status fields are read-only, and
form.dataandform.errorscannot be replaced. In React and Solid, update fields through the form methods. Vue and Svelte continue to support editing data and errors in place. - Island form errors are now typed as
string | undefined. Check that an error exists before using it. - Svelte
useIslandForm()now infers field types from its defaults. Annotate defaults that need a wider type, such asnull as File | null.