From 0aca8b3ffac469429d0d1e9650ee7962423fe802 Mon Sep 17 00:00:00 2001 From: eutopiacode Date: Sun, 31 May 2026 16:50:49 +0300 Subject: [PATCH] updated open-questions.md and design.md --- README.md | 17 ++++ docs/CONCEPT.md | 27 +----- docs/DESIGN.md | 191 ++++++++++++++++++++++++++++++++++++++++- docs/OPEN-QUESTIONS.md | 13 ++- 4 files changed, 218 insertions(+), 30 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..c2c9e13 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# eutopic + +*a small good place. social media that visits you when you visit it.* + +photo-first social app for small trusted communities. features: +- slide posts (carousel) +- stories +- emoji reactions +- "flyer" event page +chronological feed, no algorithm, no notifications, no tracking. invite-only. + +→ [docs/CONCEPT.md](docs/CONCEPT.md) for full concept, stack, and design decisions. + +--- + +**radicle:** `rad:z3pNdxS2udZaPJjFvAMNA6sxEVvVi` +**web:** https://radicle.network/nodes/iris.radicle.network/rad%3Az3pNdxS2udZaPJjFvAMNA6sxEVvVi diff --git a/docs/CONCEPT.md b/docs/CONCEPT.md index 04ffc2c..10dce6a 100644 --- a/docs/CONCEPT.md +++ b/docs/CONCEPT.md @@ -30,7 +30,7 @@ the immediate goal is to give a specific community a real alternative to instagr - **no DMs** — use signal, element, or another tool. for now, profiles include "message me at [telegram/signal/element/matrix handle]". eutopic stays focused on photo-sharing only. defensible posture — "we do one thing, well." mirrors the no-notifications stance.actual dm impl deferred to v2. - **no analytics or tracking** — none. zero. not even self-hosted. - **no algorithm** — chronological feed, no ranking, no engagement bait. -- **no scheduling, drafts, or queue UI** — bad-wifi handled invisibly via background upload. +- **no scheduling, or queue UI** — bad-wifi handled invisibly via background upload. - **no federation** — initially. the protocol is there but turned off. ## what makes it different @@ -66,25 +66,9 @@ the immediate goal is to give a specific community a real alternative to instagr - **domain**: eutopic.space canonical, eutopic.eu redirect - **code forge**: radicle (p2p, no github) - **CI**: self-hosted radicle CI runner -- **editor**: vscodium (no microsoft telemetry) + - cle primary, github mirror as `eutopiacode`. - **package manager**: bun (no separate npm/yarn) -- **funding**: liberapay primary, ko-fi/open collective backup, mobilepay deferred - -### dev toolchain (the ai-stack + front-desk) -front-desk is a CLI orchestrator that routes coding sessions to models based on **user state**, not task type. 4-choice check-in on session start: - -- **fresh** ── clean slate → gemma-4-E4B-it (local, LM Studio) -- **continuing** ── picking up prior work → gemma-4-E4B-it (local, LM Studio) -- **stuck** ── need help thinking through blockers → claude sonnet (native, subscription) -- **overwhelmed** ── small steps, one at a time → qwen3-4b-instruct-2507-mlx (local, LM Studio) - -cloud stack via opencode for involved work: GLM-4.7 (z.ai, apache 2.0) as conversational daily, DeepSeek V3.2 as cost-efficient workhorse, GLM-4.7-Flash for lightweight tasks. - -escalation: `/escalate` writes `~/.claude/handover.md` and exits; front-desk detects it on next start and execs native claude. - -hardware ceiling: M3 MBP, 18GB unified memory → practical local model ceiling ~10–11GB. - -repo: `/Users/pthfndr/dev/ai-stack`, radicle primary, github mirror as `eutopiacode`. +- **funding**: liberapay primary, ko-fi/open collective backup, mobilepay possible ### shared context for eutopic single `AGENTS.md` at the eutopic repo root, read by all routed models in front-desk. terse and decision-focused — encodes the locked-in choices (no notifications, federation off, invisibly leftist tone, etc.) so any model invoked produces consistent output. @@ -110,11 +94,6 @@ single `AGENTS.md` at the eutopic repo root, read by all routed models in front- - "the slowest part of using social media" disappears - tus protocol is open, multiple implementations -### why njalla day one, not laptop -- laptop-server experience killed pixelfed adoption in this community before -- residential bandwidth + sleep + ISP outages = trust death -- €15-30/mo on njalla covers 20-100 users comfortably -- migration path to bigger hosts exists if needed ## the meta-migration problem (named) diff --git a/docs/DESIGN.md b/docs/DESIGN.md index c83bbb4..14b0947 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -1,5 +1,192 @@ # DESIGN.md — eutopic -*to be drafted. captures interaction model, UI surfaces, and UX decisions.* +what the user experiences and why. not what gets stored (see DATA-MODEL.md). not stack decisions (see CONCEPT.md). -scope: what the user experiences and why. not what gets stored (see DATA-MODEL.md). \ No newline at end of file +--- + +## 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 1–10 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 (`FlatList numColumns={2}`), 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 react native, an open-source framework made by meta. 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)? diff --git a/docs/OPEN-QUESTIONS.md b/docs/OPEN-QUESTIONS.md index 27bfc21..97b1509 100644 --- a/docs/OPEN-QUESTIONS.md +++ b/docs/OPEN-QUESTIONS.md @@ -6,7 +6,7 @@ decision log. open = not yet decided. closed = locked, with resolution noted. ## open -priority 0: +priority 0: - exact reaction palette (design collab pending) - branding + visual identity (design collab pending) - RSVP interaction model (deferred, not designed yet) @@ -15,10 +15,12 @@ priority 0: - DMs — websockets/simple in-app vs matrix vs no DMs ever. decide before v2 launch. - social handle platform list expansion (signal + telegram primaries. custom covers edge cases. expand tbd.) - server/media migration path — which host migration is least painful for media storage (filesystem → s3-compatible). greenhost/hetzner candidates. - - which njalla plan tier? - comment hearts/likes — do comments get a heart reaction? tension with "no hierarchy" value. deferred. -- event tags — max count per event. starting point: 2 (survey community on this). +- compose — modal sheet over current screen, or full dedicated screen? +- stories — filters applied at capture time or view time? +- posters — tag filter UI: tab strip or dropdown? +- stories access — purely via tab, or also accessible from own profile? --- @@ -44,4 +46,7 @@ priority 0: - ~~survey visibility~~ → dev use only. no results shown to users, no public engagement metrics. - ~~survey feature~~ → v1, non-negotiable. community sees product is actively iterated on their feedback. - ~~survey delivery~~ → slot 1 in feed as injected card (not a real post). GIF cover image. tapping routes to `/feedback` where active survey renders above permanent free text field. card drops from slot 1 per-user once they've responded (checks `survey_response` on feed load). no modal. -- ~~survey expiry~~ → ephemeral, 36h. \ No newline at end of file +- ~~survey expiry~~ → ephemeral, 36h. +- ~~bulletin board route + name~~ → `/posters`. scope is broader than events: three post types, single required tag (choose one): `event`, `fundraiser`, `current affairs`. +- ~~event tags — max count~~ → max 1 tag per poster post. single required tag forces a clear primary classification, reduces compose cognitive load. +- ~~nav structure~~ → five-slot bottom tab bar: home / posters / compose (center) / stories / stories / profile. stories as dedicated tab, not top strip — intentional destination, not ambient check-in prompt.