Your CTA shouldn't wait behind a chat widget.
Tag each block with how much it matters — for sales, search, or clicks — and biagiojs decides what hits the wire first, what hydrates, and what stays plain HTML. No islands on a page? That's zero JavaScript, full stop.
npx create-biagiojs my-sitenpmProof, not promises
We audited this exact page
Google Lighthouse on the site you're looking at — mobile on throttled 4G, desktop emulated. One small island; the rest is static HTML. The numbers speak for themselves.


Lighthouse 13 · July 2026 · biagio.danilosprovieri.com
Under the hood
The boring stuff, already solved
Scheduler
High-value sections climb the HTML source before heavy widgets. You declare what matters; the build reshuffles the deck.
Islands
Hydrate now, later, or never. A 300 KB chat bubble at low conversion stays static — your checkout doesn't wait for it.
SEO
Canonical URLs, Open Graph, JSON-LD, sitemap and hreflang — generated at build time, not bolted on later.
Images
Responsive AVIF, WebP and JPEG via sharp. Sensible defaults, per-image profiles, and a guardrail if you reference a file that doesn't exist.
SSG + adapters
Static sites by default. When you need SSR or ISR, adapters for Node, Vercel and Cloudflare are a config away.
Try it yourself
Move the sliders — watch the plan shift
There's one island on this page. Drag conversion and interaction: hydration moves live between static, lazy and eager. No reload, no guesswork.
Static is where we start. JavaScript is something you earn, not something we sprinkle by default.
Rule of thumb: eager from ~0.3, lazy from ~0.05 — below that, the page stays JS-free.
In a real file
Say what matters — the build does the rest
<page title="Home" description="…" />
<component id="hero" seo="1" conversion="0.9">
<template><h1>Benvenuto</h1></template>
</component>
// conversion 1 → hydrates first · zero JS elsewhere
<component id="cta" conversion="1" interaction="0.85">
<template><button id="buy">Compra</button></template>
<script hydrate>
el.querySelector('#buy').onclick = () => buy();
</script>
</component> How we think about the web
Fast by default, deliberate when it counts
Static is the happy path
Most pages don't need client JavaScript. biagiojs assumes that until a component proves otherwise — so the fast case isn't something you have to fight for.
Business context drives the build
Conversion, SEO and interaction aren't metrics you chase after launch. They're inputs: the scheduler turns them into source order and a hydration plan you can reason about.
Real usage feeds the next build
CrUX field data, analytics and heatmaps land in reports/ and nudge the weights over time — the site learns how people actually use it, not how we guessed they would.
Scaffold a project in one command
Add a few weights to your components, run the build, and see what lands first on the wire. You'll know in minutes if the model fits your site.