Skip to content
BrainwiresPublic

About

A Deno-native React framework, zero runtime npm. Unmodified Next.js App Router, React, Remix, and Expo/React Native apps run on its own small React — with first-party native capabilities (Capacitor & Deno Desktop) that reimplement the Expo/RN APIs, across web, mobile, and desktop.

Topics

Resources

Contributing

Security policy

Stars

5 stars

Watchers

0 watching

Forks

Latest commit

 

History

2,366 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

denext

denext

JSR JSR Score CI Tests fallow health Source

Write your app once. Ship it as a web app, an iOS and Android app, and a desktop app for macOS, Windows and Linux — from one codebase, one component model, one router and one typed API layer.

denext is a complete application framework for Deno. It brings its own small React 19-compatible core, the app/ router with Server Components and Server Actions, an end-to-end typed API, live data, auth, a database, background jobs and the native shells — so a product team needs one stack, one language and one build, and the framework's runtime pulls nothing from npm. The same denext/mobile call reaches Capacitor on a phone, the native runtime in a desktop window and a web fallback in a browser.

Every accepted web-framework feature, unified and surface compatible. Server Components and Actions, streaming, Partial Prerendering, islands, resumability, live data, a typed API, auth, data and cron live in one framework, behind the React, Next.js, Remix, React Native and Expo APIs developers already know. That compatibility means your existing npm: and jsr: packages work as they are (Radix, Base UI, shadcn/ui, TanStack Router, recharts, react-hook-form, …): there is no new ecosystem to wait for. Bring your existing app.

Lightweight. A 19.6 KB shared client runtime against 136.9 KB for the same routes on Next.js, 0 KB of JavaScript on a page with no interactivity, and SSR on par or faster. Small and fast.

Docs: denext.dev · Package: jsr.io/@denext/denext · Source: github.com/Brainwires/denext · License: MIT

Write it once

A Server Component fetches on the server. A client component uses the platform. Neither knows, or needs to know, which platform it is on.

// app/page.tsx — a Server Component: the query runs on the server, the browser gets HTML
import { listNotes } from "../lib/db.ts"; // Deno's built-in SQLite, nothing to install
import { CopyLink } from "./copy-link.tsx";

export const metadata = { title: "Notes" };

export default async function Home() {
  const notes = await listNotes();
  return (
    <main>
      <ul>{notes.map((n) => <li key={n.id}>{n.title}</li>)}</ul>
      <CopyLink />
    </main>
  );
}
// app/copy-link.tsx — one component for the browser, the phone and the desktop window
"use client";
import { useState } from "denext";
import { runtimePlatform, writeClipboard } from "denext/mobile";

export function CopyLink() {
  const [copied, setCopied] = useState(false);
  const copy = async () => {
    // Capacitor on iOS/Android, the OS clipboard on desktop, navigator.clipboard on the web
    await writeClipboard(location.href);
    setCopied(true);
  };
  return (
    <button type="button" onClick={copy}>
      {copied ? "Copied" : `Copy link (${runtimePlatform()})`}
    </button>
  );
}

The same files become every target:

denext task dev               # the web app, with HMR, at http://localhost:3000
denext task build && denext task start   # the production server (SSR, streaming, Server Actions)
denext task export            # a static export for any host or CDN
denext task desktop           # a native desktop window (Deno Desktop)
denext task desktop:package   # a signed, distributable app (:linux and :windows tasks too)
denext task mobile:sync && denext task mobile:ios   # the Capacitor project, open in Xcode

Quick start

