For the tools your team keeps asking for

Internal tools, shipped by the dozen.

ezship turns a folder of React into a deployed internal app. You or your coding agent edits it, one command ships it, and every app your organisation builds runs on the same database, the same people and the same sign-in. There are no servers, pipelines or auth code to write.

Invite-only by design. Every app needs a signed-in Member.

Built for the apps nobody has time to build

  • Lab management
  • Project boards
  • Warehouse planning
  • IT ticket requests
  • Quality management
  • Expense approvals
  • Inspection checklists

How it works

One folder is one app. The folder is all there is.

A Site is a small React and TypeScript app with a fixed shape. It has no package.json, no config and no build setup to maintain. You write screens; ezship does the rest.

qc-line/
  • App.tsxthe frame and navigation
  • CONTEXT.mdpurpose and decisions, for people and agents
  • pages/
  • index.tsx/
  • defects.tsx/defects
  • defects.$id.tsx/defects/:id
  • components/
  • DefectCard.tsx
  • functions/
  • closeBatch.tsruns on the server
  • constants.ts
  • style.css
  1. 1

    Pull

    ez pull copies a Site's shared files into a working copy: a plain directory you can version with your own git and open in any editor.

  2. 2

    Edit and preview

    Edit it yourself or have an agent do it. ez preview builds on our Builder and serves the result at a private URL against your real data. ez dev rebuilds after every save. Nothing runs on your machine.

  3. 3

    Push and deploy

    ez push records one atomic Version with who made it and when. ez deploy checks the Rules, type-checks and compiles with the React Compiler, then swaps the app in whole. If the build fails, the running app stays as it was.

What you write

Screens and data. No other plumbing.

useLive reads a Table and re-renders the moment anyone changes it. db writes, and the change is scoped to your organisation, checked against the Table's policy and recorded in its History. When several writes must succeed together, a server function runs them in one transaction.

  • Live queries, counts and aggregates
  • Typed rows generated from your schema
  • File uploads straight into a row
  • Zod-validated server functions
  • Links between the Sites of your Instance
pages/defects.tsx
import { useLive, db, Link } from "@ezship/react";
import Badge from "global/Badge";

export default function Defects() {
  const open = useLive("defects", {
    where: { status: "open" },
    order: ["-created_at"],
  });
  const total = useLive.count("defects");

  return (
    <section>
      <h1>{open.length} open of {total}</h1>
      {open.map((d) => (
        <Link key={d.id} to={`/defects/${d.id}`}>
          {d.part} <Badge>{d.severity}</Badge>
        </Link>
      ))}
    </section>
  );
}
functions/closeBatch.ts
import { serverFunction, z } from "@ezship/react/server";

export default serverFunction(
  z.object({ batch: z.string() }),
  async ({ db }, { batch }) => {
    const left = await db.aggregate("defects", {
      where: { batch, status: "open" } });
    if (left.rows[0].count) throw new Error("open defects");
    return db.update("batches", batch, { closed: true });
  });

Made for coding agents

The constraints are the feature.

A Site cannot call fetch, touch the DOM, use storage or install packages. That sounds limiting until an agent is writing the code. The platform enforces the Rules on every build, so what an agent ships is reviewable, predictable and hard to get wrong.

One contract for everyone

Everything anyone does to a Site is an ez command. The CLI, the browser studio and its built-in agent all run the same commands, so an agent can do anything a person can do and nothing a person can't.

Instructions included

ez help is a complete, current brief for an agent. ez clone adds an AGENTS.md that points to it, so Claude Code, Codex or Cursor knows the shape, the Rules and the database before it writes a line.

Context lives with the code

Every Site and the Global Workspace carry a required CONTEXT.md that records the app's purpose, audience, workflows and decisions. The next agent or colleague starts from what the last one learned.

Or stay in the browser

The studio

Not everyone lives in a terminal. At studio.ezship.dev, Builders get an editor, a live preview and an agent in one window, working on the same Sites and the same Versions as the CLI. Start an app in the studio and finish it in your editor, or the other way round.

One App Database per organisation

Many apps, one source of truth.

Internal tools rarely stand alone. The receiving app and the inventory app need the same parts table. In ezship, every Site in your Instance shares its Tables, its people and its components, so the tenth app is quicker to build than the first.

History on every Table

Every insert, update and delete is recorded, with who made it, when and from which build. You can query who changed something and what it looked like last Tuesday, without building an audit log.

Schema that only grows

You declare Tables once in schema.sql. Changes are additive and applied atomically with each deploy, so one app can never break another by dropping a column.

Unique keys and sequences

Engine-enforced unique indexes and per-Table sequence numbers, so invoices and ticket numbers never collide, whoever writes them.

Shared look and parts

The Global Workspace holds your theme, shared components, constants and an optional Shell for branding. Each app picks them up on its next deploy.

Security and tenancy

Private by default, all the way down.

These tools hold real operational data. ezship treats every Site as sensitive from day one.

  • Invite-only, both sides. Builders and Members exist only because someone invited them. Sign-in never reveals who has access.
  • Every app needs sign-in. No Site or Preview is public. Admins can restrict a Site to named people.
  • Your own origins. Each Instance gets its own app and API addresses, and deployed pages never share an origin with the API or the studio.
  • Isolation enforced in the engine. Queries are rewritten and checked by SQLite's authorizer, so no app can reach another organisation's Tables.
  • Clear roles. Admins, Builders and Limited Builders; Members use the apps. Every action lands in the audit log.
  • Nothing is silently lost. Sites archive instead of being deleted, pushes keep their last 50 Versions, and Hosts support encrypted incremental backups.

Ship the tools your team keeps asking for.

ezship is onboarding organisations by invitation. Tell us what you want to build and we'll set up your Instance.