Crax

A lightweight React framework built on Vite. A Next.js alternative that brings back the simplicity of Create React App and argues that frontend should just be frontend.

Quick Start

terminal
npx @craxjs/crax create my-app

Works with npm, pnpm, and yarn

Why Crax?

File-Based Routing

Drop a file in src/pages/ and it becomes a route. Dynamic segments, nested layouts, and catch-all routes follow your directory structure.

Instant Startup

Fast dev server startup. Instant HMR. Optimized production builds. Minimal install footprint.

Predictive Navigation

Links prefetch on hover, focus, or when they enter the viewport. Foresight mode predicts user intent from cursor movement. Or disable prefetching entirely.

Global State, Zero Setup

Like useState, but global. createStore gives you a reactive store with no providers, no boilerplate, and no re-render pitfalls. Subscribe from any component, update from anywhere.

Responsive Images

CDN-aware images with automatic srcset generation. Lazy loading and blur-up placeholders included by default.

View Transitions

Native browser transitions between pages with a single hook. Falls back gracefully on unsupported browsers.

SEO

Declarative document head management with JSX. Open Graph, Twitter Cards, structured data, all expressed as standard HTML elements.

Deployment Ready

Dockerfile and Caddy config included. Build to dist/, deploy to any static host or CDN.

Own Your Framework

The entire framework source lives in your project under .crax/. Read it, modify it, delete what you do not use. Not a black box.

See It In Action

File-Based Routing

about.tsx
// src/pages/about.tsx → /about
// src/pages/blog/[id].tsx → /blog/:id
// src/pages/dashboard/layout.tsx → shared layout

export default function AboutPage() {
  return <h1>About</h1>
}

State Management

theme-store.ts
import { createStore, useStore } from '@crax/store'

const themeStore = createStore<'light' | 'dark'>('light')

function ThemeToggle() {
  const [theme, setTheme] = useStore(themeStore)
  return (
    <button onClick={() => setTheme(t => t === 'light' ? 'dark' : 'light')}>
      {theme}
    </button>
  )
}

Smart Link Prefetching

nav.tsx
import { Link } from '@crax/router'

// Smart (default): prefetch on hover, focus, pointerdown, or viewport entry
<Link to="/dashboard">Dashboard</Link>

// Foresight: hover + cursor trajectory prediction
<Link to="/pricing" prefetch="foresight">Pricing</Link>

// None: plain react-router link
<Link to="/terms" prefetch="none">Terms</Link>

See a full app built with Crax: Pokedex Example