Install the denext command. It is all you need: it brings its own Deno (denext's toolchain, downloaded and checksum-verified by the installer), so the machine needs no Deno of its own.

curl -fsSL https://denext.dev/install.sh | sh     # macOS and Linux; checksum-verified
irm https://denext.dev/install.ps1 | iex          # Windows (PowerShell); checksum-verified

Scaffold a project with the targets you want and run it:

denext create my-app --desktop --capacitor
cd my-app
denext task dev

create asks about Tailwind, a src/ layout, the auto-memo compiler, the desktop target and the Capacitor target (pass the flags, or --yes, to skip the prompt). Already have Deno 2.9 or newer? Then nothing needs installing: deno run -A jsr:@denext/denext/cli create my-app and deno task dev do the same, and deno install -A -g -n denext jsr:@denext/denext/cli puts the command on your PATH through Deno.

Then Getting started or the tutorial take it from here. examples/ holds a complete app for every feature below, including examples/native (one app packaged for the web, the desktop and a phone).

One codebase, every platform

The web. The App Router with Server Components, streaming and Suspense, Server Actions, parallel and intercepting routes, middleware, metadata, images, fonts and i18n. Pages with no interactivity ship 0 KB of JavaScript; interactive routes ship a shared ~20 KB runtime. Choose per route between server rendering, a static export, Partial Prerendering with Cache Components, Astro-style islands and Qwik-style resumability. A strict Content-Security-Policy is on by default. → Routing · Rendering strategies · Islands · Resumability

iOS and Android. The export runs in a Capacitor shell, and denext/mobile gives the page the device without a single @capacitor/* import: safe areas, the keyboard, the Android back gesture, system bars, haptics, the clipboard, sharing, files, pickers, the camera and barcode scanning, SQLite, the Keychain and biometrics, geolocation, local and push notifications, deep links, Sign in with Apple and Google, OAuth sessions, home-screen quick actions, native context menus, in-app purchases and more. denext mobile add <capability> installs the native side. Native views (<NativeViewSlot> for maps and video) sit inside the page; share extensions, home-screen widgets and Live Activities are generated Xcode targets; nativeModule() reaches your own Swift and Kotlin. Signed over-the-air UI updates, icon and splash generation, store builds and store submission are CLI verbs. → Mobile · Store builds · Your own native code

macOS, Windows and Linux. denext desktop wraps the export in a native window on Deno Desktop (a single binary, no Chromium) at Electron parity: a stable custom-scheme origin so sign-in providers and web storage treat the app as one site, single-instance launch, deep links and opened files, a trusted preload, an application menu, a tray icon, dock and taskbar badges, native notifications with scheduling and action buttons, native file dialogs, the OS clipboard (text, HTML and images), file drag and drop in both directions, global shortcuts, launch at login, and a window API (denext/desktop/window: fullscreen, maximize, minimum and maximum size, screens, title-bar styles, Mica, Acrylic and vibrancy, a cancelable close). Sign-in uses the system browser or ASWebAuthenticationSession; native passkeys work in the window on macOS and Windows (Linux, which has no OS passkey API, signs in through the browser); denext/desktop/clerk runs Clerk's Electron bridge unchanged. Updates are signed full-app self-updates with downgrade protection, an atomic swap and automatic rollback. Node-API addons load on all three operating systems, and defineDesktopExtension exposes your own Deno code to the page. Packaging is least-privilege: the --allow-* flags are derived from the capabilities you enable. The same denext/mobile functions answer here too: the keychain, files, SQLite, the shell, keep-awake. → Desktop apps

React Native and Expo code. reactNative: true builds an Expo or React Native app's own source for the web and the shells: react-native through react-native-web, every expo-* package through a denext/expo/* shim over denext/mobile, expo-router and React Navigation on denext/navigation, FlatList and FlashList on VirtualList, Reanimated with no Babel plugin. → React Native / Expo · denext vs React Native

Native-feel UI. VirtualList renders ten-million-row lists with exact scrollToIndex, bottom anchoring and intact iOS momentum; denext/navigation keeps pushed screens mounted with platform transitions, the iOS swipe back, state-keeping tabs and bottom sheets. → Lists · Native-feel navigation

Everything an app needs, built in

Typed, end to end. defineApi takes Standard Schemas (Zod, Valibot, ArkType, TypeBox) for params, query, body and response, and the generated .denext/api.ts types every call through createApiClient() and useApi — path, method, input, output and the error codes. defineAction does the same for Server Actions and useActionState. <Link href> and useRouter().push are typed to the app's real routes. The same definitions serve OpenAPI 3.1 and a docs page (@denext/openapi) or GraphQL with subscriptions (@denext/graphql). → Typed API · Server Actions · OpenAPI · GraphQL

Live data. <Live tags={[...]}> re-renders one server-rendered boundary and pushes it over a WebSocket when a cache tag is invalidated from anywhere — a Server Action, a webhook, a cron. defineSubscription is a server-validated, authorized live query; createChannel is typed server push; useLive, usePresence and useLiveOptimistic ride the same socket, across instances. → Live

Auth. denextAuth() mounts /auth/* with twelve OAuth/OIDC presets, SAML 2.0 identity providers, email and password, magic links and one-time codes (sent with smtpMailer() or your own mailer), passkeys, TOTP second factor with backup codes, email verification and password reset, revocable sessions, roles, bearer API tokens, native sign-in for the shells, rate limits and account deletion. auth(), requireAuth() and requireSession() cover the server, middleware and API routes. → Auth

Data. Deno's built-in SQLite with no install, Deno KV, Postgres and MySQL drivers, Drizzle and Prisma; use cache, cacheTag, revalidateTag and a durable SQLite cache store; typed content collections for Markdown, MDX, YAML and JSON (@denext/content-collections); uploads; image optimization; OG images. → Databases · Data & caching · Content collections

Backend. The opt-in @denext/backend plugin puts backend services inside the app: storage on S3, R2, MinIO or the filesystem (buckets with per-bucket rules, signed URLs, image transforms), Postgres scoped by Supabase-compatible row-level security (db() runs each query as the request's user), realtime changes from your tables (useTableChanges), and a PostgREST-style REST API with a typed from() client. It also serves Supabase's APIs (/auth/v1, /rest/v1, /storage/v1, realtime, /functions/v1), each behind its own option, so the stock @supabase/supabase-js client works unchanged against the app; plus Vault, pgmq queues, pgvector search, database webhooks and denext db (migrations, diff, dump, lint, types). Postgres itself is first-party in core: a client on Deno.SQL, Postgres stores for auth, sessions, rate limits, the cache and job history, and SQL migrations; denext ui browses the database, and denext dashboard serves the same Database section behind a password for the self-hosted stack (denext stack up | health | backup | restore). → Backend · Coming from Supabase

Background work. defineJob in jobs/<name>.ts, scheduled with cron expressions (Deno.cron where the platform has it), run on demand with runJob() or denext job, with run history. Long-lived work (a queue consumer, a feed tail) goes in services/<name>.ts, which a supervisor restarts with backoff (supervise(), defineService()). → Jobs · Services

Production. Graceful drain, per-request timeouts, concurrency ceilings, body caps, gzip and brotli, CORS, a security-header set, SSRF-safe fetch and image optimization, CSRF-defended actions, request ids, per-address rate limits that key on the client address your proxy sends (rateLimitHeader), instrumentation, denext build --compile (the server as one executable), a Docker generator (the image, plus a compose stack with Postgres, an S3 store and a migrations step detected from your config) and recipes for Docker, Deno Deploy and self-hosting. → Deployment · Security · Production checklist

Extensible. A plugin hooks six seams (routes, requests, build, prepare-time codegen, teardown, CLI verbs); the first-party plugins are the Pages Router, React Router v7, htmx, OpenAPI, GraphQL, content collections, the backend and an Effect bridge. A project adds its own CLI verbs in denext.config.ts. → Plugins

Developer experience

One CLI covers the lifecycle: dev with per-module HMR and Fast Refresh, build, export, start, generate (routes, components, actions, jobs, tests, Docker), test, lint, fmt, check, add, plugin, patch (patch-package for npm dependencies and for denext itself), desktop, mobile, ota, job and completions. Every other Deno verb works through it too (denext compile, denext run, denext x, …), and denext task runs a deno.json task, all on denext's own Deno build (Deno.SQL, Vitest/Jest compatibility in deno test), downloaded and SHA-256-verified on first need. → Toolchain Type, lint and build errors are explained in plain language with a fix (--raw prints Deno's own); a dev-time overlay reports server errors and type errors; the DevTools panel shows the live component tree and why a component re-rendered. → CLI reference · DevTools

Tooling that proves things. denext doctor validates the config and renders every route; denext audit inventories dependencies, proves the runtime is zero-npm and writes an SBOM; denext analyze breaks the client bundle down by chunk and role; denext profile measures CPU self-time and heap growth for a route in headless Chromium, with a budget gate for CI. denext/testing drives the whole app the way a JavaScript-disabled browser would (cookie jar, form submit), renders components with real hooks and events, and probes every route for a well-formed document; a test file that imports vitest gets fake timers and vi.mock under denext test. → Testing · Profiling · Doctor & audit

A GUI over the project. denext ui serves a loopback project dashboard: a schema-driven, comment-preserving denext.config.ts editor, a Cron page, plugin option forms and JSR search, every generate kind, Docker (the self-hosted stack's toggles) and docker-compose.yml editing, a Desktop panel that sets up code signing from the identities in your keychain, a Setup page for a fresh clone, a Services page for the services/ supervision tree, and a Database section (tables and rows, a SQL editor, RLS policies, migrations, storage, users, logs, realtime, Edge Functions and health). Project code never runs in the UI's process. → Project UI

Built for AI agents. denext mcp is a first-party MCP server: it lints a snippet before an agent writes it, maps a React or Next import, scaffolds, renders a route or component server-side and returns the HTML, reads a running dev server's errors, console and HMR events, exposes the live component tree and hook state, profiles a route, searches the docs and indexes the codebase. AGENTS.md is the authoring guide agents read, and denext.dev/llms.txt is the same guide for any model. → MCP server

Bring your existing app

denext is React at the reconciler level, so the React ecosystem runs on it, and its router is the Next.js App Router, so that knowledge transfers directly. denext migrate converts a project in one pass and keeps your source intact:

  • Next.js (App Router and Pages Router): the deno.json alias map resolves react and next/* to denext; --codemod rewrites imports to native denext. → Migrating from Next.js · Pages Router
  • Remix and React Router v7: loaders, actions, meta and error boundaries run on the denext/remix runtime. → Migrating from Remix · React Router
  • Expo and React Native: migrate --from expo writes the config and a capacitor.config.ts and reports which native-only packages need a recipe. → Coming from React Native · Native SDK recipes
  • Vite, CRA and any React SPA: mode: "spa" hosts a client-only app on the same runtime, with the same desktop and mobile packaging. → SPA mode

Coming from Supabase? The database carries over: your schema, SQL functions and row-level security policies run unchanged on @denext/backend (the same roles and auth.* functions), and the guide moves users and files. → Coming from Supabase

npm: and jsr: libraries work as usual, and denext patch records a reviewable patch for an npm package or for denext itself. The honest edges are kept in one place: Known limitations and Deliberate differences.

Small and fast

denext ships its own React core instead of React + ReactDOM + a framework runtime, so a browser downloads about 7× less JavaScript than for the same app on Next.js, and a static page downloads none. Measured on examples/hello (production, gzipped, Next.js 16.3 + React 19.2 on the same routes):

What a browser downloads denext Next.js
Shared client runtime 19.6 KB 136.9 KB
First load of / 20.8 KB 137.3 KB
Each later navigation ~1 KB route chunk

Hydration and SSR throughput run on par or faster, and on a library-heavy app (recharts, react-hook-form, Radix) the routes ship roughly half or less. Every number is reproducible with bench/run.ts; the methodology and the full results are in bench/REPORT.md.

The framework's runtime carries no npm dependencies — CI-enforced — so npm audit-class advisories have nothing to land on and an SBOM for a denext app is essentially the app. Build-time tooling uses esbuild plus first-party Rust-to-wasm packages (@denext/swc, @denext/lightningcss, @denext/photon, @denext/avif, @denext/og).

The denext command

The binary is a CLI, not a second copy of the framework: inside a project every verb that loads the app re-execs the denext version the project pins, so denext build produces exactly what deno task build would. It needs no Deno installed: every verb that runs Deno (denext task …, denext test, denext fmt, the pinned-version re-exec) runs it on denext's own Deno toolchain, downloaded and SHA-256-verified on first need. Four ways to get it:

  1. curl -fsSL https://denext.dev/install.sh | sh — the released binary for macOS and Linux (~/.denext/bin; checksum-verified; DENEXT_VERSION picks a release). The installer then runs denext toolchain install, and — only when no deno is on your PATH — denext toolchain link, so deno is that toolchain too (DENEXT_NO_DENO_LINK=1 skips the link, DENEXT_NO_TOOLCHAIN=1 both; an existing deno is never replaced). On Windows, irm https://denext.dev/install.ps1 | iex in PowerShell does the same per-user, no admin (%USERPROFILE%\.denext\bin, added to your user Path; uninstall with & ([scriptblock]::Create((irm https://denext.dev/install.ps1))) -Uninstall). Each release also carries a Homebrew formula, a Scoop manifest and a winget manifest set beside the archives.
  2. deno install -A -g -n denext jsr:@denext/denext/cli — a launcher through your Deno (then denext toolchain install fetches the toolchain and caches every verb for offline use).
  3. deno task compile from a checkout.
  4. Nothing at all: deno run -A jsr:@denext/denext/cli <verb> does the same thing, and the scaffolded dev / build / start tasks run that CLI pinned to the project's version.

A project is a deno.json with the JSX settings, the import map and the lint plugin — no node_modules, no lockfile churn:

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "denext",
    "lib": ["deno.window", "dom", "dom.iterable", "dom.asynciterable"]
  },
  "imports": {
    "denext": "jsr:@denext/denext@^4.0.0",
    "denext/jsx-runtime": "jsr:@denext/denext@^4.0.0/jsx-runtime",
    "denext/server": "jsr:@denext/denext@^4.0.0/server",
    "denext/client": "jsr:@denext/denext@^4.0.0/client"
  },
  "lint": { "plugins": ["jsr:@denext/denext@^4.0.0/lint-plugin"] }
}

Every entry point (denext, denext/server, denext/client, denext/live, denext/mobile, denext/navigation, denext/desktop, denext/testing, denext/plugin-kit, …) is documented in the API reference; every config key in Configuration.

Documentation

Learn — Getting started · Tutorial · Project layout · Routing · Data & caching · Rendering · Styling

Build — Typed API · Server Actions · Live · Auth · Databases · Backend · Jobs · Content collections · Testing

Ship — Deployment · Desktop apps · Mobile · App backend · Security · Production checklist

Reference — CLI · Configuration · API · Plugins · MCP server · Project UI · Examples · Troubleshooting · Changelog

Under the hood — FEATURES.md (every feature, with the mechanism) · Architecture · KNOWN-DIFFERENCES.md · KNOWN-LIMITATIONS.md

The project — MISSION.md · POLICIES.md (guardrails and the security policy) · ROADMAP.md · CONTRIBUTING.md · CHANGELOG.md · AGENTS.md

License

MIT — see LICENSE.

About

A Deno-native React framework, zero runtime npm. Unmodified Next.js App Router, React, Remix, and Expo/React Native apps run on its own small React — with first-party native capabilities (Capacitor & Deno Desktop) that reimplement the Expo/RN APIs, across web, mobile, and desktop.

Topics

Resources

Contributing

Security policy

Stars

5 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Contributors

Languages