210 lines
11 KiB
Markdown
210 lines
11 KiB
Markdown
|
|
# eutopic — concept doc v0.1
|
|||
|
|
|
|||
|
|
> *a small good place. social media that visits you when you visit it.*
|
|||
|
|
|
|||
|
|
## what it is
|
|||
|
|
|
|||
|
|
eutopic is a federation-capable, photo-first social app for small trusted communities. it's a place to post pictures and short stories for friends and friends-of-friends — explicitly not a global network, not algorithmically driven, and not optimized for attention extraction.
|
|||
|
|
|
|||
|
|
the immediate goal is to give a specific community a real alternative to instagram that doesn't ask them to learn the fediverse, pick a server, or understand what activitypub is. it should feel like opening any other app — but without the cruft, surveillance, and dopamine grift of meta's products.
|
|||
|
|
|
|||
|
|
## who it's for
|
|||
|
|
|
|||
|
|
- a small community currently on instagram, with low-to-medium tech literacy
|
|||
|
|
- 70/30 ios/android split
|
|||
|
|
- mostly EU-based, finnish leaning, mixed language preferences
|
|||
|
|
- 5-50 people at launch, growing organically by invite
|
|||
|
|
|
|||
|
|
## what it does (v1)
|
|||
|
|
|
|||
|
|
- **feed** — chronological, no algorithm, posts with up to 10 photos
|
|||
|
|
- **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"
|
|||
|
|
- **profiles** — username, display name, avatar, bio
|
|||
|
|
- **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
|
|||
|
|
|
|||
|
|
## what it explicitly doesn't do (v1)
|
|||
|
|
|
|||
|
|
- **no push notifications** — eutopic doesn't ping you. you visit when you visit.
|
|||
|
|
- **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 federation** — initially. the protocol is there but turned off.
|
|||
|
|
|
|||
|
|
## what makes it different
|
|||
|
|
|
|||
|
|
1. **no notifications by design** — a deliberate stance, not a missing feature.
|
|||
|
|
2. **DIY animation aesthetic** — hand-drawn upload progress, hand-picked reactions, design imperfection as identity.
|
|||
|
|
3. **transparent costs, donation funded** — single "about" page with real monthly numbers, link to liberapay.
|
|||
|
|
4. **no premium tier, no badges** — donation is private, no class hierarchy in the app.
|
|||
|
|
5. **federation-capable but closed** — built on activitypub via fedify, federation off by default. flag-flippable later without rewrites.
|
|||
|
|
6. **invisibly leftist** — values inform every architectural choice, but never appear on the surface. no manifestos, no political iconography, no "we believe in" claims. people who care about the values recognize them; people who don't just enjoy the product. the architecture is the belief.
|
|||
|
|
|
|||
|
|
## stack
|
|||
|
|
|
|||
|
|
### backend
|
|||
|
|
- **runtime**: bun
|
|||
|
|
- **web framework**: elysia
|
|||
|
|
- **activitypub**: @fedify/fedify + @fedify/elysia
|
|||
|
|
- **database**: sqlite (via bun:sqlite), postgres-ready schema for later migration
|
|||
|
|
- **media storage**: filesystem first, swap to S3-compatible (greenhost/hetzner) later
|
|||
|
|
- **upload protocol**: tus.io (resumable, background-friendly)
|
|||
|
|
- **reverse proxy**: nginx
|
|||
|
|
- **process management**: systemd
|
|||
|
|
|
|||
|
|
### mobile
|
|||
|
|
- **framework**: react native + expo (framework only, not EAS)
|
|||
|
|
- **navigation**: expo router
|
|||
|
|
- **builds**: local on M3 mac for ios, radicle CI for android
|
|||
|
|
- **upload**: tus client + expo-background-task / URLSession background tasks
|
|||
|
|
- **animations**: lottie or APNG, hand-drawn DIY
|
|||
|
|
|
|||
|
|
### infrastructure
|
|||
|
|
- **hosting**: njalla VPS from day one (skip the laptop-server phase for public use)
|
|||
|
|
- **domain**: eutopic.space canonical, eutopic.eu redirect
|
|||
|
|
- **code forge**: radicle (p2p, no github)
|
|||
|
|
- **CI**: self-hosted radicle CI runner
|
|||
|
|
- **editor**: vscodium (no microsoft telemetry)
|
|||
|
|
- **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`.
|
|||
|
|
|
|||
|
|
### 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.
|
|||
|
|
|
|||
|
|
## architecture decisions
|
|||
|
|
|
|||
|
|
### why fedify from day one with federation off
|
|||
|
|
- avoids painful rewrite later if federation becomes desired
|
|||
|
|
- adds upfront cost is minimal (it's a library, not a protocol implementation)
|
|||
|
|
- data model uses URIs from the start, makes future migration trivial
|
|||
|
|
- can be turned on by config flag without breaking clients
|
|||
|
|
|
|||
|
|
### why no notifications in v1
|
|||
|
|
- biggest single technical simplification (no APNs, FCM, UnifiedPush, device tokens)
|
|||
|
|
- aligns with anti-attention-economy values
|
|||
|
|
- ships v1 weeks faster
|
|||
|
|
- ships with a strong differentiator
|
|||
|
|
- can revisit if/when DMs are added in v2
|
|||
|
|
|
|||
|
|
### why background + resumable uploads
|
|||
|
|
- meta's posting feels instant because uploads are invisible
|
|||
|
|
- bad-wifi survival (commutes, trains, rural areas)
|
|||
|
|
- "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)
|
|||
|
|
|
|||
|
|
this community already tried pixelfed and bounced back to instagram. the failure mode wasn't pixelfed's quality — it was the cumulative weight of small decisions: pick a server, understand handles, install a third-party client, deal with federation timeline weirdness. each "wait, what?" is a friction point that compounds.
|
|||
|
|
|
|||
|
|
eutopic's design constraint: **the user should never be asked to understand anything that doesn't have a direct analog in instagram.** no server picker, no handle explanation, no fediverse vocabulary anywhere in the UI. the activitypub layer is invisible.
|
|||
|
|
|
|||
|
|
## onboarding flow (target)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. friend texts you an invite link
|
|||
|
|
2. tap link → app store / play store → install
|
|||
|
|
3. open app, invite code prefilled from deep link
|
|||
|
|
4. enter email + pick username
|
|||
|
|
5. magic link to email → tap → you're in
|
|||
|
|
6. friends-of-the-inviter auto-suggested to follow
|
|||
|
|
7. post your first photo
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
zero decisions about technology. zero "where do you want to live online" questions.
|
|||
|
|
|
|||
|
|
## funding model
|
|||
|
|
|
|||
|
|
a single "about" page (and a settings-page link) with:
|
|||
|
|
|
|||
|
|
- **hosting** ── €X/mo
|
|||
|
|
- **domain** ── €Y/yr
|
|||
|
|
- **apple developer program** ── $99/yr
|
|||
|
|
- **current month** ── covered ✓ / short by €N
|
|||
|
|
- **support eutopic** ── link to liberapay (opens in browser, not in-app purchase)
|
|||
|
|
|
|||
|
|
no donor badges, no public donor list, no "premium tier," no nagging popups. donation is private and doesn't change in-app experience.
|
|||
|
|
|
|||
|
|
## about page tone (target)
|
|||
|
|
|
|||
|
|
a single quiet page. no manifesto, no flags. example phrasing:
|
|||
|
|
|
|||
|
|
- "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 it costs ~€X/month. donations help cover hosting."
|
|||
|
|
- "made with care in EU."
|
|||
|
|
|
|||
|
|
## 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.
|
|||
|
|
|
|||
|
|
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.
|
|||
|
|
|
|||
|
|
internal mantras for design and engineering decisions:
|
|||
|
|
- *take their rope, use it to leave*
|
|||
|
|
- *the tool is not the master*
|
|||
|
|
- *the architecture is the belief*
|
|||
|
|
|
|||
|
|
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."
|
|||
|
|
|
|||
|
|
everywhere else: this stance is invisible. it's a private joke we share with anyone who asks.
|
|||
|
|
|
|||
|
|
## reactions (initial concept)
|
|||
|
|
|
|||
|
|
a curated set of 6-8 reactions, hand-picked or hand-drawn, each meaningful. final set TBD with design collaborators. starting palette:
|
|||
|
|
|
|||
|
|
- ✿ — something beautiful
|
|||
|
|
- ☕ — cozy, comfortable
|
|||
|
|
- ⚡ — electric, exciting
|
|||
|
|
- 🌱 — growth, change
|
|||
|
|
- 🫧 — gentle, soft
|
|||
|
|
- 👁 — i see you, witnessed
|
|||
|
|
|
|||
|
|
posts could be sortable by reaction type (see things people found cozy). reactions could rotate seasonally.
|
|||
|
|
|
|||
|
|
## tech audit (compromises named)
|
|||
|
|
|
|||
|
|
### actively avoided
|
|||
|
|
firebase, meta SDKs, google analytics, cloudflare, amazon, github, stripe-as-primary.
|
|||
|
|
|
|||
|
|
### compromised but unavoidable
|
|||
|
|
- **apple developer program** ($99/yr) — required for ios distribution
|
|||
|
|
- **apple app store** — gatekeeping, content review power; mitigated by PWA fallback option
|
|||
|
|
- **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
|
|||
|
|
|
|||
|
|
### neutral with caveats
|
|||
|
|
- expo (US company, but framework is MIT and works without EAS)
|
|||
|
|
- node/npm (microsoft-owned registry but packages themselves are FOSS)
|
|||
|
|
- njalla (values-aligned but small; backup plan = greenhost / 1984 / flokiNET)
|
|||
|
|
- fedify (small project, low bus factor; AP is a spec so swappable)
|
|||
|
|
|
|||
|
|
### values-aligned
|
|||
|
|
bun, elysia, sqlite, postgres, nginx, debian, systemd, tus, liberapay, radicle, F-Droid.
|