Design system
Patterns
How Ostorya apps lay out pages, talk to the merchant, ask before deleting, handle credits and languages.
Page layout#
- Top row: filters or periods on the start side, actions on the end side (secondary, then the primary button last).
- Then a row of KPI tiles if the screen has numbers, then the content cards, 16px apart.
- Wide screens: a list on the start side and the detail beside it (like Ads Manager). Phones: the list, then the detail full screen.
- Your app's name and the current page go in the desktop menu bar:
bridge.setTitle("Campaigns").
Messages#
- Success and errors go to the desktop toasts:
bridge.notify("Campaign saved"),bridge.notifyError("Meta refused the image. Try another photo."). No red boxes inside your page. - Say what happened and what to do, in plain words. Never show a raw error, a stack trace or an error code alone.
- Things that need the merchant (unread chats, a failed ad) go on your dock icon:
bridge.notify(message, badge). Clear it when handled.
Deletes always ask first#
Every delete or remove opens a confirmation modal that names the thing and what will happen. Never on the first click, never "click again to confirm", never window.confirm().
Credits and paid actions#
- Before a paid action, show its price on the button or next to it: "Draw 9 images · ~225 credits".
- Write credits as whole numbers (
1,250 credits). - When the balance is short, never show an error: open a dialog "Add credits to continue" with the amount needed, whose main button calls
bridge.openBilling(). - Charge only for what the merchant gets: a failed run costs nothing, and the screen says so.
Languages and right to left#
- Write your texts in
theme.locale(Arabic, French and English at least). Arabic setsdir="rtl"onhtml. - Use logical CSS (
margin-inline-start,inset-inline-end,text-align: start) so the layout mirrors by itself. The kit already does. - Numbers, prices and phone numbers stay in Western digits, in every language.
- Leave room: French is about 30% longer than English. Buttons must not wrap or cut a word at 360px.
Writing#
- Short, plain words, the merchant's words: "orders", "delivered", "cash", not internal names.
- Sentence case for everything: "New campaign", not "New Campaign".
- Buttons start with a verb and say exactly what happens: "Build 3 landing pages", not "Submit".
- No fake data: no invented reviews, sales or "12 people are watching". Show
—when a number isn't known.
Review checklist#
Before you submit your app, check each line in the desktop, in light and dark, with Reduce glass on and off, in Arabic, and at 360px:
| Check | |
|---|---|
| The wallpaper shows behind your app; content is on o-card glass cards. | Foundations |
| Primary buttons and switches follow the merchant's accent; statuses use the five tones. | Foundations |
| Body 14px, controls 40px, cards 22px radius: nothing bigger than Ostorya's own apps. | Foundations |
| Every button, tab, filter and menu item has an icon. | Components |
| No native <select>, no native date input, no window.confirm(). | Components |
| Modals and fixed bars stay above the dock. | Components |
| Errors and confirmations use the desktop toasts. | Patterns |
| Every delete asks first in a modal. | Patterns |
| Arabic is right to left and nothing overflows at 360px. | Patterns |
| No fake numbers and no buttons that do nothing. | Patterns |