Compare commits
3 commits
9b4b85e188
...
28bd256ac7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28bd256ac7 | ||
|
|
24dd715e9b | ||
|
|
fab7802a3b |
12 changed files with 221 additions and 22 deletions
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
## ai
|
||||||
|
.claude/
|
||||||
|
|
||||||
|
## test output
|
||||||
|
output.md
|
||||||
|
|
||||||
|
## node status
|
||||||
|
nodes.md
|
||||||
|
|
@ -30,10 +30,12 @@ target: 5–50 users at launch, growing by invite only.
|
||||||
- no premium tier. no donor badges. no class hierarchy in the app.
|
- no premium tier. no donor badges. no class hierarchy in the app.
|
||||||
- no manifesto, no political iconography on any user-facing surface.
|
- no manifesto, no political iconography on any user-facing surface.
|
||||||
- `is_event` flag on posts for bulletin board. not a separate entity.
|
- `is_event` flag on posts for bulletin board. not a separate entity.
|
||||||
|
- posters: anyone can post. three post types, single required tag: `event` | `fundraiser` | `current affairs`. auto-archives 1 day after `event_ends_at`. layout: 2-column grid, infinite scroll, paginated fetch.
|
||||||
- reactions: poster defines up to 5 emoji + open picker fallback. stored as user + post + emoji + timestamp.
|
- reactions: poster defines up to 5 emoji + open picker fallback. stored as user + post + emoji + timestamp.
|
||||||
- save/bookmark: optional, toggled by poster at compose. default off.
|
- save/bookmark: optional, toggled by poster at compose. default off.
|
||||||
- story interactions: no replies. "witnessed" metadata only, private, 24h.
|
- story interactions: no replies. "witnessed" metadata only, private, 24h.
|
||||||
- comments: flat, chronological, on posts only.
|
- comments: flat, chronological, on posts only.
|
||||||
|
- surveys: admin-only creation. multiple choice only. 36h expiry. injected as slot-1 feed card (not a real post), drops per-user after response. `/feedback` always has free text field regardless of active survey.
|
||||||
|
|
||||||
**ux**
|
**ux**
|
||||||
- users should never be asked to understand anything instagram doesn't ask them to understand.
|
- users should never be asked to understand anything instagram doesn't ask them to understand.
|
||||||
|
|
@ -50,14 +52,14 @@ target: 5–50 users at launch, growing by invite only.
|
||||||
- **notifications**: off in v1. DM notifications only if DMs land in v2. never for feed activity.
|
- **notifications**: off in v1. DM notifications only if DMs land in v2. never for feed activity.
|
||||||
- **DMs**: deferred to v2. three options on table. not decided.
|
- **DMs**: deferred to v2. three options on table. not decided.
|
||||||
- **federation**: flag off. may flip in v2/v3. UI stays invisible either way.
|
- **federation**: flag off. may flip in v2/v3. UI stays invisible either way.
|
||||||
- **PWA**: deferred. may ship in v1.5.
|
- **PWA**: fallback option to consider if run into problems with apple app store.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## stack (settled)
|
## stack (settled)
|
||||||
|
|
||||||
runtime: bun / framework: elysia / activitypub: fedify / db: sqlite (postgres-ready) /
|
runtime: bun / framework: elysia / activitypub: fedify / db: sqlite (postgres-ready) /
|
||||||
storage: filesystem → s3-compatible / uploads: tus.io / mobile: react native + expo (no EAS) /
|
storage: filesystem → s3-compatible / uploads: tus.io / mobile: flutter + go_router /
|
||||||
hosting: njalla VPS / proxy: nginx / process: systemd / forge: radicle / funding: liberapay
|
hosting: njalla VPS / proxy: nginx / process: systemd / forge: radicle / funding: liberapay
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -76,7 +78,7 @@ hosting: njalla VPS / proxy: nginx / process: systemd / forge: radicle / funding
|
||||||
|
|
||||||
- anti-attention economy: check every feature decision against this.
|
- anti-attention economy: check every feature decision against this.
|
||||||
- "the architecture is the belief" — values show in what's built and refused, not in copy.
|
- "the architecture is the belief" — values show in what's built and refused, not in copy.
|
||||||
- compromises (react native, app stores) are named honestly in the about/credits page.
|
- compromises (flutter/dart, app stores) are named honestly in the about/credits page.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ the immediate goal is to give a specific community a real alternative to instagr
|
||||||
|
|
||||||
- **feed** — chronological, no algorithm, posts with up to 10 photos
|
- **feed** — chronological, no algorithm, posts with up to 10 photos
|
||||||
- **stories** — 10s auto-advance, basic filters via swipe, no replies, 24h expiry
|
- **stories** — 10s auto-advance, basic filters via swipe, no replies, 24h expiry
|
||||||
- **reactions** — a curated set of meaningful reactions (8 max), replacing the generic "like"
|
- **reactions** — poster defines up to 5 emoji as their reaction set, plus open emoji picker fallback. stored as user + post + emoji + timestamp.
|
||||||
- **profiles** — username, display name, avatar, bio
|
- **profiles** — username, display name, avatar, bio
|
||||||
- **invite-only signup** — magic-link email auth, no passwords
|
- **invite-only signup** — magic-link email auth, no passwords
|
||||||
- **community surveys** — adding the possibility of feedback for dev work, unusual for mass social media. shows that we care
|
- **community surveys** — adding the possibility of feedback for dev work, unusual for mass social media. shows that we care
|
||||||
|
|
@ -55,11 +55,11 @@ the immediate goal is to give a specific community a real alternative to instagr
|
||||||
- **process management**: systemd
|
- **process management**: systemd
|
||||||
|
|
||||||
### mobile
|
### mobile
|
||||||
- **framework**: react native + expo (framework only, not EAS)
|
- **framework**: flutter (dart)
|
||||||
- **navigation**: expo router
|
- **navigation**: go_router
|
||||||
- **builds**: local on M3 mac for ios, radicle CI for android
|
- **builds**: local on M3 mac for ios, radicle CI for android. CI/CD on codeberg possibly.
|
||||||
- **upload**: tus client + expo-background-task / URLSession background tasks
|
- **upload**: tus client (tus_client package) + background isolates / WorkManager (android) / URLSession background tasks (ios)
|
||||||
- **animations**: lottie or APNG, hand-drawn DIY
|
- **animations**: lottie (rive or flutter_lottie), hand-drawn DIY
|
||||||
|
|
||||||
### infrastructure
|
### infrastructure
|
||||||
- **hosting**: njalla VPS from day one (skip the laptop-server phase for public use)
|
- **hosting**: njalla VPS from day one (skip the laptop-server phase for public use)
|
||||||
|
|
@ -139,9 +139,9 @@ a single quiet page. no manifesto, no flags. example phrasing:
|
||||||
|
|
||||||
## the subversive stance (internal value, not surface copy)
|
## the subversive stance (internal value, not surface copy)
|
||||||
|
|
||||||
eutopic is built on tools the giants gave away — react native (meta), bun (originally seeded by US capital), the npm registry (microsoft), apple's runtime (apple), even activitypub (a w3c spec adopted by what used to be a small twitter alternative). we are using their open work to build something they wouldn't.
|
eutopic is built on tools the giants gave away — flutter (google), bun (originally seeded by US capital), the npm registry (microsoft), apple's runtime (apple), even activitypub (a w3c spec adopted by what used to be a small twitter alternative). we are using their open work to build something they wouldn't.
|
||||||
|
|
||||||
this isn't compromise, it's strategy. opensourcing tools is the one good thing big tech does. using those tools against the extraction economy they invented is the entire point. linux ran on intel chips and ate intel's lunch in servers. eutopic runs on react native and aims to make meta's social graph products less necessary, one community at a time.
|
this isn't compromise, it's strategy. opensourcing tools is the one good thing big tech does. using those tools against the extraction economy they invented is the entire point. linux ran on intel chips and ate intel's lunch in servers. eutopic runs on flutter and aims to make meta's social graph products less necessary, one community at a time.
|
||||||
|
|
||||||
internal mantras for design and engineering decisions:
|
internal mantras for design and engineering decisions:
|
||||||
- *take their rope, use it to leave*
|
- *take their rope, use it to leave*
|
||||||
|
|
@ -150,7 +150,7 @@ internal mantras for design and engineering decisions:
|
||||||
|
|
||||||
surface-level: a credit line in the about/credits page is enough for nerds who notice:
|
surface-level: a credit line in the about/credits page is enough for nerds who notice:
|
||||||
|
|
||||||
> "eutopic uses react native, an open-source framework made by meta. we use their open work to build something they wouldn't."
|
> "eutopic uses flutter, an open-source framework made by google. we use their open work to build something they wouldn't."
|
||||||
|
|
||||||
everywhere else: this stance is invisible. it's a private joke we share with anyone who asks.
|
everywhere else: this stance is invisible. it's a private joke we share with anyone who asks.
|
||||||
|
|
||||||
|
|
@ -176,10 +176,9 @@ firebase, meta SDKs, google analytics, cloudflare, amazon, github, stripe-as-pri
|
||||||
- **apple developer program** ($99/yr) — required for ios distribution
|
- **apple developer program** ($99/yr) — required for ios distribution
|
||||||
- **apple app store** — gatekeeping, content review power; mitigated by PWA fallback option
|
- **apple app store** — gatekeeping, content review power; mitigated by PWA fallback option
|
||||||
- **google play store** — same gatekeeping; mitigated by F-Droid + sideloaded APK
|
- **google play store** — same gatekeeping; mitigated by F-Droid + sideloaded APK
|
||||||
- **react native** (meta-maintained) — small irony of using meta's framework to flee meta, named honestly
|
- **flutter** (google-maintained) — using google's toolkit, no worse than meta's. dart is a small price for a single codebase that ships real native iOS and android
|
||||||
|
|
||||||
### neutral with caveats
|
### neutral with caveats
|
||||||
- expo (US company, but framework is MIT and works without EAS)
|
|
||||||
- node/npm (microsoft-owned registry but packages themselves are FOSS)
|
- node/npm (microsoft-owned registry but packages themselves are FOSS)
|
||||||
- njalla (values-aligned but small; backup plan = greenhost / 1984 / flokiNET)
|
- njalla (values-aligned but small; backup plan = greenhost / 1984 / flokiNET)
|
||||||
- fedify (small project, low bus factor; AP is a spec so swappable)
|
- fedify (small project, low bus factor; AP is a spec so swappable)
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,8 @@ reaction_set: string[]?; // emoji, max 5. null = open picker only.
|
||||||
event_date: timestamp?; // required if is_event
|
event_date: timestamp?; // required if is_event
|
||||||
event_ends_at: timestamp?; // required if is_event
|
event_ends_at: timestamp?; // required if is_event
|
||||||
event_location: string?;
|
event_location: string?;
|
||||||
event_tags: string[]; // max 2, for bulletin board filters
|
poster_tag: string?; // one of: event | fundraiser | current affairs
|
||||||
|
// constraint: poster_tag required if is_event = true
|
||||||
archived_at: timestamp?; // set by background job 1 day after event_ends_at
|
archived_at: timestamp?; // set by background job 1 day after event_ends_at
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ formerly "bulletin board". renamed because the scope is broader than events:
|
||||||
- `fundraiser` — community fundraising
|
- `fundraiser` — community fundraising
|
||||||
- `current affairs` — informational, reading, things worth knowing
|
- `current affairs` — informational, reading, things worth knowing
|
||||||
|
|
||||||
layout: 2-column grid (`FlatList numColumns={2}`), infinite scroll, paginated fetch.
|
layout: 2-column grid (`SliverGrid` / `GridView.builder`), infinite scroll, paginated fetch.
|
||||||
|
|
||||||
filtering by tag: TBD (tab strip or dropdown above grid).
|
filtering by tag: TBD (tab strip or dropdown above grid).
|
||||||
|
|
||||||
|
|
@ -164,7 +164,7 @@ RSVP interaction model: open question, not designed yet. see OPEN-QUESTIONS.md.
|
||||||
- "we don't notify you — visit when you want to."
|
- "we don't notify you — visit when you want to."
|
||||||
- running costs (hosting, domain, apple developer program) — real numbers, updated manually.
|
- running costs (hosting, domain, apple developer program) — real numbers, updated manually.
|
||||||
- liberapay donation link (opens in browser).
|
- 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."
|
- 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."
|
- "made with care in EU."
|
||||||
|
|
||||||
no donor badges. no public donor list. donation is private.
|
no donor badges. no public donor list. donation is private.
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ priority 0:
|
||||||
- branding + visual identity (design collab pending)
|
- branding + visual identity (design collab pending)
|
||||||
- RSVP interaction model (deferred, not designed yet)
|
- RSVP interaction model (deferred, not designed yet)
|
||||||
- email notification format/timing for RSVPs (deferred)
|
- email notification format/timing for RSVPs (deferred)
|
||||||
- PWA — day one alongside native, or v1.5?
|
|
||||||
- DMs — websockets/simple in-app vs matrix vs no DMs ever. decide before v2 launch.
|
- 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.)
|
- 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.
|
- server/media migration path — which host migration is least painful for media storage (filesystem → s3-compatible). greenhost/hetzner candidates.
|
||||||
|
|
@ -21,6 +20,8 @@ priority 0:
|
||||||
- stories — filters applied at capture time or view time?
|
- stories — filters applied at capture time or view time?
|
||||||
- posters — tag filter UI: tab strip or dropdown?
|
- posters — tag filter UI: tab strip or dropdown?
|
||||||
- stories access — purely via tab, or also accessible from own profile?
|
- stories access — purely via tab, or also accessible from own profile?
|
||||||
|
- CI/CD on codeberg possibly?
|
||||||
|
- feed reaction visibility — should users see all reactions on a post, only their own, or none? (poster-tab reactions already locked: author-only. this is feed-only.)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -40,7 +41,7 @@ priority 0:
|
||||||
- ~~social handle structure~~ → array of `{ platform, handle, label?, active }`. one entry per platform. `label` only used for custom platform. `active` hides without deleting. plus free text `contact_prefs` ("bad texter", "weekends only" etc).
|
- ~~social handle structure~~ → array of `{ platform, handle, label?, active }`. one entry per platform. `label` only used for custom platform. `active` hides without deleting. plus free text `contact_prefs` ("bad texter", "weekends only" etc).
|
||||||
- ~~third-party auth / handle linking~~ → rejected. store strings, display them, done.
|
- ~~third-party auth / handle linking~~ → rejected. store strings, display them, done.
|
||||||
- ~~social handle onboarding~~ → opt-in during onboarding. if skipped: "re-enable at any time in settings."
|
- ~~social handle onboarding~~ → opt-in during onboarding. if skipped: "re-enable at any time in settings."
|
||||||
- ~~bulletin board layout~~ → 2-column grid (`FlatList numColumns={2}`), infinite scroll, paginated fetch.
|
- ~~bulletin board layout~~ → 2-column grid (`SliverGrid` / `GridView.builder`), infinite scroll, paginated fetch.
|
||||||
- ~~survey creator~~ → admin only (you). `is_admin` flag on user record, used only for this.
|
- ~~survey creator~~ → admin only (you). `is_admin` flag on user record, used only for this.
|
||||||
- ~~survey format~~ → multiple choice only. separate `/feedback` subpage always has free text field.
|
- ~~survey format~~ → multiple choice only. separate `/feedback` subpage always has free text field.
|
||||||
- ~~survey visibility~~ → dev use only. no results shown to users, no public engagement metrics.
|
- ~~survey visibility~~ → dev use only. no results shown to users, no public engagement metrics.
|
||||||
|
|
@ -49,4 +50,5 @@ priority 0:
|
||||||
- ~~survey expiry~~ → ephemeral, 36h.
|
- ~~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`.
|
- ~~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.
|
- ~~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.
|
- ~~nav structure~~ → five-slot bottom tab bar: home / posters / compose (center) / stories / profile. stories as dedicated tab, not top strip — intentional destination, not ambient check-in prompt.
|
||||||
|
- ~~PWA~~ — fallback option to consider if run into problems with apple app store
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,12 @@ rough versioned plan. not a project management doc. no dates.
|
||||||
- feed + stories + reactions
|
- feed + stories + reactions
|
||||||
- background + resumable upload via tus.io
|
- background + resumable upload via tus.io
|
||||||
- onboarding via invite link
|
- onboarding via invite link
|
||||||
- bulletin board (`is_event` posts)
|
- posters (`/posters`, `is_event` posts with single required tag: event | fundraiser | current affairs)
|
||||||
- liberapay donation page
|
- liberapay donation page
|
||||||
- njalla deployment with systemd
|
- njalla deployment with systemd
|
||||||
|
|
||||||
## soon (v1.5)
|
## soon (v1.5)
|
||||||
- F-Droid release
|
- F-Droid release
|
||||||
- PWA fallback for iOS users avoiding app store
|
|
||||||
- mobilepay via stripe if community needs it
|
- mobilepay via stripe if community needs it
|
||||||
|
|
||||||
## later (v2 — after v1 stable 3+ months)
|
## later (v2 — after v1 stable 3+ months)
|
||||||
|
|
|
||||||
26
docs/SURVEY-QQS.md
Normal file
26
docs/SURVEY-QQS.md
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
# SURVEY-QQS.md — eutopic
|
||||||
|
|
||||||
|
candidate questions for in-app community surveys. admin-only, multiple choice, 36h expiry.
|
||||||
|
|
||||||
|
format: question + options. one survey live at a time.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## queue
|
||||||
|
|
||||||
|
### 1. feed reaction visibility
|
||||||
|
|
||||||
|
**question:** when you react to a post in your feed, what would feel right?
|
||||||
|
|
||||||
|
**options:**
|
||||||
|
- see everyone's reactions on every post
|
||||||
|
- only see your own reaction on posts you've reacted to
|
||||||
|
- no visible reactions — they're a private signal to the poster
|
||||||
|
|
||||||
|
**why ask:** values tension between social warmth and engagement pressure. community intuition matters more than designer intuition here.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## used
|
||||||
|
|
||||||
|
(none yet)
|
||||||
9
model-tests/01-architectural-risk.md
Normal file
9
model-tests/01-architectural-risk.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
tests: critical reasoning, constraint awareness
|
||||||
|
context: AGENTS.md
|
||||||
|
version: 1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
read @AGENTS.md. you are a senior backend engineer reviewing this project's architectural decisions before the first line of code is written.
|
||||||
|
|
||||||
|
identify up to three decisions that carry the most technical risk or hidden complexity. for each one: name the decision, explain the specific risk, and suggest one mitigation. be direct — this is a pre-build review, not a validation exercise.
|
||||||
133
model-tests/02-flutter-folder-structure.md
Normal file
133
model-tests/02-flutter-folder-structure.md
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
tests: instruction-following, feature-first structure, domain accuracy
|
||||||
|
context: DESIGN.md excerpt (screens + navigation)
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
you are helping design the frontend of eutopic — a photo-first social app for small, invite-only communities. it runs on flutter (dart). it has five main screens: home feed, posters (bulletin board), compose (center tab), stories, and profile. it also has secondary screens for onboarding, settings, and feedback. here's specs:
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## navigation
|
||||||
|
|
||||||
|
five-slot bottom tab bar for screens:
|
||||||
|
|
||||||
|
```
|
||||||
|
⒣ 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.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
eutopic has no notifications, no DMs (chat), and no push alerts. do not include any notification-related files or widgets.
|
||||||
|
|
||||||
|
use feature-first structure. example:
|
||||||
|
lib/features/feed/feed_screen.dart
|
||||||
|
lib/features/feed/widgets/post_card.dart
|
||||||
|
lib/shared/models/user.dart
|
||||||
|
|
||||||
|
draw an ASCII tree diagram of the flutter frontend folder and file structure. include lib/ as the root. show actual filenames (*.dart), not just folder names.
|
||||||
7
model-tests/03-roadmap-scope.md
Normal file
7
model-tests/03-roadmap-scope.md
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
tests: technical judgment, scope reasoning, team-size awareness
|
||||||
|
context: AGENTS.md + ROADMAP.md
|
||||||
|
version: 1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
read @AGENTS.md and @docs/ROADMAP.md. given the stack choices and the team size (1-2 people), does the feature scope for v0 and v1 feel right-sized, or is it too ambitious? focus on scope, not timeline.
|
||||||
13
model-tests/04-elysia-basic-server.md
Normal file
13
model-tests/04-elysia-basic-server.md
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
tests: coding ability, elysia/bun knowledge, route handling
|
||||||
|
context: none
|
||||||
|
version: 1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
write a minimal elysia (bun) http server in a single file. it should have three routes:
|
||||||
|
|
||||||
|
GET /health — returns { status: "ok" }
|
||||||
|
GET /users — returns a hardcoded array of 2-3 user objects with id, name, and email fields
|
||||||
|
POST /users — accepts a JSON body with name and email, logs the received data to console, and returns { received: true }
|
||||||
|
|
||||||
|
no database, no auth, no external dependencies beyond elysia itself. the file should be runnable with `bun run index.ts`.
|
||||||
Loading…
Reference in a new issue