Three visual directions (Skärgård, Kvitto, Kalas) as self-contained HTML pages with every SPEC §13.3 screen in light and dark, Swedish, plus PNG exports and the exporter script. Direction-independent docs: ia.md, screens.md, flows.md, components.md, tokens.md (values for all three directions), strings.csv (key,en,sv,notes), and the comparison with a recommendation in directions/README.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
11 KiB
Kvitt: flows
Status: U1 proposal (2026-10-17). Step-by-step flows with screen ids (ia.md, screens.md). Rules referenced by spec section; nothing here redefines them. Data from the shared mock household (Jacob = owner/admin, Anna = partner; today lördag 17 oktober 2026).
Notation: User does · System does · S-n screen · ⟶ navigation.
F-1 First run as admin (US-1, FR-1, FR-2, FR-5)
- Jacob runs
kvitt-server bootstrapon the Pi (outside the app); it prints the code7K3M-QX9D-2HPAand the linkhttps://icehack.asuscomm.com:8443/i/7K3MQX9D2HPA(AC-1.1). - Jacob opens the link on the phone. The landing page (AC-2.5) offers "Ladda ner Kvitt" (first time) and "Öppna i Kvitt".
- Jacob installs the APK (Android asks once to allow installs from the browser; outside the app), then taps "Öppna i Kvitt" ⟶
S-1with server and code filled (AC-2.6). Without a link:S-1empty, he types the code (server prefilled). - Jacob types his name in "Ditt namn" and taps "Para ihop". Progress "Parar ihop…"; pairs with the phone model as device name ("Galaxy S26"). (
S-1always has "Ditt namn" on a first pairing because AC-2.4 sends the display name in the accept call and the app cannot know the invite kind beforehand; the server ignores it fordeviceinvites. The field is hidden in the "Para ihop telefonen igen" variant.) - Full sync (AC-2.9) ⟶
S-4loading state "Hämtar era utgifter…" ⟶ the system notification-permission prompt. - Partner not yet joined ⟶
S-4shows theS-3content "Väntar på din partner" (AC-5.1). - Jacob taps "Bjud in partner" ⟶
S-21, apartnerinvite is created and shown: code in groups of 4, link, "Gäller till tis 20 okt. 14:02". - Jacob taps "Dela" ⟶ Android share sheet ⟶ sends the message to Anna (SMS, Signal, …). Back ⟶
S-3now shows the expiry. - When Anna has joined (F-2), the next sync replaces
S-3withS-4empty state "Skapa ert första konto" ⟶ Jacob taps "Nytt konto" ⟶S-6"Vardag", 50/50 ⟶ Spara ⟶S-4with the account and the FAB.
Error branches: invite_invalid / network / rate_limited inline on S-1 (screens.md S-1). Lost every phone later: kvitt-server pair-device (AC-1.6) then F-1 steps 2–5.
F-2 Join as spouse (US-2, AC-2.4, AC-2.10)
- Anna receives Jacob's message, taps the link ⟶ landing page ⟶ "Ladda ner Kvitt" ⟶ installs (Android "Install unknown apps" for her browser, once) ⟶ "Öppna i Kvitt" ⟶
S-1filled. - Anna types her name in "Ditt namn" ("Anna") and taps "Para ihop" ⟶ pairs, creates the member user.
- ⟶
S-2: "Du går med i Jacobs hushåll", her name prefilled, avatar with initials. Anna taps "Lägg till bild" ⟶ photo picker ⟶ picks a photo ⟶ upload with progress. Taps "Fortsätt". - Full sync ⟶
S-4loading ⟶ notification permission prompt ⟶S-4empty "Skapa ert första konto" (or Jacob's accounts, if he created any after she joined). - On Jacob's phone the next sync (or push-triggered sync) removes
S-3.
F-3 Add an expense online (US-3, AC-8.6) — the ten-second flow
- Jacob opens Kvitt ⟶
S-4. - Taps FAB "Lägg till utgift" ⟶
S-7with amount focused, keypad up; defaults: Konto Vardag (last used), Kategori (last used in Vardag, else Övrigt), Datum Idag, Betalt av Du, Delning Kontots standard 50/50. - Types
412. - Taps Beskrivning, types "Systembolaget".
- (optional, one tap each) taps the Kategori chip ⟶ grid ⟶ Nöje; taps Betalt av to switch to Anna; taps Delning to open the split section.
- Taps "Spara" ⟶ saved locally, pending ⟶ back to
S-4, snackbar "Utgiften sparades"; Vardag's wording/amount and the global hero update immediately (AC-10.4). - 2 s later, sync pushes (AC-15.3); the sync line returns to "Synkad nyss"; the server pushes
expense_createdto Anna's phone, which syncs and shows "Jacob lade till en utgift · Systembolaget · 412,00 kr · Vardag".
F-4 Add an expense offline, then sync (US-12, FR-15)
- Jacob is on a plane.
S-4sync line: "Offline · Synkad 14 okt. 08:12". - F-3 steps 2–6 exactly. Snackbar "Sparad. Synkas när du är online." The row in
S-5shows the pending marker;S-4sync line "Offline · 1 ändring väntar på synk". - He adds more and edits one; the count increases ("3 ändringar väntar på synk"). Account, category and recurring actions show "Kräver anslutning".
- Landing: network returns ⟶ sync on foreground or WorkManager ⟶ sync line "Synkar…" ⟶ "Synkad nyss"; pending markers disappear.
- Conflict branch: Anna edited the same expense meanwhile with a later
updated_at⟶ push answersstale⟶ the row shows Anna's version; sync line "Synkad nyss · 1 ändring synkades inte" (warning style) ⟶ tap ⟶S-16"Ändringar som inte synkades": "Babette · Din ändring ersattes av en nyare ändring från Anna" ⟶ tap opens the current expense (read-onlyS-8) ⟶ "Ta bort från listan". - Delete branch: Anna deleted it ⟶ reason
deleted"Den här togs bort innan din ändring kom fram".
F-5 Edit an expense the other person created (AC-8.2, AC-12.4)
- Jacob gets a notification "Anna lade till en utgift · ICA Maxi Lindhagen · 1 147,60 kr · Vardag" ⟶ taps ⟶
S-8(after sync). - Timeline: "Anna skapade den här · 16 okt. 14:02". He sees the receipt says 1 247,60.
- Taps "Ändra" ⟶
S-7"Ändra utgift" with all fields loaded; amount focused. - Changes 1 147,60 to 1 247,60 ⟶ "Spara" ⟶ back to
S-8; timeline gains a last line "Din ändring väntar på synk". - Sync ⟶ the pending line is replaced by "Du ändrade beloppet från 1 147,60 kr till 1 247,60 kr · 16 okt. 19:40".
- Anna's phone gets "Jacob ändrade en utgift · ICA Maxi Lindhagen · 1 247,60 kr"; her
S-8shows the same timeline (her view: "Jacob ändrade beloppet …").
F-6 Global settle-up with adjusted allocation (US-7, AC-11.3, AC-11.5, §9.4)
Start: global "Du är skyldig Anna 3 250,00 kr"; Vardag Anna owes Jacob 1 184,50; Huset Jacob owes 3 084,50; Japan 2027 Jacob owes 1 350,00.
- Jacob taps "Gör upp" on
S-4⟶S-9: "Du betalar Anna", amount 3 250,00 kr (default = global debt), proposal (oldest owing first): Huset 3 084,50, Japan 2027 165,50; "Kvar att fördela 0,00 kr"; info "Vardag påverkas inte: där är Anna skyldig dig 1 184,50 kr." - They agreed to clear Japan first. Jacob edits Japan 2027 to 1 500,00 ⟶ row warning "Det här reglerar mer än som är skyldigt i Japan 2027" (1 500 > 1 350); remaining "−" ⟶ "1 334,50 kr för mycket"; Bekräfta disabled.
- Edits Huset to 1 750,00 ⟶ "Kvar att fördela 0,00 kr"; Bekräfta enabled; Japan warning remains.
- Sets Anteckning "Swish", Datum Idag. Taps "Bekräfta" ⟶ dialog repeating the warning ⟶ "Bekräfta ändå".
- Saved locally ⟶ back to
S-4: global −3 250,00 + 3 250,00 = 0 ⟶ "Ni är kvitt"; per account Huset "Du är skyldig Anna 1 334,50 kr", Japan "Anna är skyldig dig 150,00 kr", Vardag unchanged. (This is §9.4's stated consequence; the per-account settle-ups in F-7 clear the rest.) - Sync; Anna gets "Jacob registrerade en betalning · Jacob betalade dig 3 250,00 kr" (her view).
Variant: "Lägg till konto" ⟶ picker (all non-deleted accounts, archived included) ⟶ adds a row with 0,00 to fill in. Removing a row increases "Kvar att fördela".
F-7 Per-account settle-up (US-8, AC-11.4)
- Jacob on
S-4taps Huset ⟶S-5"Du är skyldig Anna 3 084,50 kr" ⟶ "Gör upp det här kontot". - ⟶
S-9per-account variant: "Du betalar Anna", 3 084,50 kr, one fixed row Huset 3 084,50. No "Lägg till konto". - Optional: changes the amount to 2 000,00 ⟶ the single row follows the amount (it is the only allocation) ⟶ Bekräfta.
- ⟶ back to
S-5: a settlement row "Du betalade Anna 3 084,50 kr" at the top of October; header "Kvitt". - To settle an account where the other user owes (Vardag):
S-5Vardag ⟶ "Gör upp det här kontot" ⟶ direction defaults to "Anna betalar dig" (AC-11.4); Jacob records Anna's Swish.
F-8 Create a recurring expense (US-10, FR-9)
- Jacob ⟶ Inställningar
S-13⟶ "Återkommande utgifter"S-19⟶ "Ny". - Editor: amount 12 400,00; description "Hyra"; Konto Huset; Kategori Hem; Betalt av Anna (one tap); Delning Kontots standard 60/40; Dag i månaden 25; Första månad: defaults to oktober 2026 because the 25th is still ahead (AC-9.8); Sista månad empty.
- Spara (online) ⟶ list row "Hyra · 12 400,00 kr · Huset · Varje månad den 25:e · Nästa: 25 okt.".
- On 25 Oct at 06:00 the server creates the expense ⟶ both phones get "Återkommande utgift tillagd · Hyra · 12 400,00 kr · Huset" (AC-9.6) ⟶
S-8shows "Återkommande: Hyra" and "Skapad automatiskt (återkommande) · 25 okt. 06:00". - Offline at step 3 ⟶ Spara disabled with "Kräver anslutning".
Pause: list row ⟶ editor ⟶ "Pausad" on ⟶ Spara ⟶ row shows "Pausad". Resume does not backfill (§9.5); the editor shows the hint "Månader som passerat under pausen skapas inte i efterhand."
F-9 Archive an account (US-9, AC-6.4)
- Anna on
S-4⟶ Japan 2027 ⟶S-5⟶ overflow ⟶ "Arkivera" (online). - Archived ⟶ back on
S-4, snackbar "Japan 2027 arkiverades" with "Ångra". The account disappears from the active list and appears under "Arkiverade (2)" (collapsed) with its balance still shown; the global balance is unchanged (AC-10.5). - In
S-7the account picker no longer lists it;S-9"Lägg till konto" still does;S-11still counts it. - Unarchive: Home ⟶ "Arkiverade" ⟶ Japan 2027 ⟶
S-5("Arkiverat" badge) ⟶ "Återställ från arkiv". - Delete branch: overflow "Ta bort konto" is disabled with "Kontot kan inte tas bort så länge det har utgifter, betalningar eller återkommande utgifter" unless the account is empty (AC-6.5).
F-10 In-app update (US-14, FR-16)
- Cold start of a release build ⟶
GET /apk/latest⟶ version code higher ⟶S-4banner "Version 1.2 finns" [Uppdatera] [Senare]. - Jacob taps "Uppdatera". First time: dialog "Tillåt installation" explains that Android will ask once ⟶ "Fortsätt" ⟶ system settings "Installera okända appar" for Kvitt ⟶ he allows and taps back.
- Download ⟶ banner "Laddar ner… 64 %" with progress; the app stays usable.
- Size and SHA-256 verified ⟶ the system installer dialog ⟶ "Uppdatera" (system) ⟶ the app restarts on the new version.
- Failure ⟶ banner "Nedladdningen misslyckades. Försök igen." ⟶ "Försök igen" (AC-16.4).
- "Senare" hides the banner until the next cold start. The update is also reachable from
S-22"Sök efter uppdatering".
F-11 Remove a lost phone (US-17, FR-3) — supporting flow
- Jacob (admin) ⟶
S-13⟶ "Enheter"S-20⟶ the lost "Galaxy S26+" row ⟶ "Ta bort" ⟶ confirmation ⟶ revoked. - The lost phone, if it ever connects, gets
device_revoked⟶ wipes local data ⟶S-18"Den här telefonen har tagits bort" ⟶ "Para ihop igen" ⟶S-1.