From 39f802d26a316933b0769ac146e628a4a9d6ae8a Mon Sep 17 00:00:00 2001 From: Benjamin Toby Date: Fri, 20 Mar 2026 12:46:03 +0100 Subject: [PATCH] Update documentaion. --- README.md | 73 ++++- comparisons/NEXTJS.md | 644 ++++++++++++++++++++++++++++++++++++++++++ features/FEATURES.md | 113 ++++++++ package.json | 4 +- 4 files changed, 824 insertions(+), 10 deletions(-) create mode 100644 comparisons/NEXTJS.md create mode 100644 features/FEATURES.md diff --git a/README.md b/README.md index 7772878..c0ff75d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,15 @@ # Bunext -A Next.js-style full-stack meta-framework built on [Bun](https://bun.sh) and React 19. Bunext provides server-side rendering, file-system based routing, Hot Module Replacement (HMR), and client-side hydration — using ESBuild to bundle client assets and Bun's native HTTP server (`Bun.serve`) to handle requests. +A server-rendering framework for React, built on [Bun](https://bun.sh). Bunext handles file-system routing, SSR, HMR, and client hydration — using ESBuild to bundle client assets and `Bun.serve` as the HTTP server. + +## Philosophy + +Bunext is focused on **server-side rendering and processing**. Every page is rendered on the server on every request. The framework deliberately does not implement client-side navigation, SPA routing, or client-side state management — those concerns belong in client-side libraries and are orthogonal to what Bunext is solving. + +The goal is a framework that is: +- Fast — Bun's runtime speed and ESBuild's bundling make the full dev loop snappy +- Transparent — the entire request pipeline is readable and debugable +- Standard — server functions and API handlers use native Web APIs (`Request`, `Response`, `URL`) with no custom wrappers --- @@ -15,6 +24,7 @@ A Next.js-style full-stack meta-framework built on [Bun](https://bun.sh) and Rea - [Pages](#pages) - [Basic Page](#basic-page) - [Server Function](#server-function) + - [Default Server Props](#default-server-props) - [Redirects from Server](#redirects-from-server) - [Custom Response Options](#custom-response-options) - [SEO Metadata](#seo-metadata) @@ -192,6 +202,7 @@ import type { BunextPageServerFn } from "bunext/src/types"; type Props = { props?: { username: string; bio: string }; query?: Record; + url?: URL; }; export const server: BunextPageServerFn<{ @@ -211,11 +222,12 @@ export const server: BunextPageServerFn<{ }; }; -export default function ProfilePage({ props }: Props) { +export default function ProfilePage({ props, url }: Props) { return (

{props?.username}

{props?.bio}

+

Current path: {url?.pathname}

); } @@ -231,6 +243,45 @@ The server function receives a `ctx` object (type `BunxRouteParams`) with: | `query` | `any` | Query string parameters | | `resTransform` | `(res: Response) => Promise\|Response` | Intercept and transform the final response | +### Default Server Props + +Every page component automatically receives a `url` prop — a copy of the request URL object — even if no `server` function is exported. This means you can always read URL data (pathname, search params, origin, etc.) directly from component props without writing a `server` function. + +```tsx +// src/pages/index.tsx +import type { BunextPageModuleServerReturnURLObject } from "bunext/src/types"; + +type Props = { + url?: BunextPageModuleServerReturnURLObject; +}; + +export default function HomePage({ url }: Props) { + return ( +
+

Visiting: {url?.pathname}

+

Origin: {url?.origin}

+
+ ); +} +``` + +The `url` prop exposes the following fields from the standard Web `URL` interface: + +| Field | Type | Example | +| -------------- | ---------------- | -------------------------------- | +| `href` | `string` | `"https://example.com/blog?q=1"` | +| `origin` | `string` | `"https://example.com"` | +| `protocol` | `string` | `"https:"` | +| `host` | `string` | `"example.com"` | +| `hostname` | `string` | `"example.com"` | +| `port` | `string` | `""` | +| `pathname` | `string` | `"/blog"` | +| `search` | `string` | `"?q=1"` | +| `searchParams` | `URLSearchParams` | `URLSearchParams { q: "1" }` | +| `hash` | `string` | `""` | +| `username` | `string` | `""` | +| `password` | `string` | `""` | + ### Redirects from Server Return a `redirect` object from the `server` function to redirect the client: @@ -620,10 +671,7 @@ middleware: async ({ req, url }) => { return new Response("Down for maintenance", { status: 503 }); } - // Add CORS headers to all API responses - if (url.pathname.startsWith("/api/")) { - // Let the request proceed, but transform the response via resTransform on individual routes - } + // For API routes, return undefined to continue — the handler controls its own Response directly }, ``` @@ -679,7 +727,14 @@ Output files are named `[dir]/[name]/[hash]` so filenames change when content ch ### Hot Module Replacement -In development, Bunext injects a script into every HTML page that opens a **Server-Sent Events (SSE)** connection to `/__hmr`. When a rebuild completes and the bundle hash for a page changes, the server pushes an event through the SSE stream and the client reloads the page automatically. +In development, Bunext injects a script into every HTML page that opens a **Server-Sent Events (SSE)** connection to `/__hmr`. When a rebuild completes and the bundle hash for a page changes, the server pushes an `update` event through the stream containing the new artifact metadata. The client then performs a **true in-place HMR update** — no full page reload: + +1. If the page has a CSS bundle, the old `` is replaced with a new one pointing to the updated CSS file (cache-busted with `?t=`). +2. The existing client hydration `