@nativefragments/core
v0.5.0
Published
Zero dependency, zero build framework core for agents building AI-friendly web applications.
Maintainers
Readme
Native Fragments Core
Zero dependencies. Zero build. Blazing fast. Built for agents. AI-friendly applications. Zero maintenance.
Native Fragments Core is the runtime package for building fast, maintainable web
applications with native browser APIs: HTML, CSS, JavaScript, Custom Elements,
Shadow DOM, Fetch, History, and standard server-side Response objects.
- Website: https://nativefragments.org
- Docs: https://docs.nativefragments.org
For a new app, start with the scaffold:
npm create @nativefragments/app@latest my-app
cd my-app
npm run devInstall the core package directly when you are wiring Native Fragments into an existing app:
npm i @nativefragments/coreWhat Core Provides
- Escaped server-side HTML templates.
- Explicit route helpers with path params.
- Full-page and fragment render helpers.
- Cloudflare Worker adapter.
- Browser fragment navigation with first-class prefetching.
- Nested fragment slots for routes inside routes.
- Web Worker RPC helpers for moving expensive client work off the main thread.
- Shadow DOM component helpers, including declarative Shadow DOM support to avoid refresh FOUC.
- Agent skill shipped with the package.
Package Exports
import { declarativeShadow, fragment, html, route } from "@nativefragments/core/server";
import { createCloudflareHandler } from "@nativefragments/core/cloudflare";Browser helpers are plain ES modules that can be served from your app's
public/nativefragments directory:
import { installFragmentNavigation } from "/nativefragments/router.js";
import { shadow, sheet } from "/nativefragments/component.js";
import { createWorkerClient } from "/nativefragments/worker.js";Nested Fragments
Routes can expose named fragment renderers for app regions that navigate inside the current page:
const profile = fragment("settings-panel", profilePanel);
route("/settings/profile", {
render: settingsPage,
fragments: [profile]
});<a href="/settings/profile" data-fragment-slot="settings-panel" data-fragment-prefetch="intent">
Profile
</a>
<section data-fragment-slot="settings-panel"></section>The browser router sends x-fragment-slot: settings-panel, swaps only that
section, and keeps the full route as the no-JavaScript fallback.
External links, static documents, modified clicks, and links marked with
data-nativefragments-reload or data-fragment-navigation="false" keep normal
browser navigation:
<a href="/agents.txt" data-nativefragments-reload>Get started for agents</a>Routes support path params:
route("/settings/:panel", {
render: ({ params }) => settingsPage(params.panel),
fragments: [profile]
});Fragment Prefetch
The browser router prefetches same-origin fragments on hover and focus by default. Links can override the behavior:
<a href="/reports" data-fragment-prefetch="visible">Reports</a>
<a href="/settings" data-fragment-prefetch="load">Settings</a>
<a href="/logout" data-fragment-prefetch="none">Log out</a>Prefetching is based on real anchors in the document. Agents and browsers can inspect the same links; there is no separate framework manifest to understand.
Content Security Policy
The Cloudflare adapter creates a per-request nonce and passes it to the app
shell. Use it on inline scripts/styles when you enable a strict CSP:
import { createCloudflareHandler } from "@nativefragments/core/cloudflare";
import { attrs, html, raw } from "@nativefragments/core/server";
import { routes } from "./routes.js";
export const shell = ({ body, meta, nonce }) => html`<!doctype html>
<html>
<head>
<script${attrs({ nonce })}>
document.documentElement.classList.add("js");
</script>
</head>
<body>${raw(body)}</body>
</html>`;
export default createCloudflareHandler({
routes,
shell,
contentSecurityPolicy: ({ nonce }) =>
[
"default-src 'self'",
"base-uri 'none'",
"object-src 'none'",
`script-src 'self' 'nonce-${nonce}'`,
`style-src 'self' 'nonce-${nonce}'`
].join("; ")
});The default policy remains compatible: frame-ancestors 'self'. Strict
script-src/style-src is opt-in so existing apps do not break.
Worker Helpers
Use workers for search, filtering, parsing, and other client work that can run away from the main thread:
// public/app/search-worker.js
import { exposeWorker } from "/nativefragments/worker.js";
exposeWorker({
search: ({ rows, query }) =>
rows.filter((row) => row.name.toLowerCase().includes(query.toLowerCase()))
});// public/app/search.js
import { createWorkerClient } from "/nativefragments/worker.js";
const searchWorker = createWorkerClient("/app/search-worker.js");
const rows = await searchWorker.call("search", { rows: allRows, query: "oslo" });No-FOUC Components
For components visible on first paint, render a declarative shadow template on
the server and hydrate it with shadow() in the browser:
html`<app-card>${declarativeShadow({
styles: [`:host { display: block; }`],
html: html`<article>Ready at first paint</article>`
})}</app-card>`;The browser shadow() helper preserves that server-rendered shadow root on the
first upgrade, then updates normally on later renders.
Do not ship an empty above-the-fold custom element and fill it only after the browser imports the component module. That is a layout-shift bug. For non-trivial components, put the shadow HTML and CSS in a shared template module and import it from both the server renderer and browser component.
Agent Skill
Agents can read the shipped framework conventions from:
node_modules/@nativefragments/core/skills/nativefragments/SKILL.mdUse that file as the editing brief before changing a Native Fragments app.
API Reference
Links
- Website: https://nativefragments.org
- Docs: https://docs.nativefragments.org
- GitHub: https://github.com/somedudeokay/nativefragments
- npm: https://www.npmjs.com/package/@nativefragments/core
