@chr33s/solarflare
v0.0.13
Published
> [!WARNING] > Experimental: API is unstable and not production-ready.
Downloads
864
Readme
[!WARNING]
Experimental: API is unstable and not production-ready.
Solarflare
Cloudflare-optimized streaming SSR/CSR meta-framework built on web platform APIs, whilst retaining the DX of JSX / React|Preact.
Features
- Streaming SSR — File-based routing with deferred promise streaming
- Web Components — Hydration via
preact-custom-element - SPA Navigation — Navigation API + View Transitions
- HMR — Hot module replacement with scroll restoration
- Styles — Constructable Stylesheets, critical CSS extraction
- Performance — Early hints, route caching, preconnect hints, speculation rules
- Cloudflare — Workers-optimized with edge caching
- TypeScript — Full type safety
Requirements
- Node.js ≥v24.12.0
- Modern browser (Chrome 102+, Edge 102+, Safari 15.4+)
CLI
solarflare [options]| Option | Description |
| -------------------- | ------------------------- |
| --clean, -c | Clean output before build |
| --debug, -d | Enable debugging |
| --production, -p | Optimize for production |
| --serve, -s | Start dev server with HMR |
| --sourcemap | Generate source maps |
| --watch, -w | Watch and rebuild |
Conventions
| Directory | Purpose |
| ---------- | ------------------------------------------------------- |
| ./src | Original (source) human readable code |
| ./dist | Compiled (distribution) [client, server] output code |
| ./public | Static assets, copied verbatim to dist/client directory |
| File | Purpose |
| -------------- | -------------------------------- |
| *.client.tsx | Client component (web component) |
| *.server.tsx | Server handler (Workers runtime) |
| _layout.tsx | Layout wrapper |
| _* | Private (not routed) |
| $param | Dynamic segment → :param |
| index.* | Directory root |
| Path | Purpose |
| ----- | ---------------------------------------- |
| /_* | reserved internal use (e.g. /_console) |
API
Server Handler
export default async function server(request: Request, params: Record<string, string>) {
return {
_status: 200,
_headers: { "Cache-Control": "max-age=3600" },
title: "Hello",
};
}Promise-valued props are streamed independently (deferred):
export default async function server() {
const user = await fetchUser(); // blocking
const analytics = fetchAnalytics(); // deferred
const recommendations = fetchRecommendations(); // deferred
return { user, analytics, recommendations };
}Client Component
export default function Client({ title }: { title: string }) {
return <h1>{title}</h1>;
}Layout
import type { VNode } from "preact";
import { Body, Head } from "@chr33s/solarflare/server";
export default function Layout({ children }: { children: VNode }) {
return (
<html>
<head>
<Head />
</html>
<body>
{children}
<Body />
</body>
</html>
);
}Deferred (Suspense like deferred renderer)
import { Deferred } from "@chr33s/solarflare/client";
<Deferred priority="high" fallback={<div>Loading additional content...</div>}>
...
</Deferred>;Configuration using meta tags
<!-- router -->
<meta name="sf:base" content="/" />
<meta name="sf:scroll-behavior" content="auto" />
<meta name="sf:view-transitions" content="false" />
<meta name="sf:skip-node-replacement" content="s-*" />
<!-- performance -->
<meta name="sf:preconnect" content="https://cdn.example.com" />
<meta name="sf:early-flush" content="true" />
<meta name="sf:cache-max-age" content="300" />
<meta name="sf:cache-swr" content="3600" />
<meta name="sf:prefetch" content="/about, /faq, /blog/*" />
<meta name="sf:prerender" content="/, /landing" />
<meta name="sf:prefetch-selector" content="a.nav-link" />
<meta name="sf:speculation-eagerness" content="moderate" />Custom Web Component
import { define } from "@chr33s/solarflare/client";
export default define(MyComponent, { shadow: true });Environment
| File | Purpose |
| ----------------------- | ------------------------------------------------------------ |
| WRANGLER_LOG | Set logging verbosity for both wrangler & console forwarding |
| WRANGLER_SEND_METRICS | Disable sending anonymous usage data to Cloudflare |
Examples
- Basic — Layouts, dynamic routes, API, components
- Bun — Bun runtime example
- Deno — Deno runtime example
- DSD — Declarative Shadow DOM example
- Minimal — Single route
- Node — Using
srvxinstead of Workers - Shopify App — Shopify app starter
Development
npm install
npm run devCodemod
npm install --save-optional
npx solarflare --codemod ./appLicense
MIT
