Skip to content

junebuild/june

Repository files navigation

June

The agent-ready React framework. One page definition serves humans (streamed HTML, zero client JS) and agents (markdown, JSON, MCP) — nothing drifts, because nothing is duplicated.

Status: 0.0.x preview. The spec is still being drafted and APIs will change. Early feedback is the point — open an issue.

Quick start

npm create june@latest my-app
cd my-app && npm install
npm run dev          # → http://localhost:3000

The scaffolder runs on Node; the june CLI runs on Bun (≥ 1.3).

You get a working app, not a blank page:

my-app/
  app/
    page.tsx          # one page — also answers /.json and /.md
    users/page.tsx    # a second route with a defineAction() → an MCP tool
    layout.tsx        # wraps every page (nested layouts compose root → leaf)
    Counter.tsx       # a client island — the ONE subtree that hydrates
    _client.tsx       # the island registry; its presence enables /client.js
  june.config.ts      # exists to turn things OFF — defaults are on
  package.json

Then try both audiences:

curl localhost:3000/.md        # the page you just saw, as markdown
curl -X POST localhost:3000/mcp \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
npx june info                  # routes + the agent surface, at a glance

One definition, every surface

A page's default export is the view; named exports configure the other surfaces. .json auto-derives from the loader data:

import type { RouteContext, Loaded } from "@junejs/core/route";

export const loader = (ctx: RouteContext<{ slug: string }>) => fetchPost(ctx.params.slug);

export default function Post(post: Loaded<typeof loader>) {  // GET /posts/x      → streamed HTML
  return <article></article>;
}

export const md = (post: Loaded<typeof loader>) => post.original;  // GET /posts/x.md → authored markdown
// GET /posts/x.json → the loader data, auto-derived

And one defineAction() is simultaneously a server action for your UI and an MCP tool at /mcp — same run(input, ctx), same authorization gate. llms.txt, sitemap, and an API catalog derive from the route graph automatically.

What's in the box

Every docs page is also markdown — append .md to any june.build URL. The site is built with June and is its own demo.

Honest limits (so you can calibrate)

No streamed Suspense fallbacks yet, no Flight-payload navigation, and the Rust+V8 runtime numbers on the site are an experimental track — today's host is Bun/Node, deploying to Workers. The full list lives on june.build/why.

This repository

packages/core         @junejs/core — the pure contract layer (zero node:*, enforced)
packages/june         @junejs/server — host adapters, dev server, build, deploy
packages/cli          @junejs/cli — the `june` command
packages/db           @junejs/db — ambient db/kv/blob (request-scoped, edge-safe)
packages/juno         @junejs/juno — the default data layer
packages/create-june  the scaffolder
apps/june.build       the framework site, dogfooded on June
examples/             fixtures (the golden dev ≡ built-worker parity contract)
docs/                 architecture notes
bun install
bun run ci     # typecheck + the full suite (incl. parity + packed-artifact E2E)

License

MIT © June.build

About

The agent-ready React framework - serves humans (streamed HTML, zero client JS) and agents (markdown, JSON, MCP) from one definition. Web-standards core, deploys to Cloudflare Workers.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors