FishTea

solid ground, liquid UI

Describe a business once.
Derive everything else.

One spec.json gives you the Postgres schema, the classifier's tool list, the planner, the UI and an operator console. Conversation replaces routing: a small on-device model turns what a visitor says into a shape, the planner composes typed calls, and the answer pours into one of seven vessels.

A business is not a set of pages. It is an authority that answers questions.

A shoe store is a place where you can ask anything about shoes. That is the whole definition — and none of it requires a page.

Software is assembled from modules built for everyone, so every variation — a different customer, tier, market or permission — becomes conditional logic draped over something generic. That is inherited, not careless: we store data in rows and columns, so we build software in the shape of that storage, and anything not uniform arrives late as a layer bolted on top. It shows up most painfully in the URL, a string we have spent two decades forcing to act like a memory.

FishTea starts from the other end. Describe what may be asked and by whom, and let the interface be the last and thinnest thing.

Browsing is not a funnel. It is how a customer works out what they implicitly like. Most of it is not purchase intent, and treating it as a path to checkout measures the wrong thing.

Search is not a result set to filter. The search is the question, and what comes back is an opportunity to ignore or to go deeper. "Not those, something warmer" is not a refinement — it is the next turn.

Personalisation stops being a layer. If the interaction is the conversation, every surface is already personal — by what was actually said, not by a profile.

The longer argument →

A whole application in one command

Answer an interview about your business; get a running stack. The archetype is a starting point, not a cage — everything it wrote is yours to edit.

$ fishtea new myshop --template ecommerce --interactive
$ cd myshop
$ fishtea up

  db          postgres + pgvector   ready
  classifier  needle3, 3 workers    warm
  core        http://10.0.0.19:3000 listening
  ui          http://10.0.0.19:5173

The visitor types "something linen for a summer wedding, under £80". The classifier picks the findProducts shape and fills its arguments; the planner runs the typed calls the shape names; the answer pours into a list vessel with the provenance strip underneath — which shape answered, what it read, what it wrote, how long it took.

Nothing about that is hand-written. It is all derived from the spec.

Five archetypes

Each one is a complete, runnable application with seed data and an onboarding interview that turns it into your business.

ecommerce

A catalogue, a cart, orders — and vendor feeds, so stock can come from somewhere else.

portfolio

A person you can interview: skills, projects, an honest assessment of fit.

verification

Consent, attestation, and disclosure limited to the purpose asked for.

program

Sessions and registration: capacity, ages, sibling discounts, scholarships.

blank

One entity, one read, one write. Start here when nothing else fits.

Plugins for everything outside the conversation

Six seams, one mechanism. A plugin is a directory with a manifest; what it contributes is merged when the spec loads and never written into your spec.json.

integration

Calls, entities and shapes — Stripe, a frontier model, a shipping quote.

ui

A design system: tokens, and optionally its own vessels.

auth

How a visitor becomes known.

classifier

An alternative to the on-device needle pool.

channel

Where a notification is delivered.

archetype

A template fishtea new can start from.

How plugins work →

Upgrade without regenerating

An application pins a framework range and records where every file came from, so an upstream fix reaches it without touching a line you wrote.

$ fishtea update

framework  1.1.0 → 1.2.0  (pinned ^1.1.0)
spec       format 1.1 → 1.2
files      2 to update, 1 new, 1 conflicting, 3 yours

   ↑ calls/cart_add.sql
   + calls/products_newest.sql
   ! calls/products_related.sql — you changed it and so
     did the archetype; the new one lands as .new

Every framework version you install stays on disk and fishtea use <version> switches between them by moving one symlink. Going back is as cheap as going forward — which is the only reason going forward is comfortable.

Versioning and updates →