eutopic/docs/DESIGN.md

192 lines
6.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DESIGN.md — eutopic
what the user experiences and why. not what gets stored (see DATA-MODEL.md). not stack decisions (see CONCEPT.md).
---
## design principles
- users should never be asked to understand anything instagram doesn't ask them to understand.
- friction is a feature when it slows down compulsive checking. friction is a bug when it slows down posting.
- no dark patterns. no engagement optimization. no "one more thing" loops.
- imperfection is intentional. DIY aesthetic over polish-as-performance.
---
## visual identity
**status**: design collab in progress. nothing locked yet.
**direction**:
- wordmark only. no separate logomark — "eutopic" is distinctive enough as a word.
- typographic register: considered, a bit odd, not startup-clean. something with character.
- glyph set for nav icons to be developed as custom symbols, not system unicode or standard icon libraries.
- aesthetic reference: zine, risograph print, hand-stamped, dingbat. not flat SaaS icons.
- tool: figma. brief to follow from design collab.
**nav icon candidates** (to be refined or replaced by collab):
- home: ⒣
- posters: ⇶
- compose: ◲
- stories: ❣
- profile: ☺
these should ship as SVG assets or a custom icon font in the actual app — unicode rendering is inconsistent across android devices and system fonts.
---
## navigation
five-slot bottom tab bar:
```
⒣ home | ⇶ posters | ◲ compose | ❣ stories | ☺ profile
```
- **home** — chronological feed
- **posters** — bulletin board (`/posters`, `is_event` posts + informational posts + fundraisers)
- **compose** — center slot, filled/distinct treatment. opens compose flow (modal or full screen — TBD)
- **stories** — dedicated tab, not a top strip. intentional destination, not ambient anxiety ring.
- **profile** — own profile. viewing others' profiles navigates within the app but doesn't change the active tab.
stories as a bottom tab (vs instagram-style top strip) is a deliberate choice: it frames stories as something you visit, not something that nags you to check.
---
## screens
### onboarding (unauthenticated)
```
invite gate
└── invite code prefilled from deep link, or entered manually
email + username entry
magic link sent / confirm screen
social handle opt-in
└── signal / telegram / custom. skippable. "re-enable anytime in settings."
follow suggestions
└── friends-of-inviter auto-suggested. skippable.
```
zero technology decisions for the user. no server picker. no handle explanation. no fediverse vocabulary.
---
### feed (`/`)
- chronological. no algorithm. no ranked content.
- posts with 110 photos (swipeable within the post card).
- reactions inline below each post.
- comments accessible via tap (flat, chronological thread).
- **survey card** injected at slot 1 when an active survey exists. GIF cover. taps to `/feedback`. disappears per-user once responded. not a real post.
- no unread indicators. no "new posts" banner. pull to refresh is fine.
---
### posters (`/posters`)
formerly "bulletin board". renamed because the scope is broader than events:
**post types** (single tag, required, choose one):
- `event` — dated gathering, auto-archives 1 day after `event_ends_at`
- `fundraiser` — community fundraising
- `current affairs` — informational, reading, things worth knowing
layout: 2-column grid (`SliverGrid` / `GridView.builder`), infinite scroll, paginated fetch.
filtering by tag: TBD (tab strip or dropdown above grid).
reactions on poster posts: visible to post author only. no public counts. no hierarchy.
RSVP interaction model: open question, not designed yet. see OPEN-QUESTIONS.md.
---
### compose (◲)
- triggered from center nav slot.
- photo picker first (up to 10 photos).
- caption optional.
- toggle: post to feed or post to posters. if posters: tag picker (single tag required) + event fields if `event`.
- toggle: saveable on/off (default off).
- toggle: reaction set — choose up to 5 emoji, or leave open (open picker only).
- upload starts in background immediately on confirm. progress shown via hand-drawn animation. bad wifi handled invisibly via tus.io resumable upload.
- no drafts, no scheduling, no queue UI.
---
### stories (❣)
- dedicated tab, not a top strip.
- 10s auto-advance per story.
- filters via swipe gesture (basic, applied at view time or capture time — TBD).
- no replies. "witnessed" metadata only: private per-viewer row, expires with story (24h).
- story author can see flat witness list (like instagram). no public count.
- story creation: camera or photo picker, then post. no drafts.
---
### profile (☺)
**own profile:**
- avatar, display name, username, bio.
- social handles (signal / telegram / custom) — shown based on `display_social_handle` setting: none / mutuals / all.
- `contact_prefs` free text ("bad texter", "weekends only").
- own posts grid.
- settings access.
**others' profiles:**
- same view, minus settings. follow/unfollow action.
- social handles visible per their `display_social_handle` setting.
---
### feedback (`/feedback`)
- always accessible (settings link or survey card tap).
- active survey renders at top if one exists (multiple choice, 36h expiry).
- permanent free text field below, always present regardless of active survey.
- no results shown to users. dev use only.
---
### settings + about
**settings:**
- account (username, display name, avatar, bio)
- social handles (add / hide / remove)
- contact prefs
- `display_social_handle` toggle
**about:**
- "eutopic is a quiet place for friends to share photos."
- "we don't track you. we don't run ads. we don't sell your data."
- "we don't notify you — visit when you want to."
- running costs (hosting, domain, apple developer program) — real numbers, updated manually.
- liberapay donation link (opens in browser).
- credit line: "eutopic uses flutter, an open-source framework made by google. we use their open work to build something they wouldn't."
- "made with care in EU."
no donor badges. no public donor list. donation is private.
---
## animations
- upload progress: hand-drawn, DIY aesthetic. lottie or APNG. not a standard spinner.
- reactions: subtle, not dopamine-optimized. no confetti, no burst animations.
- transitions: simple. no parallax, no over-engineered motion.
- imperfection is okay. "designed" imperfection is part of the identity.
---
## open UX questions
see OPEN-QUESTIONS.md for live status. currently open:
- compose: modal sheet over current screen, or full dedicated screen?
- stories: filters applied at capture or at view time?
- posters: tag filter UI — tab strip or dropdown?
- RSVP interaction model (not designed yet)
- comment hearts/likes — do comments get a reaction? tension with no-hierarchy value.
- stories access: purely via tab, or also accessible from profile (own stories)?