A flowlet is a small, live screen the agent builds when you ask for one: a water tracker with a tap-to-drink button and a weekly chart, a shopping list you check off, an expense tracker that reads receipts from a photo, a habit board that reminds you at 9pm. You don't design it and you don't write any config β you describe what you want ("track my daily water"), and the agent assembles it from a catalog of building blocks. It then lives on your dashboard, updates instantly when you tap it, and syncs across your devices.
If you'd rather not start from a blank page, there are also ready-made templates β pick one and it's yours.
Flowlets turn the agent from something you talk to into something that builds you tools. Each one is a real, persistent mini-app that knows your world.
Everything is local. A flowlet's definition, its data, and its photos live in a single SQLite file under your Flowly home β nothing is synced to any server, and the same screen renders natively on Desktop and iOS.
What makes a flowlet different
A flowlet is not a chat message, a static image, or a one-off report:
- It's interactive. Buttons, toggles, steppers, sliders, checklists, forms β you tap and it responds instantly.
- It's live. Its numbers, charts, and progress bars are computed from your data every time you open it. Log a glass of water and the weekly chart moves.
- It's persistent. It stays on your dashboard across sessions, versioned so earlier definitions are never lost.
- It's native. The same definition renders as native SwiftUI on iOS and a native component tree on Desktop β never a cramped web view.
- It's yours. It runs on your machine, on your data, with no round-trip to anyone's cloud.
Compared to artifacts β which are renderable outputs you look at β a flowlet is a renderable surface you operate, with its own state and logic.
How a flowlet works
The single most important idea: your machine owns the truth; the screen is just a renderer. This is what keeps flowlets fast, correct, and private.
- The agent authors a definition. When you ask for a tracker, the agent writes a small declarative document β components, state, and what each tap does β and validates it. No code, no HTML.
- Your device renders it natively. The client reads the definition plus a
flat
valuesmap (all the resolved numbers, lists, and chart data) and draws native controls. It does no math and makes no decisions. - A tap is deterministic β no model involved. When you press a button, the
client sends only "component X was tapped". Your machine looks up what that
component's action is, applies it exactly (add a row, log a value, flip a
toggle), and sends back a fresh
valuesmap. The screen re-renders. There is no language model in the loop for a tap, so it's instant, free, and can never "hallucinate" a wrong result.
The only tap that ever reaches the model is a deliberate one β an agent button
you designed to ask a question, or a photo capture that reads an image.
[!NOTE] Because every tap is a named, declared action rather than free-form code, a flowlet you share can't do anything its definition doesn't spell out. This is the foundation the sharing model (below) is built on.
Anatomy of a flowlet
A flowlet's definition is a handful of parts. You never write these β this is what the agent assembles β but understanding them explains what a flowlet can do:
| Part | What it holds |
|---|---|
| name / icon / accent | The title, an icon, and a hex accent colour for the tile. |
| state | The values the flowlet remembers β a number, a string (a date is stored as one), a flag, a list of rows, or a timer. Each has a default. |
| series | An append-only event log ("drank 250ml at 3pm") that charts and totals read from. |
| computed | Derived values the agent never has to keep in sync β a sum over a list, a percentage, a status sentence. Recomputed every render. |
| layout | The screen itself: the tree of components you see and tap. |
| screens | Optional drill-down pages β tap a list row to open a detail/edit screen. |
| watches | Reminders the flowlet fires itself, with no scheduled model turn. |
| sources | Live external data the flowlet pulls in on a schedule. |
The full catalog of components, actions, and grammar is in the Flowlet catalog reference.
State, values, and computed numbers
A flowlet remembers things in state. A state key has a type β number,
string (a date is stored as one), bool, a list of structured rows, or a
timer β and a default. Tapping a control mutates state deterministically (a
stepper's + increments a number; a toggle flips a flag).
Anything derived is a computed value, so the agent never stores a number it would have to keep correct by hand. A computed can be:
- an aggregate over a list β
sum/count/avg/min/maxof a field, optionally filtered (e.g. "total ofamountfor rows in the last 30 days"); - an aggregate over a series β the same, over the event log, in a time
window (
today,7d,30d,90d,all); - an expression β safe arithmetic and comparisons over other values
(
max(0, monthly_budget - month_total)), with a few date helpers (days_until,days_since,weekday); - a conditional sentence β the first matching case wins, so a card can read "Over budget by 200 βΊ" or "You're doing great" depending on the numbers.
Because these recompute from your data on every render, the screen is always consistent β there's no stale total to get out of step.
Semantic building blocks β the agent states intent, the system owns layout
For the common shapes, the agent doesn't hand-assemble rows and inputs from raw primitives β it uses composites that own their own layout and wiring, so a list row is never lopsided and a form is never mis-wired. Three of them:
list_rowβ one row of a list. The agent says which field is the title, which is the subtitle, which is the trailing value, which is the badge, which is the thumbnail image β and the system lays it out: title on top, a muted detail line under it, the value right-aligned, a photo thumbnail on the left, a chevron if the row drills into a detail screen. Truncation, spacing, and alignment are guaranteed, not left to chance.formβ a multi-field entry card ("add an expense" = title + amount + category + date). The agent lists the fields; the system builds the typed inputs, holds the draft, adds the row on submit, and clears the form. This is why adding an item "just works" instead of leaking half-filled state.tracker_cardβ a headline number plus a chart about a list ("this month" + a bar chart of daily spend). The total and the chart are both computed from the list's rows, so they can never drift from what's actually in the list β deleting a row updates both.
You never name these; the agent picks them. They're what make a generated flowlet look designed rather than assembled.
Lists you build up β todos, shopping, expenses
A list state key holds living rows you add and remove; a repeater renders
one row per item. This is how todo lists, shopping lists, journals, and expense
trackers work.
- Add a row with a quick-add input, a full
form, or aphotocapture. - Check off / edit a row in place, or tap it to open a detail screen. Every user-owned list row is guaranteed to be editable β the system injects the edit controls if the agent didn't, so a wrong value can always be fixed.
- Delete a row by swiping it (a round, deliberate delete), everywhere.
Row edits and deletes are ordinary deterministic actions β no model turn β so a 50-item list stays instant.
Charts
A flowlet draws its own charts natively (Swift Charts on iOS, hand-tuned SVG on Desktop), from data your machine resolves β the client only draws.
- Trends over time β
bar,line, orareaover hours / days / weeks. - Compare series β overlay up to four lines or grouped/stacked bars.
- Breakdowns β a
pieordonutgrouped by category (top slices, with the tail folded into "other"). - A chart about a list β point it at the list itself and it aggregates the
rows, so it stays correct through every add, edit, delete, and photo capture.
(This is what a
tracker_carduses.) - Compact inline β a
sparklineor aheatmapfor an at-a-glance history.
Actions β what a tap does
Every interactive component carries a declared action. The common ones:
set/increment/decrement/toggleβ change a state value.logβ append an event to a series (a "drink 250 ml" button).item_add/item_update/item_toggle/item_remove/item_moveβ manage a dynamic list.reset/remove_lastβ clear a value, or undo the last logged event.timer_toggleβ start/pause a live stopwatch.batchβ do several of the above at once.agentβ the one action that reaches the model: hand it a message, exactly as if you'd typed it. Used sparingly, for the "ask my agent about this" button.
An action can be latched with once β at most once per day, per week, or
ever. This is what makes a "complete the day" button a real guarantee: after it
fires and resets your checkboxes, tapping it again the same day does nothing.
Read a photo into a flowlet
A photo capture is a first-class action: a receipt, a meal, a whiteboard β
the agent reads the image in one isolated, tool-less turn and turns it into a
new list row: the expense's amount and merchant, the meal's calories and macros.
You can take the photo there and then, choose one from your library, or pick an
image file β a meal you already photographed is worth just as much as one you
shoot now.
The image is attacker-controlled input, so the reading turn runs with every tool disabled; it can only look and answer.
Reminders that fire themselves
A flowlet can carry watches β declarative reminders it evaluates on its own, with no scheduled model turn burning tokens. A watch fires on a schedule ("every day at 21:00"), on a condition ("when today's water is still under the goal after 6pm"), when a goal is first met, or when something's gone stale ("no entry in 2 days"). It re-checks the instant its data changes and again on a background heartbeat, with a cooldown so it never nags. Optionally, the agent can compose the reminder text from the live numbers at fire time.
This is why a tracker feels like it's looking out for you β the reminder is part of the flowlet, not a separate cron job. (For reminders that aren't tied to a tracker, use cron.)
Live, external data
A flowlet can bind a list to the outside world with sources β the agent fetches something on a schedule (or on pull-to-refresh) and writes it into a list the screen already renders: today's calendar, your open pull requests, the weather. Source-owned lists are read-only in the UI β the snapshot is replaced, not edited.
Screens that adapt
Any component can carry a visibility condition, so a "you're over budget" callout only appears when you actually are, and a "complete the day" button only shows once both habits are checked. Text can be conditional, too β the same card reads "3 days left" or "due today" from the numbers. All of it is evaluated on your device against the live values, identically on every platform.
Across your devices β and entirely local
A flowlet you create on Desktop appears on your iPhone and vice-versa, because both talk to the same agent on your machine. The state is one source of truth; tap it on one device and every open screen updates.
And it's all local:
- The definition, all state, every logged event, and every captured photo live
in one SQLite file (
flowlets.sqlite) under your Flowly home. - Charts, totals, and conditions are computed on your machine.
- Nothing about a flowlet is sent to any external service unless a
sourceyou set up explicitly fetches it, or anagentbutton you designed sends a message.
Start from a template
Asking for a screen works, but it assumes you already know what to ask for. So Flowly ships a handful of ready-made flowlets β pick a card and you have a working screen a second later:
| Template | What you get |
|---|---|
| Water | A daily goal as a ring, one tap per glass, a weekly chart, and an evening nudge if you're behind. |
| Habits | Two habits to tick off, a "complete the day" button that can only fire once a day, a weekly streak, and 90 days on a grid. |
| Expenses | A monthly budget with an over-budget warning, a category breakdown, and entry by hand or straight from a receipt photo. |
| Tasks | A list you add to and tick off, split into what's open and what's done. |
| Sleep | Log the night, see the 30-day trend against your target, get a bedtime nudge. |
| Mood | A one-tap daily rating, 90 days on a grid, and room for a note about the day. |
Two things worth knowing:
- It's yours immediately. Creating from a template writes an ordinary flowlet you own β there's no lasting link back to the template. Ask the agent to change anything about it ("drop the second habit, add a 7am reminder") and it edits it like any other screen.
- It arrives in your language. The screen is built in whichever language the app is set to, so you get a finished screen rather than one to translate.
On an empty Flowlets page the templates are the page. Once you have flowlets of your own they move out of the way into a single button.
Talking to your agent about flowlets
You never write a definition β you ask. The agent builds, and refines on request:
- "Make me a water tracker with a goal of 3 liters and a weekly chart."
- "Add a habit board β read 1 hour, code 5 hours β with a 9pm reminder."
- "Build an expense tracker where I can add a receipt by photo, and show a monthly total and a category breakdown."
- "On my water tracker, make the daily goal 2.5 liters." β it edits the existing one, versioned.
- "How much did I spend on groceries this month?" β it reads the flowlet's live values and just tells you.
Behind the scenes, when the agent creates or updates a flowlet it also runs a quick self-review β a deterministic set of quality checks (is a list add-able? does a chart drift from its list? does a "complete the day" button have a once-per-day latch?) plus a preview against sample data β and fixes what it flags. That's why a generated flowlet tends to come out right the first time.
Limits and safety
Flowlets are bounded by design, so a generated one can never run away:
- A definition is capped in size and component count; lists cap at 200 rows.
- Photo captures and
agenttaps are rate-limited per flowlet and globally. - A
source's fetch and a watch'sagentcompose are throttled. - The reading turn for a captured photo runs with all tools disabled β it can look at the image and nothing else.
Reference
- Flowlet catalog β the complete component list, action ops, chart shapes, expression grammar, watches and sources schemas, and the serve-time guarantees.
- Artifacts β renderable outputs you look at, the sibling of a flowlet's interactive surface.
- Cron β scheduled reminders that aren't tied to a flowlet.