commit a5744ea60dda85e6f5fb61b1b05889b1632d1948 Author: Maxim Kalistratov Date: Thu Feb 12 21:23:44 2026 +0400 Initial commit diff --git a/.markdownlint-cli2.yaml b/.markdownlint-cli2.yaml new file mode 100644 index 0000000..95221ee --- /dev/null +++ b/.markdownlint-cli2.yaml @@ -0,0 +1,2 @@ +config: + line-length: false diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..ac439ff --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,44 @@ +# Morpheus — Project Context + +Privacy-centric social network for Russian-speaking users. Built on Nostr. +Private, not anonymous. NIP-44 E2E encryption for DMs. No ads, ever. + +## Tech Stack + +- **Protocol:** Nostr (NIP-01, NIP-44, NIP-29, NIP-40, NIP-46, NIP-56, NIP-96) +- **Media:** Blossom / NIP-96 +- **Platforms:** Flutter/Dart. Mobile-first (iOS + Android), Web PWA, Desktop +- **Key storage:** Secure Enclave / Keystore, Shamir social recovery, encrypted cloud backup + +## Architecture + +- NIP-44 E2E for all DMs — server never has plaintext +- Public posts are public (by design) +- Metadata visible to relay operators — see [threat model](docs/threat-model-and-workarounds.md) +- No tracking, no ad infra, no behavioral profiling +- Monetization: subscriptions, marketplace, creator tools — see [docs/monetization.md](docs/monetization.md) +- Web of trust relay gating (NIP-02 follow count) — see [docs/web-of-trust.md](docs/web-of-trust.md) + +## Tooling + +- **Linting:** `just lint-md` — runs markdownlint-cli2 +- **Git hooks:** lefthook — see `lefthook.yml` +- **Docs:** EN + RU, keep in sync — see [README.md](README.md) for full table + +## Design system + +See [docs/design-system.md](docs/design-system.md). Key values: + +- Primary: Morpheus Violet `#7C3AED`, dark mode first +- Fonts: Inter (UI), JetBrains Mono (code), Manrope/Unbounded (display) +- 4px spacing grid, `6/10/16/24px` radius scale +- Rounded-square avatars with pubkey-hash gradient fallback + +## Rules + +- No ads logic, tracking pixels, analytics SDKs, or behavioral profiling — ever +- All DM code must use NIP-44 — no plaintext DM paths +- UI copy in both EN and RU +- Prefer simplicity over configurability +- Speed is a feature +- When in doubt, choose the more private option diff --git a/README.md b/README.md new file mode 100644 index 0000000..a4bc862 --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# Morpheus + +Privacy-centric social network for Russian-speaking users, built on the +[Nostr](https://nostr.com/) protocol. + +> "Everyone knows your name. Nobody reads your messages." + +## Sketches + +| Feed | Groups | Chat | +| :---: | :---: | :---: | +| ![Feed](sketches/feed-mockup.png) | ![Groups](sketches/community-mockup.png) | ![Chat](sketches/chat-mockup.png) | + +## Prerequisites + +| Tool | Purpose | Install | +| --- | --- | --- | +| [just](https://github.com/casey/just) | Command runner | `brew install just` / `cargo install just` | +| [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) | Markdown linter | `npm install -g markdownlint-cli2` | +| [lefthook](https://github.com/evilmartians/lefthook) | Git hooks manager | `gem install lefthook` / `brew install lefthook` | + +After cloning, install git hooks: + +```sh +lefthook install +``` + +## Just commands + +[just](https://github.com/casey/just) is a command runner (like `make`, but +simpler). Run `just --list` to see all available recipes. + +```sh +just lint-md # Lint all Markdown files +``` + +## Markdown linting + +All `.md` files are linted with +[markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) to keep +documentation consistent and well-formatted. Configuration lives in +`.markdownlint-cli2.yaml`. + +The lint runs automatically on every commit via lefthook (see `lefthook.yml`). +To run it manually: + +```sh +just lint-md +# or directly: +markdownlint-cli2 "**/*.md" +``` + +## Documentation + +All docs are maintained in English and Russian (keep both in sync). + +| Document | EN | RU | +| --- | --- | --- | +| Philosophy | [docs/philosophy.md](docs/philosophy.md) | [docs/ru/philosophy.md](docs/ru/philosophy.md) | +| Monetization | [docs/monetization.md](docs/monetization.md) | [docs/ru/monetization.md](docs/ru/monetization.md) | +| Design system | [docs/design-system.md](docs/design-system.md) | [docs/ru/design-system.md](docs/ru/design-system.md) | +| Threat model | [docs/threat-model-and-workarounds.md](docs/threat-model-and-workarounds.md) | [docs/ru/threat-model-and-workarounds.md](docs/ru/threat-model-and-workarounds.md) | +| Web of trust | [docs/web-of-trust.md](docs/web-of-trust.md) | [docs/ru/web-of-trust.md](docs/ru/web-of-trust.md) | diff --git a/docs/design-system.md b/docs/design-system.md new file mode 100644 index 0000000..aced4aa --- /dev/null +++ b/docs/design-system.md @@ -0,0 +1,267 @@ +# Morpheus — Design System + +## Design Philosophy + +### Feels alive, never heavy + +Morpheus should feel like the fastest app on your phone. Inspired by the speed of Telegram, +the visual polish of iOS native apps, and the personality of Discord — but with its own +distinct identity. Not corporate. Not underground. Alive. + +## Visual Identity + +### Name & Symbol + +- **Morpheus** — the awakener, the one who offers the choice +- Symbol: an abstracted eye or pill shape — recognition without explanation +- The symbol must work at 16x16 favicon size and on a billboard + +### Color System + +#### Primary Palette + +```plaintext +Morpheus Violet #7C3AED — Primary brand color, CTAs, active states +Electric Indigo #4F46E5 — Secondary, links, interactive elements +``` + +#### Neutral Palette + +```plaintext +Void #09090B — Darkest background (dark mode) +Charcoal #18181B — Card backgrounds (dark mode) +Slate #27272A — Borders, dividers (dark mode) +Mist #A1A1AA — Secondary text +Cloud #F4F4F5 — Card backgrounds (light mode) +Snow #FAFAFA — Lightest background (light mode) +Pure #FFFFFF — Text on dark, cards on light +``` + +#### Accent Palette (Semantic) + +```plaintext +Pulse Green #10B981 — Success, online, sent +Flame Orange #F59E0B — Warning, pending +Signal Red #EF4444 — Error, destructive actions +Ice Blue #06B6D4 — Info, links in context +``` + +#### Gradient + +```plaintext +Morpheus Gradient: #7C3AED → #4F46E5 → #06B6D4 +Usage: onboarding screens, premium badges, hero moments only +Never on body text. Never on backgrounds with text overlay. +``` + +### Dark Mode First + +- Dark mode is the default. Light mode is fully supported but secondary. +- Rationale: target audience prefers dark. Dark mode is easier on OLED batteries. +- Dark backgrounds use the Void/Charcoal scale, never pure #000000 for cards. + +## Typography + +### Font Stack + +```plaintext +Primary: Inter (UI text, body) +Monospace: JetBrains Mono (keys, codes, technical info) +Display: Manrope or Unbounded (headings, marketing, hero text) +``` + +### Type Scale + +```plaintext +Display XL: 36px / 40px line-height — Hero text only +Display: 30px / 36px — Page titles +Heading 1: 24px / 32px — Section headers +Heading 2: 20px / 28px — Card headers +Body: 16px / 24px — Default readable text +Body Small: 14px / 20px — Secondary info, timestamps +Caption: 12px / 16px — Labels, badges, metadata +``` + +### Weight Usage + +```plaintext +Regular (400): Body text, descriptions +Medium (500): UI labels, navigation, buttons +Semibold (600): Headings, emphasis +Bold (700): Display text, hero moments only +``` + +## Spacing & Layout + +### Spacing Scale (4px base) + +```plaintext +xs: 4px — Inline padding, icon gaps +sm: 8px — Tight grouping +md: 12px — Default inner padding +lg: 16px — Card padding, section gaps +xl: 24px — Between sections +2xl: 32px — Page-level spacing +3xl: 48px — Major section breaks +``` + +### Border Radius + +```plaintext +sm: 6px — Buttons, inputs, small cards +md: 10px — Cards, dialogs +lg: 16px — Large cards, modals +xl: 24px — Avatars (rounded square), feature cards +full: 9999px — Pills, tags, circular avatars +``` + +### Grid + +- Mobile-first. Single column default. +- Max content width: 640px for feeds (readability). +- Desktop: centered content column with contextual sidebars. +- No infinite horizontal scrolling. Vertical is native. + +## Components + +### Buttons + +```plaintext +Primary: Morpheus Violet bg, white text, 6px radius, medium weight + Hover: slightly lighter. Active: slightly darker. +Secondary: Transparent bg, violet text, 1px violet border + Hover: violet/10 bg fill +Ghost: Transparent bg, mist text, no border + Hover: slate bg fill +Destructive: Signal Red bg, white text (confirmation required) + +Size: Default 40px height, compact 32px, large 48px + Min touch target: 44x44px always +``` + +### Cards + +```plaintext +Dark mode: Charcoal bg, 1px Slate border, md radius +Light mode: Pure bg, 1px Cloud border, md radius +Elevation: Subtle shadow on hover only (never resting shadow) +Padding: lg (16px) +``` + +### Inputs + +```plaintext +Height: 44px (touch-friendly) +Border: 1px Slate, focus → 2px Morpheus Violet +Background: Void (dark) / Snow (light) +Placeholder: Mist color +Error state: Signal Red border + helper text below +``` + +### Avatars + +```plaintext +Sizes: 24px (inline), 32px (list), 40px (default), 64px (profile), 96px (hero) +Shape: Rounded square (xl radius) — distinguishes from other platforms +Fallback: Generated gradient from public key hash (every user gets a unique one) +Online dot: Pulse Green, bottom-right, 25% of avatar size +``` + +### Navigation + +```plaintext +Mobile: Bottom tab bar, 5 items max. Haptic feedback on tap. + Active tab: Morpheus Violet icon + label + Inactive: Mist icon, no label +Desktop: Left sidebar, collapsible. Icons + labels. +Transitions: Horizontal slide between tabs, vertical within feeds +``` + +## Motion & Animation + +### Principles + +- **Purposeful**: every animation communicates something (state change, spatial relationship) +- **Fast**: default duration 150-200ms. Never exceed 300ms for UI transitions. +- **Interruptible**: user input cancels any running animation immediately +- **No decorative animation**: no floating particles, no pulsing logos, no ambient motion + +### Standard Easings + +```plaintext +ease-out: cubic-bezier(0.0, 0.0, 0.2, 1) — Elements entering +ease-in: cubic-bezier(0.4, 0.0, 1, 1) — Elements exiting +ease-in-out: cubic-bezier(0.4, 0.0, 0.2, 1) — Elements transforming +spring: spring(1, 80, 10) — Playful interactions (reactions, likes) +``` + +### Key Animations + +```plaintext +Page transition: Horizontal slide, 200ms ease-out +Modal: Scale from 0.95 + fade, 150ms ease-out +Toast/snackbar: Slide up from bottom, 200ms ease-out, auto-dismiss 3s +Pull to refresh: Native feel, custom indicator with Morpheus symbol +Message send: Slide up + slight scale, spring easing +Reaction: Pop + particle burst, spring easing (one of few "fun" moments) +Skeleton loading: Shimmer gradient, 1.5s loop (only when truly loading) +``` + +## Iconography + +### Style + +- Outlined style (not filled) for navigation and UI — 1.5px stroke +- Filled style for active/selected states +- 24x24 base size, optically adjusted per icon +- Consistent metaphors: no mixing material/feather/custom within a view + +### Custom Icons Needed + +- Relay status indicator +- Key/identity icon (not a literal key — too crypto-bro) +- Encryption indicator (subtle, not a padlock — normalization, not alarm) +- Morpheus-specific actions (e.g., "zap" for tips if using Lightning) + +## Tone of Voice (UI Copy) + +### Localization Principles + +- **Casual but not childish** — "Hey" not "Greetings, dear user" +- **Direct** — "Send" not "Submit your message" +- **Confident** — "Your messages are encrypted" not "We try to protect..." +- **Bilingual-ready** — UI must work in Russian and English from day one +- **No corporate speak** — "Something went wrong" not "An unexpected error occurred" + +### Examples + +```plaintext +Empty state: "Nobody here yet. Be the first." (not "No content available") +Error: "Couldn't connect. Tap to retry." (not "Network error 503") +Onboarding: "This key is you. Save it somewhere safe." (not "Back up your keypair") +Destructive: "Delete this forever?" (not "Are you sure you want to delete?") +``` + +## Accessibility + +- Minimum contrast ratio: 4.5:1 for body text, 3:1 for large text +- All interactive elements: 44x44px minimum touch target +- Screen reader labels for all icons and non-text elements +- Reduce Motion support: disable all non-essential animation +- Font scaling: support system font size preferences (up to 200%) +- No information conveyed by color alone (always pair with icon or text) + +## Platform Targets + +### Priority Order + +1. **Mobile (iOS + Android)** — React Native or Flutter, native feel mandatory +2. **Web (PWA)** — Full feature parity, installable +3. **Desktop** — Electron or Tauri wrapper of web, or native if resources allow + +### Platform Adaptation + +- Follow platform conventions for navigation patterns (iOS back swipe, Android back button) +- Native share sheets, notifications, haptics +- Respect system dark/light mode by default, allow manual override +- Adaptive layouts: phone → tablet → desktop, not just scaled up diff --git a/docs/monetization.md b/docs/monetization.md new file mode 100644 index 0000000..795f2c7 --- /dev/null +++ b/docs/monetization.md @@ -0,0 +1,104 @@ +# Morpheus — Monetization Strategy + +## Constraint + +The business model must satisfy all of the following: + +1. **No ads** — ever. Not behavioral, not contextual, not "privacy-respecting." Zero ads. +2. **No data selling** — ever +3. **Accessible to teenagers** — most users won't have credit cards +4. **Sustainable** — must cover infrastructure (relay hosting, CDN, development) +5. **Aligned with privacy** — revenue and user interests must never conflict +6. **Compliant** — payment processing and business operations follow applicable law + +## Revenue Streams + +### Tier 1: Core Revenue (Day 1) + +#### 1.1 Morpheus Pro (Subscription) + +Monthly subscription unlocking premium features: + +- Custom themes and advanced profile styling +- Higher media upload limits (video length, image quality) +- Priority relay access (faster message delivery) +- Exclusive sticker packs and reactions +- Profile badges and visual flair +- Early access to new features + +**Pricing strategy:** + +- Aggressive teen-friendly pricing (~149-299 RUB/month) +- Payment via Russian methods: SBP, Mir cards, mobile carrier billing +- Mobile carrier billing is critical — teens can pay via phone balance +- Gift codes purchasable at retail (similar to game cards) +- "Gift Pro to a friend" as social mechanic + +**Why it works:** Teens already pay for Discord Nitro, Telegram Premium, game passes. +Status symbols and customization are proven monetization for this demographic. + +#### 1.2 Sticker & Theme Marketplace + +- Creators design and sell sticker packs, themes, and profile decorations +- Morpheus takes a 15-20% commission +- Creators earn real money, incentivizing high-quality content +- Free base packs ensure non-paying users aren't excluded + +### Tier 2: Growth Revenue (Month 3-6) + +#### 2.1 Creator Tools (Paid) + +For users with audiences (bloggers, musicians, artists): + +- Analytics dashboard (aggregate, non-identifying) +- Paid subscriptions to creator channels (Morpheus takes 10-15%) +- Tipping via integrated payment (Lightning Network or traditional) +- Exclusive content gates + +#### 2.2 Business Profiles + +- Verified business accounts with enhanced features +- Customer communication tools +- No ad targeting — businesses post to their followers organically +- Flat monthly fee, no per-impression charges + +### Tier 3: Ecosystem Revenue (Month 6-12) + +#### 3.1 Morpheus Relay Hosting + +- Managed relay infrastructure for communities and organizations +- "Your community, your relay, our infrastructure" +- Tiered pricing based on storage and throughput + +#### 3.2 API Access + +- Rate-limited free tier for hobbyist developers +- Paid tiers for bots, integrations, and third-party apps +- Fosters ecosystem without subsidizing it indefinitely + +## Anti-Patterns (What We Will NOT Do) + +| Anti-pattern | Why not | +| --- | --- | +| Any form of advertising | Core principle — no ads, ever | +| Data licensing / selling | Violates privacy promise | +| Freemium with crippled free tier | Alienates core teen audience | +| Token / cryptocurrency speculation | Distracts from product, attracts wrong crowd | +| Venture-funded growth-at-all-costs | Misaligned incentives, leads to enshittification | +| Paywalled basic messaging | Communication is a right, not a premium feature | + +## Financial Sustainability Model + +**Phase 1 (0-6 months):** Seed funding or grants (open-source / digital rights foundations). +Lean team. Run community relays at cost. + +**Phase 2 (6-18 months):** Pro subscriptions + marketplace commissions cover server costs. +Target: 3-5% conversion to Pro among active users. + +**Phase 3 (18+ months):** Creator economy + business profiles generate margin. +Relay hosting becomes profit center. Sustainable without external funding. + +## Key Metric + +**Revenue per user must never require knowing who the user is.** +All monetization is opt-in, explicit, and identity-independent. diff --git a/docs/philosophy.md b/docs/philosophy.md new file mode 100644 index 0000000..28434db --- /dev/null +++ b/docs/philosophy.md @@ -0,0 +1,131 @@ +# Morpheus — Philosophy + +> "Everyone knows your name. Nobody reads your messages." + +## The Core Distinction + +**Morpheus is private, not anonymous.** + +You have a real identity on Morpheus — a profile, a reputation, followers, a history. +People know you. That's the point of a social network. + +But your direct messages are encrypted end-to-end with NIP-44. Not because we choose +not to read them — because we architecturally *cannot*. The encryption happens on your +device, between you and the recipient. We never hold the keys. + +This is not a political statement. It's an engineering decision. + +| What we CAN provide if legally required | What we CANNOT provide, ever | +| --- | --- | +| Public posts (they're public by design) | Content of encrypted DMs | +| Account metadata (creation date, public key) | Private encryption keys | +| Relay connection logs (IP, timestamp) | Decrypted message content | +| Public social graph (who follows whom publicly) | Messages that were never stored on our relays | + +We comply with the law. We also build systems where the most sensitive data +simply does not exist in a form we can access. These two things are not in conflict. + +## Why Morpheus Exists + +Social networks in Russia are under pressure. Services get blocked, APIs get restricted, +content gets moderated by external mandate. Young people deserve a social space that is: + +1. **Fast** — because they're used to the best apps in the world +2. **Beautiful** — because aesthetics matter to this generation +3. **Honest about privacy** — not "trust us" but "verify: here's the code" +4. **Resilient** — if something changes politically, your messages are still yours + +## Design Principles + +### 1. Speed is respect + +Every millisecond of loading time says "we don't value your time." +Morpheus must feel instant — faster than Telegram, smoother than Instagram. +60fps or nothing. If the user can perceive a delay, it's a bug. + +### 2. Privacy through architecture, not policy + +Don't say "we won't read your messages." Say "we can't." +NIP-44 encryption means DM content is ciphertext on our relays. +We don't make a privacy promise — we make a mathematical guarantee. +Public posts are public. Private messages are private. No ambiguity. + +### 3. Not anonymous, not surveilled — just private + +Users have identities. They build reputations. They're accountable for public behavior. +But their private conversations are theirs. This is the same expectation people have +with postal mail, phone calls, and in-person conversations. +Morpheus simply extends this expectation to digital communication. + +### 4. Simplicity is power + +Every feature must justify its existence. If a teenager can't figure it out +in 3 seconds, it's too complex. No settings pages. No toggles. +The app should feel like it reads your mind, not like it needs a manual. + +### 5. We are a business, not a movement + +Morpheus is a company that makes a product. We charge for premium features. +We are not funded by ads, not funded by data sales, not funded by ideology. +Our incentive is simple: make a product so good that people pay for it. +When incentives are clear, trust follows. + +### 6. Compliant and principled + +We operate within the law. We register where required. We respond to lawful requests. +AND we build systems where encrypted content cannot be decrypted by us. +These are not contradictions — this is responsible engineering. +We will never install backdoors, key escrow, or ghost protocols. +If we cannot technically comply with a specific request, we say so transparently. + +### 7. Open by default + +The client is open source. The protocol (Nostr) is open. +Users can verify every privacy claim by reading the code. +If you don't trust us, don't take our word — audit us. + +## What Morpheus Is + +- A fast, beautiful social network for young Russian-speaking people +- Built on Nostr protocol for real encryption and portability +- A business that makes money from premium features, not from users' data +- Compliant with applicable law while protecting what encryption protects +- An app your friend tells you about because it's good, not because it's political + +## What Morpheus Is NOT + +- **Not anonymous** — you have a real, persistent identity +- **Not a protest tool** — it's for memes, group chats, dating, music, friends +- **Not a crypto/Web3 project** — Nostr uses keys, but there are no tokens or blockchain +- **Not anti-government** — we comply with law; we also use strong encryption +- **Not a dark web app** — the aesthetic is bright, modern, and mainstream + +## The Privacy Spectrum + +```plaintext +Fully surveilled Morpheus position Fully anonymous +|__________________________|___________________________| +VK, OK "Private, not anonymous" Tor, I2P + - Real identities + - E2E encrypted DMs + - Public posts are public + - Compliant operations + - No backdoors +``` + +Morpheus occupies the practical middle ground: the same privacy you'd expect in real life, +applied to digital communication. Nothing more extreme. Nothing less. + +## The Morpheus Promise + +We will: + +- Encrypt all DMs with NIP-44 — always, by default, no opt-in needed +- Publish our source code +- Comply with lawful requests using data we actually have +- Be transparent about what data exists and what doesn't +- Never add backdoors or weaken encryption +- Never sell user data or run behavioral advertising +- Build a sustainable business on premium features + +We will be honest when we cannot do something, rather than pretend we can. diff --git a/docs/ru/design-system.md b/docs/ru/design-system.md new file mode 100644 index 0000000..09c07ad --- /dev/null +++ b/docs/ru/design-system.md @@ -0,0 +1,267 @@ +# Morpheus — Дизайн-система + +## Философия дизайна + +### «Ощущается живым, никогда — тяжёлым.» + +Morpheus должен ощущаться как самое быстрое приложение на телефоне. Вдохновлено скоростью Telegram, +визуальной отполированностью нативных приложений iOS и характером Discord — но с собственной +идентичностью. Не корпоративный. Не андеграунд. Живой. + +## Визуальная идентичность + +### Название и символ + +- **Morpheus** — пробуждающий, тот кто предлагает выбор +- Символ: абстрактный глаз или форма пилюли — узнаваемость без объяснений +- Символ должен работать в размере 16x16 фавикон и на билборде + +### Цветовая система + +#### Основная палитра + +```plaintext +Morpheus Violet #7C3AED — Основной цвет бренда, CTA, активные состояния +Electric Indigo #4F46E5 — Вторичный, ссылки, интерактивные элементы +``` + +#### Нейтральная палитра + +```plaintext +Void #09090B — Самый тёмный фон (тёмная тема) +Charcoal #18181B — Фон карточек (тёмная тема) +Slate #27272A — Границы, разделители (тёмная тема) +Mist #A1A1AA — Вторичный текст +Cloud #F4F4F5 — Фон карточек (светлая тема) +Snow #FAFAFA — Самый светлый фон (светлая тема) +Pure #FFFFFF — Текст на тёмном, карточки на светлом +``` + +#### Акцентная палитра (семантическая) + +```plaintext +Pulse Green #10B981 — Успех, онлайн, отправлено +Flame Orange #F59E0B — Предупреждение, ожидание +Signal Red #EF4444 — Ошибка, деструктивные действия +Ice Blue #06B6D4 — Информация, ссылки в контексте +``` + +#### Градиент + +```plaintext +Градиент Morpheus: #7C3AED → #4F46E5 → #06B6D4 +Применение: экраны онбординга, премиум-бейджи, только «героические» моменты +Никогда на тексте body. Никогда на фонах с текстом поверх. +``` + +### Тёмная тема — по умолчанию + +- Тёмная тема по умолчанию. Светлая полностью поддерживается, но вторична. +- Обоснование: целевая аудитория предпочитает тёмную. Тёмная тема экономит батарею OLED. +- Тёмные фоны используют шкалу Void/Charcoal, никогда чистый #000000 для карточек. + +## Типографика + +### Набор шрифтов + +```plaintext +Основной: Inter (текст интерфейса, body) +Моноширинный: JetBrains Mono (ключи, коды, техническая информация) +Дисплейный: Manrope или Unbounded (заголовки, маркетинг, hero-текст) +``` + +### Шкала типографики + +```plaintext +Display XL: 36px / 40px межстрочный — Только hero-текст +Display: 30px / 36px — Заголовки страниц +Heading 1: 24px / 32px — Заголовки секций +Heading 2: 20px / 28px — Заголовки карточек +Body: 16px / 24px — Стандартный читаемый текст +Body Small: 14px / 20px — Вторичная информация, время +Caption: 12px / 16px — Лейблы, бейджи, метаданные +``` + +### Использование жирности + +```text +Regular (400): Текст body, описания +Medium (500): Лейблы UI, навигация, кнопки +Semibold (600): Заголовки, акценты +Bold (700): Дисплейный текст, только hero-моменты +``` + +## Отступы и сетка + +### Шкала отступов (база 4px) + +```text +xs: 4px — Внутренние отступы inline, зазоры иконок +sm: 8px — Тесная группировка +md: 12px — Стандартный внутренний отступ +lg: 16px — Отступ карточек, зазоры секций +xl: 24px — Между секциями +2xl: 32px — Отступы на уровне страницы +3xl: 48px — Крупные разрывы секций +``` + +### Радиусы скругления + +```text +sm: 6px — Кнопки, инпуты, мелкие карточки +md: 10px — Карточки, диалоги +lg: 16px — Крупные карточки, модалы +xl: 24px — Аватары (скруглённый квадрат), карточки фич +full: 9999px — Пиллы, теги, круглые аватары +``` + +### Сетка + +- Mobile-first. Одна колонка по умолчанию. +- Максимальная ширина контента: 640px для лент (читаемость). +- Десктоп: центрированная колонка контента с контекстными сайдбарами. +- Никакого бесконечного горизонтального скролла. Вертикальный — нативный. + +## Компоненты + +### Кнопки + +```text +Primary: Morpheus Violet фон, белый текст, радиус 6px, medium вес + Hover: слегка светлее. Active: слегка темнее. +Secondary: Прозрачный фон, фиолетовый текст, граница 1px фиолетовая + Hover: заливка violet/10 +Ghost: Прозрачный фон, mist текст, без границы + Hover: заливка slate +Destructive: Signal Red фон, белый текст (требуется подтверждение) + +Размер: По умолчанию 40px высота, компактный 32px, большой 48px + Минимальная зона касания: всегда 44x44px +``` + +### Карточки + +```text +Тёмная тема: Charcoal фон, граница 1px Slate, радиус md +Светлая тема: Pure фон, граница 1px Cloud, радиус md +Возвышение: Тень только при hover (никогда в покое) +Отступ: lg (16px) +``` + +### Поля ввода + +```text +Высота: 44px (удобно для касания) +Граница: 1px Slate, фокус → 2px Morpheus Violet +Фон: Void (тёмная) / Snow (светлая) +Placeholder: цвет Mist +Ошибка: граница Signal Red + текст подсказки ниже +``` + +### Аватары + +```text +Размеры: 24px (inline), 32px (список), 40px (по умолчанию), 64px (профиль), 96px (hero) +Форма: Скруглённый квадрат (радиус xl) — отличает от других платформ +Фолбэк: Генерируемый градиент из хеша публичного ключа (каждый пользователь уникален) +Точка онлайн: Pulse Green, справа внизу, 25% от размера аватара +``` + +### Навигация + +```text +Мобильная: Нижняя панель вкладок, максимум 5 элементов. Хаптик при касании. + Активная вкладка: иконка Morpheus Violet + лейбл + Неактивная: иконка Mist, без лейбла +Десктоп: Левый сайдбар, сворачиваемый. Иконки + лейблы. +Переходы: Горизонтальный слайд между вкладками, вертикальный внутри лент +``` + +## Анимация и движение + +### Принципы + +- **Целенаправленная**: каждая анимация что-то сообщает (смена состояния, пространственная связь) +- **Быстрая**: стандартная длительность 150-200мс. Никогда не превышать 300мс для переходов UI. +- **Прерываемая**: ввод пользователя немедленно отменяет любую текущую анимацию +- **Никакой декоративной анимации**: без плавающих частиц, пульсирующих логотипов, фоновых эффектов + +### Стандартные кривые + +```text +ease-out: cubic-bezier(0.0, 0.0, 0.2, 1) — Элементы входят +ease-in: cubic-bezier(0.4, 0.0, 1, 1) — Элементы выходят +ease-in-out: cubic-bezier(0.4, 0.0, 0.2, 1) — Элементы трансформируются +spring: spring(1, 80, 10) — Игривые взаимодействия (реакции, лайки) +``` + +### Ключевые анимации + +```text +Переход страницы: Горизонтальный слайд, 200мс ease-out +Модал: Scale от 0.95 + fade, 150мс ease-out +Тост/снэкбар: Слайд снизу вверх, 200мс ease-out, автоисчезновение 3с +Pull to refresh: Нативное ощущение, кастомный индикатор с символом Morpheus +Отправка сообщения: Слайд вверх + лёгкий scale, spring easing +Реакция: Pop + взрыв частиц, spring easing (один из немногих «весёлых» моментов) +Скелетон загрузки: Шиммер-градиент, цикл 1.5с (только при реальной загрузке) +``` + +## Иконографика + +### Стиль + +- Outlined стиль (не filled) для навигации и UI — обводка 1.5px +- Filled стиль для активных/выбранных состояний +- Базовый размер 24x24, оптически скорректирован для каждой иконки +- Единообразные метафоры: не смешивать material/feather/custom в одном виде + +### Нужны кастомные иконки + +- Индикатор статуса реле +- Иконка ключа/идентичности (не буквальный ключ — слишком крипто-бро) +- Индикатор шифрования (тонкий, не замок — нормализация, не тревога) +- Morpheus-специфичные действия (напр. «zap» для чаевых при использовании Lightning) + +## Тон голоса (UI-тексты) + +### Принципы тона + +- **Разговорный, но не детский** — «Привет», не «Приветствуем вас, уважаемый пользователь» +- **Прямой** — «Отправить», не «Подтвердить отправку сообщения» +- **Уверенный** — «Ваши сообщения зашифрованы», не «Мы стараемся защитить...» +- **Двуязычный** — UI должен работать на русском и английском с первого дня +- **Без корпоративного языка** — «Что-то пошло не так», не «Произошла непредвиденная ошибка» + +### Примеры + +```text +Пустое состояние: «Тут пока никого. Будь первым.» (не «Контент отсутствует») +Ошибка: «Не удалось подключиться. Нажми, чтобы повторить.» (не «Ошибка сети 503») +Онбординг: «Этот ключ — это ты. Сохрани его в надёжном месте.» (не «Создайте резервную копию ключевой пары») +Деструктивное: «Удалить навсегда?» (не «Вы уверены, что хотите удалить?») +``` + +## Доступность + +- Минимальный коэффициент контрастности: 4.5:1 для текста body, 3:1 для крупного текста +- Все интерактивные элементы: минимальная зона касания 44x44px +- Метки screen reader для всех иконок и нетекстовых элементов +- Поддержка Reduce Motion: отключение всей необязательной анимации +- Масштабирование шрифта: поддержка системных настроек размера шрифта (до 200%) +- Информация не передаётся только цветом (всегда дублировать иконкой или текстом) + +## Целевые платформы + +### Приоритет + +1. **Мобильные (iOS + Android)** — React Native или Flutter, нативное ощущение обязательно +2. **Веб (PWA)** — Полный паритет функций, устанавливаемый +3. **Десктоп** — Electron или Tauri обёртка веба, или нативный при наличии ресурсов + +### Адаптация к платформам + +- Следовать соглашениям платформы для паттернов навигации (iOS свайп назад, Android кнопка назад) +- Нативные share sheets, уведомления, хаптик +- Уважать системную тёмную/светлую тему по умолчанию, разрешить ручное переключение +- Адаптивные лейауты: телефон → планшет → десктоп, не просто масштабированные diff --git a/docs/ru/monetization.md b/docs/ru/monetization.md new file mode 100644 index 0000000..5e489e9 --- /dev/null +++ b/docs/ru/monetization.md @@ -0,0 +1,104 @@ +# Morpheus — Стратегия монетизации + +## Ограничения + +Бизнес-модель должна удовлетворять всем следующим условиям: + +1. **Никакой рекламы** — никогда. Ни поведенческой, ни контекстной, ни «уважающей приватность». Ноль рекламы. +2. **Никакой продажи данных** — никогда +3. **Доступно для молодёжи** — у большинства пользователей нет банковских карт +4. **Устойчиво** — должно покрывать инфраструктуру (хостинг реле, CDN, разработка) +5. **Согласовано с приватностью** — доход и интересы пользователей никогда не должны конфликтовать +6. **Законопослушно** — обработка платежей и бизнес-операции соответствуют применимому праву + +## Потоки дохода + +### Уровень 1: Основной доход (с первого дня) + +#### 1.1 Morpheus Pro (Подписка) + +Ежемесячная подписка, открывающая премиум-функции: + +- Кастомные темы и продвинутая стилизация профиля +- Увеличенные лимиты загрузки медиа (длина видео, качество изображений) +- Приоритетный доступ к реле (быстрая доставка сообщений) +- Эксклюзивные стикерпаки и реакции +- Бейджи профиля и визуальные украшения +- Ранний доступ к новым функциям + +**Стратегия ценообразования:** + +- Доступные цены (~149-299 руб/мес) +- Оплата российскими методами: СБП, карты Мир, оплата с баланса мобильного +- Оплата с мобильного критически важна — молодёжь может платить с баланса телефона +- Подарочные коды, покупаемые в рознице (как карты для игр) +- «Подарить Pro другу» как социальная механика + +**Почему работает:** Молодёжь уже платит за Discord Nitro, Telegram Premium, игровые пропуски. +Статусные символы и кастомизация — проверенная монетизация для этой аудитории. + +#### 1.2 Маркетплейс стикеров и тем + +- Создатели дизайнят и продают стикерпаки, темы и декорации профилей +- Morpheus берёт комиссию 15-20% +- Создатели зарабатывают реальные деньги, что стимулирует качественный контент +- Бесплатные базовые паки гарантируют, что неплатящие пользователи не исключены + +### Уровень 2: Доход роста (месяцы 3-6) + +#### 2.1 Инструменты для создателей (платные) + +Для пользователей с аудиторией (блогеры, музыканты, художники): + +- Дашборд аналитики (агрегированная, неидентифицирующая) +- Платные подписки на каналы создателей (Morpheus берёт 10-15%) +- Чаевые через интегрированную оплату (Lightning Network или традиционная) +- Закрытый контент для подписчиков + +#### 2.2 Бизнес-профили + +- Верифицированные бизнес-аккаунты с расширенными возможностями +- Инструменты коммуникации с клиентами +- Никакого рекламного таргетинга — бизнесы постят для своих подписчиков органически +- Фиксированная месячная плата, никаких плат за показы + +### Уровень 3: Доход экосистемы (месяцы 6-12) + +#### 3.1 Хостинг реле Morpheus + +- Управляемая инфраструктура реле для сообществ и организаций +- «Ваше сообщество, ваш реле, наша инфраструктура» +- Тарификация по хранилищу и пропускной способности + +#### 3.2 Доступ к API + +- Бесплатный уровень с ограничениями для разработчиков-любителей +- Платные уровни для ботов, интеграций и сторонних приложений +- Развивает экосистему, не субсидируя её бесконечно + +## Антипаттерны (чего мы НЕ будем делать) + +| Антипаттерн | Почему нет | +| --- | --- | +| Любая форма рекламы | Основной принцип — никакой рекламы, никогда | +| Лицензирование / продажа данных | Нарушает обещание приватности | +| Freemium с изуродованным бесплатным уровнем | Отталкивает основную аудиторию | +| Токены / криптовалютные спекуляции | Отвлекает от продукта, привлекает не тех | +| Рост любой ценой на венчурные деньги | Неверные стимулы, ведёт к деградации продукта | +| Платные базовые сообщения | Общение — право, а не премиум-функция | + +## Модель финансовой устойчивости + +**Фаза 1 (0-6 месяцев):** Начальное финансирование или гранты. +Компактная команда. Запуск реле по себестоимости. + +**Фаза 2 (6-18 месяцев):** Pro-подписки + комиссии маркетплейса покрывают серверные расходы. +Цель: конверсия 3-5% в Pro среди активных пользователей. + +**Фаза 3 (18+ месяцев):** Экономика создателей + бизнес-профили генерируют маржу. +Хостинг реле становится центром прибыли. Устойчивость без внешнего финансирования. + +## Ключевая метрика + +**Доход с пользователя никогда не должен требовать знания, кто этот пользователь.** +Вся монетизация добровольная, явная и не зависящая от личности. diff --git a/docs/ru/philosophy.md b/docs/ru/philosophy.md new file mode 100644 index 0000000..89d9aed --- /dev/null +++ b/docs/ru/philosophy.md @@ -0,0 +1,131 @@ +# Morpheus — Философия + +> «Все знают твоё имя. Никто не читает твои сообщения.» + +## Главное различие + +**Morpheus — приватный, не анонимный.** + +У тебя есть реальная личность в Morpheus — профиль, репутация, подписчики, история. +Люди тебя знают. В этом суть социальной сети. + +Но твои личные сообщения зашифрованы сквозным шифрованием NIP-44. Не потому что мы +решили их не читать — а потому что мы архитектурно *не можем*. Шифрование происходит +на твоём устройстве, между тобой и получателем. У нас никогда нет ключей. + +Это не политическое заявление. Это инженерное решение. + +| Что мы МОЖЕМ предоставить по закону | Чего мы НЕ МОЖЕМ предоставить, никогда | +| --- | --- | +| Публичные посты (они публичные по замыслу) | Содержание зашифрованных ЛС | +| Метаданные аккаунта (дата создания, публичный ключ) | Приватные ключи шифрования | +| Логи подключений к реле (IP, время) | Расшифрованные сообщения | +| Публичный социальный граф (кто на кого подписан) | Сообщения, не хранившиеся на наших реле | + +Мы соблюдаем закон. Мы также строим системы, в которых самые чувствительные данные +просто не существуют в доступной нам форме. Эти два утверждения не противоречат друг другу. + +## Зачем Morpheus существует + +Социальные сети в России под давлением. Сервисы блокируют, API ограничивают, +контент модерируют по внешнему указанию. Молодые люди заслуживают социальное пространство, которое: + +1. **Быстрое** — потому что они привыкли к лучшим приложениям в мире +2. **Красивое** — потому что эстетика важна для этого поколения +3. **Честное насчёт приватности** — не «доверьтесь нам», а «проверьте: вот код» +4. **Устойчивое** — если что-то изменится политически, твои сообщения по-прежнему твои + +## Принципы дизайна + +### 1. Скорость — это уважение + +Каждая миллисекунда загрузки говорит «мы не ценим твоё время». +Morpheus должен ощущаться мгновенным — быстрее Telegram, плавнее Instagram. +60fps или ничего. Если пользователь замечает задержку — это баг. + +### 2. Приватность через архитектуру, а не через политику + +Не говори «мы не будем читать ваши сообщения». Говори «мы не можем». +Шифрование NIP-44 означает, что содержимое ЛС — шифротекст на наших реле. +Мы не даём обещание приватности — мы даём математическую гарантию. +Публичные посты — публичные. Личные сообщения — личные. Никакой двусмысленности. + +### 3. Не анонимный, не под наблюдением — просто приватный + +У пользователей есть личности. Они строят репутацию. Они отвечают за публичное поведение. +Но их личные разговоры — их. Это то же ожидание, что люди имеют +от почтовых писем, телефонных звонков и личных бесед. +Morpheus просто распространяет это ожидание на цифровое общение. + +### 4. Простота — это сила + +Каждая функция должна оправдать своё существование. Если подросток не может +разобраться за 3 секунды — слишком сложно. Никаких страниц настроек. Никаких переключателей. +Приложение должно ощущаться как читающее мысли, а не как требующее инструкцию. + +### 5. Мы бизнес, а не движение + +Morpheus — это компания, которая делает продукт. Мы берём деньги за премиум-функции. +Мы не финансируемся рекламой, не продажей данных, не идеологией. +Наш стимул прост: сделать продукт настолько хорошим, чтобы за него платили. +Когда стимулы понятны — доверие следует. + +### 6. Законопослушный и принципиальный + +Мы работаем в рамках закона. Регистрируемся где требуется. Отвечаем на законные запросы. +И строим системы, где зашифрованный контент не может быть расшифрован нами. +Это не противоречия — это ответственная инженерия. +Мы никогда не установим бэкдоры, депонирование ключей или призрачные протоколы. +Если мы технически не можем выполнить конкретный запрос, мы об этом прозрачно сообщаем. + +### 7. Открытый по умолчанию + +Клиент с открытым исходным кодом. Протокол (Nostr) открытый. +Пользователи могут проверить каждое заявление о приватности, прочитав код. +Если не доверяете нам — не верьте на слово — проведите аудит. + +## Что такое Morpheus + +- Быстрая, красивая социальная сеть для молодых русскоязычных людей +- Построена на протоколе Nostr для настоящего шифрования и переносимости +- Бизнес, который зарабатывает на премиум-функциях, а не на данных пользователей +- Соблюдает применимое законодательство, защищая то, что защищает шифрование +- Приложение, о котором друг рассказывает потому что оно хорошее, а не потому что политическое + +## Чем Morpheus НЕ является + +- **Не анонимный** — у тебя реальная, постоянная личность +- **Не инструмент протеста** — это для мемов, групповых чатов, знакомств, музыки, друзей +- **Не крипто/Web3 проект** — Nostr использует ключи, но нет токенов и блокчейна +- **Не антиправительственный** — мы соблюдаем закон; мы также используем надёжное шифрование +- **Не даркнет-приложение** — эстетика яркая, современная и мейнстримная + +## Спектр приватности + +```plaintext +Полная слежка Позиция Morpheus Полная анонимность +|__________________________|___________________________| +VK, OK «Приватный, не анонимный» Tor, I2P + - Реальные личности + - E2E-шифрованные ЛС + - Публичные посты публичны + - Законопослушная работа + - Без бэкдоров +``` + +Morpheus занимает практичную золотую середину: та же приватность, которую ты ожидаешь +в реальной жизни, применённая к цифровому общению. Не более экстремально. Не менее. + +## Обещание Morpheus + +Мы будем: + +- Шифровать все ЛС с NIP-44 — всегда, по умолчанию, без необходимости включения +- Публиковать наш исходный код +- Отвечать на законные запросы данными, которыми мы реально располагаем +- Быть прозрачными о том, какие данные существуют, а какие нет +- Никогда не добавлять бэкдоры и не ослаблять шифрование +- Никогда не продавать данные пользователей и не запускать рекламу +- Строить устойчивый бизнес на премиум-функциях + +Мы будем честны, когда не можем что-то сделать, а не притворяться, что можем. diff --git a/docs/ru/threat-model-and-workarounds.md b/docs/ru/threat-model-and-workarounds.md new file mode 100644 index 0000000..62aca2e --- /dev/null +++ b/docs/ru/threat-model-and-workarounds.md @@ -0,0 +1,242 @@ +# Morpheus — Модель угроз и решения + +## Юридическая позиция + +Morpheus — **законопослушная, принципиальная** компания: + +- Мы регистрируемся где требуется и работаем в рамках применимого права +- Мы отвечаем на законные запросы данными, которыми реально располагаем +- Мы используем сквозное шифрование NIP-44 для ЛС — содержимое ЛС не является данными, которые мы имеем в читаемой форме +- Мы никогда не добавим бэкдоры, депонирование ключей и не ослабим шифрование +- Мы прозрачны: если нас просят о данных, которые мы не можем предоставить, мы объясняем почему + +Это модель Apple/WhatsApp, применённая к социальным сетям: +полное сотрудничество, но архитектура делает определённые запросы технически невозможными. + +--- + +## Основное различие: Приватный ≠ Анонимный + +Morpheus — **приватный**, не **анонимный**. + +| | Анонимный | Приватный (Morpheus) | +| --- | --- | --- | +| Идентичность | Скрытая, одноразовая | Реальная, постоянная, с репутацией | +| Публичный контент | Нельзя отследить автора | Автор известен — в этом суть | +| ЛС | Никто не может их прочитать | Никто не может их прочитать (NIP-44) | +| Метаданные | Скрытые (уровень Tor) | Доступны операторам реле | +| Юридическая позиция | Уклонение от идентификации | Законопослушность; шифрование защищает контент | +| Атмосфера | Даркнет, паранойя | Нормальная социальная жизнь с реальной защитой | + +**Позиция Morpheus:** «Все знают твоё имя. Никто не читает твои сообщения.» + +NIP-44 шифрует *содержание* личных сообщений. Метаданные (кто с кем общался, когда) +видны операторам реле. Это честная и защитимая позиция: +мы защищаем разговор, а не факт его существования. + +--- + +## Проблема 1: Несоответствие аудитории и ценностного предложения + +**Проблема:** Молодёжь не покупает «приватность». Они покупают скорость, эстетику и статус. + +**Решения:** + +1. **Вести продуктом, а не протоколом.** Маркетинг никогда не упоминает Nostr, реле или шифрование напрямую. Он говорит: «самое быстрое социальное приложение» или «групповые чаты, которые реально работают». + +2. **Приватность как текстура, а не фича.** Вместо страницы «настройки приватности» приватность проявляется как: + - Тонкая иконка замка на ЛС (всегда там, нельзя отключить — просто работает) + - «Сообщения зашифрованы» показано один раз при онбординге, потом никогда + - Нет «был в сети» или «прочитано» по умолчанию (приватность = социальный комфорт) + +3. **Скорость — ЭТО фича.** Молодёжь сравнивает приложения по ощущению скорости. Инвестировать непропорционально в воспринимаемую производительность: оптимистичный UI, мгновенная отправка, предзагрузка лент, агрессивное кеширование. + +4. **Социальное доказательство важнее фич.** Получить 5 популярных создателей на платформу до публичного запуска. Молодёжь идёт за людьми, а не за протоколами. + +--- + +## Проблема 2: Технические ограничения Nostr + +**Проблема:** Nostr не имеет нативной поддержки функций, которые ожидает молодёжь. + +### 2a. Групповые чаты + +**Текущее состояние:** NIP-29 (группы на базе реле) базовый. Нет богатых функций. + +**Решение:** + +- Строить на NIP-29 для публичных групп (модерируемые реле, обнаруживаемые) +- Для приватных групп: NIP-44 шифрование с общим групповым ключом, ротация при смене участников +- Реализовать функции групп на уровне клиента: ответы, реакции, закрепы, упоминания, треды +- Это кастомная работа, но даёт конкурентное преимущество — «лучшие групповые чаты на Nostr» + +### 2b. Хостинг медиа + +**Текущее состояние:** Nostr-события текстовые. Медиа требует внешний хостинг. + +**Решение:** + +- Запуск управляемых серверов Blossom (BLOb Simple Storage) для загрузки медиа +- NIP-96 хранение файлов как стандарт — пользователи загружают через приложение, раздача через CDN +- Агрессивная клиентская компрессия (WebP/AVIF для изображений, H.265 для видео) +- Прогрессивная загрузка: превью → среднее → полное разрешение +- Квота хранения привязана к уровню аккаунта (бесплатный = разумный, Pro = щедрый) +- Контентно-адресуемое хранение (дедупликация по хешу) экономит расходы + +### 2c. Поиск и обнаружение + +**Текущее состояние:** Нет глобального поиска. Поиск по реле — специфичен для реле. + +**Решение:** + +- Клиентский полнотекстовый индекс контента подписок (SQLite/Realm на устройстве) +- «Обзор» на базе курируемой агрегации реле — Morpheus запускает индексирующий реле +- Трендовые темы вычисляются по объёму публичных событий через реле сообщества Morpheus +- Обнаружение по хештегам (NIP-12 запросы по общим тегам) +- «Люди, которых вы можете знать» на основе пересечения социальных графов (вычисляется на клиенте) +- Курируемые людьми рекомендуемые аккаунты и сообщества (редакционно, не алгоритмически) + +### 2d. Управление ключами / Восстановление личности + +**Текущее состояние:** Потерял nsec = потерял всё. Неприемлемо для молодёжи. + +**Решение:** + +- **Социальное восстановление ключа (основное):** Разделение секрета Шамира — ключ восстановления делится между N доверенными контактами, требуется K из N для восстановления. «Выбери 5 друзей. Любые 3 могут помочь восстановить аккаунт.» +- **Зашифрованный облачный бэкап (опционально):** Зашифровать nsec паролем пользователя, хранить зашифрованный блоб в iCloud/Google Drive. +- **Ключи привязанные к устройству:** Хранение nsec в Secure Enclave / Android Keystore. Биометрическая разблокировка. +- **NIP-46 (Nostr Connect):** Паттерн удалённого подписанта — для продвинутых пользователей. +- **Прогрессивное раскрытие:** Новые пользователи получают ключ на устройстве + предложение облачного бэкапа. Продвинутые пользователи могут экспортировать nsec. + +### 2e. Истории / Эфемерный контент + +**Текущее состояние:** Нет нативного примитива Nostr для исчезающего контента. + +**Решение:** + +- NIP-40 (таймстамп истечения) на событиях — реле удаляют после TTL +- Клиент обеспечивает отображение истечения (даже если rogue-реле хранит событие) +- Истории как карусель событий kind:20 или kind:1063 с истечением через 24ч +- Не «исчезающие» в смысле Signal — но соответствует UX историй Instagram/Telegram + +--- + +## Проблема 3: Блокировка государством + +**Проблема:** Роскомнадзор может заблокировать домены и IP реле. + +**Контекст:** Morpheus работает законопослушно, но блокировка может произойти несмотря на это (как с Telegram в 2018-2020). Цель — не уклонение от правоохранительных органов, а обеспечение доступности сервиса. + +**Решения:** + +### Слой 1: Стандартная устойчивость + +- WebSocket через TLS (wss://) выглядит как обычный HTTPS-трафик для DPI +- Реле за Cloudflare или аналогичным CDN — блокировка CDN блокирует миллионы сайтов +- Несколько доменов реле в разных TLD — избыточность, не уклонение +- Приложение автоматически переключается на рабочие реле + +### Слой 2: Устойчивость распространения + +- Android: Google Play, RuStore, прямая загрузка APK, F-Droid +- iOS: App Store, PWA как запасной вариант при удалении из магазина +- Веб-приложение всегда доступно как базовая линия +- Ссылки на APK/PWA через существующие каналы (Telegram-боты, QR-коды) + +### Слой 3: Проактивное взаимодействие + +- Проактивно взаимодействовать с регуляторами — объяснять, какие данные у нас есть, и предоставлять их +- Демонстрировать готовность к сотрудничеству для снижения мотивации к блокировке +- Поддерживать диалог — блокировка часто переговоры, а не бинарное решение + +**Примечание:** Если Morpheus заблокируют несмотря на сотрудничество, протокол Nostr гарантирует +доступ к данным через любой другой Nostr-клиент. Это ультимативная устойчивость. + +--- + +## Проблема 4: Юридическое соответствие (Закон Яровой / СОРМ) + +**Проблема:** Российское законодательство требует хранения и предоставления доступа к коммуникациям. + +**Подход: Полное сотрудничество, честное объяснение архитектуры.** + +1. **Регистрация по требованию.** Юрлицо (юрисдикция TBD по совету юристов). Регистрация как организатор распространения информации при необходимости. + +2. **Хранить то, что можем.** Публичные посты, метаданные, логи подключений — они существуют на наших реле и мы можем их предоставить. + +3. **Объяснять то, что не можем хранить.** Содержимое ЛС зашифровано на стороне клиента NIP-44. У нас никогда нет ключей дешифрования. Это не уклонение — это задокументированная, проверяемая архитектура. + +4. **Открытый исходный код подтверждает наши заявления.** Любой технический аудит кодовой базы подтвердит, что сервер никогда не имеет доступа к открытому тексту ЛС. + +5. **Юридический прецедент.** WhatsApp, Signal и iMessage работают с E2E-шифрованием во многих юрисдикциях. + +6. **Сбор данных регистрации не более необходимого.** Если для юридического соответствия требуется телефон/email, мы собираем. Но не больше. + +**Ключевой принцип:** Мы никогда не отказываемся сотрудничать. Мы объясняем техническую реальность. Зашифрованное зашифровано — не потому что мы выбираем не расшифровывать, а потому что не можем. + +--- + +## Проблема 5: Монетизация без рекламы + +**Проблема:** Никакой рекламы, никогда. Нужен альтернативный доход. + +**Подход:** См. [monetization.md](./monetization.md). Резюме: + +- Подписка Morpheus Pro (премиум-функции, кастомизация, увеличенные лимиты) +- Маркетплейс стикеров/тем (экономика создателей с комиссией) +- Инструменты для создателей (платная аналитика, контент только для подписчиков) +- Бизнес-профили (фиксированная месячная плата, только органический охват) +- Управляемый хостинг реле (инфраструктура-как-сервис для сообществ) + +Все потоки дохода добровольные и не требуют профилирования пользователей. + +--- + +## Проблема 6: Модерация контента + +**Проблема:** Молодёжь на платформе требует ответственной модерации без подрыва приватности. + +**Подход:** + +1. **Публичный контент модерируем.** Публичные посты... публичные. Мы можем и будем модерировать публичный контент на реле, которые мы оперируем. Стандартные правила сообщества. + +2. **Зашифрованные ЛС не модерируемы нами — и это нормально.** Как почтовая служба не читает ваши письма. Клиентские функции безопасности (блок, жалоба, мут) дают пользователям контроль. + +3. **Многоуровневая модерация публичного контента:** + - **Уровень реле:** Реле Morpheus применяют опубликованные правила сообщества. + - **Уровень сообщества:** Модераторы групп управляют своими пространствами. NIP-56 жалобы поступают к модераторам. + - **Уровень клиента:** Спам-фильтры, предупреждения о контенте, мут/блок инструменты. + +4. **Соответствие CSAM:** Хеш-сопоставление (PhotoDNA или эквивалент) на медиа, загружаемые на серверы Morpheus. Обязательное юридическое и этическое обязательство. На серверной стороне медиа CDN. + +5. **Отчёты прозрачности.** Ежеквартальные публикации: сколько модерационных действий, сколько юридических запросов, какие данные были предоставлены. + +--- + +## Проблема 7: Холодный старт / Сетевые эффекты + +**Проблема:** Социальная сеть без пользователей бесполезна. + +**Решения:** + +1. **Запуск как мессенджер, потом как соцсеть.** Групповым чатам не нужны сетевые эффекты — нужны 5-10 друзей. «Перенеси свою группу друзей в Morpheus» — выполнимое предложение. + +2. **Мост в Telegram.** Бот для кросспостинга между группами Telegram и Morpheus. Снижает стоимость перехода. + +3. **Таргетировать конкретные сообщества:** + - Студенческие группы университетов + - Игровые сообщества + - Музыка/арт сцены + - Технически продвинутые ранние пользователи + +4. **Партнёрства с создателями.** Привлечь популярных русскоязычных создателей контента. Их аудитории последуют. + +5. **Функция «Импорт группы».** Создать группу Morpheus из существующей группы Telegram/VK, авто-приглашение участников. + +6. **Реферальные механики.** «Пригласи 3 друзей → разблокируй эксклюзивный стикерпак.» + +7. **Запустить киллер-фичу, которой нет нигде:** + - Голосовые сообщения с автоматической транскрипцией (огромный спрос в русскоязычных сообществах) + - Встроенный редактор мемов + - Анонимные вопросы на профилях (как ASKfm — весело и вирально) + - Превосходные инструменты создания стикеров diff --git a/docs/ru/web-of-trust.md b/docs/ru/web-of-trust.md new file mode 100644 index 0000000..ab5466f --- /dev/null +++ b/docs/ru/web-of-trust.md @@ -0,0 +1,85 @@ +# Morpheus — Сеть доверия (Web of Trust) + +## Основная идея + +Реле Morpheus принимает события только от публичных ключей, на которые +подписаны как минимум **N** существующих участников реле. Используется +граф подписок, уже существующий в Nostr (NIP-02 списки контактов) — +никаких кастомных NIP, токенов-приглашений или специальных событий +поручительства. + +## Как это работает + +1. Пользователь A публикует список контактов NIP-02, включающий + публичный ключ пользователя B +2. Реле подсчитывает, сколько существующих участников подписаны на B +3. Если количество достигает порога (например, 3), реле начинает + принимать события от B +4. Если количество подписчиков B падает ниже порога (отписки), реле + перестаёт принимать новые события от него + +```text +Реле получает событие от pubkey X + → Подсчитать NIP-02 списки контактов на этом реле, включающие X + → Если количество >= N: принять событие + → Если количество < N: отклонить с auth-required или closed +``` + +## Почему это работает + +- **Спам умирает естественно** — боты не могут набрать реальные подписки + от существующих участников и никогда не достигают порога +- **Нет затрат на модерацию** — граф подписок и есть слой модерации; + ни одному админу не нужно вручную одобрять или банить пользователей +- **Сообщество остаётся целостным** — начальное сообщество русскоязычное, + подписки распространяются через реальные социальные связи, поэтому + сеть остаётся культурно и лингвистически однородной без явных + языковых фильтров +- **Нерелевантный шум исчезает** — реле обслуживает только события от + множества участников, случайный глобальный трафик Nostr не попадает + в ленту +- **Нет кастомного протокола** — используются только NIP-01 (события) + и NIP-02 (списки контактов), которые поддерживает каждый клиент Nostr +- **Децентрализованное доверие** — нет единого привратника; доверие + распределено по графу подписок + +## Настройка порога + +| N | Эффект | +| --- | --- | +| 1 | Минимальный барьер — одна подписка от любого участника даёт доступ. Лёгкий рост, слабая защита от спама. | +| 3 | Баланс — требуется небольшой социальный кластер. Хорошо для фазы раннего роста. | +| 5+ | Тесное сообщество — труднее попасть, сильная защита от спама. Хорошо для зрелой сети. | + +Порог может быть динамическим — ниже в период раннего роста, выше по +мере взросления сети. Также может различаться по типу событий +(например, публикация требует 3 подписок, а ЛС — только 1). + +## Граничные случаи + +- **Проблема курицы и яйца** — первые N пользователей добавляются + вручную (начальное множество). Это основатели сообщества. +- **Наблюдатели** — пользователи, которые читают, но не публикуют, тоже + нуждаются в подписках для взаимодействия. Доступ на чтение может быть + открытым. +- **Кросс-реле** — пользователи могут подключаться к публичным реле + параллельно с реле Morpheus. Барьер WoT применяется только к ленте + реле Morpheus. +- **Защита от сибилов** — создание фейковых аккаунтов для подписки на + себя возможно, но затратно в масштабе (каждому фейку самому нужно N + реальных подписчиков). Рекурсия делает сибил-атаки экспоненциально + сложнее. +- **Потеря подписчиков** — если кто-то отписывается и количество падает + ниже N, существующие события остаются на реле, но новые отклоняются + до восстановления числа подписчиков. + +## Заметки по реализации + +- Реле поддерживает материализованное представление графа подписок + (NIP-02, kind:3 события) +- При каждом входящем событии проверяется количество входящих подписок + автора относительно порога +- Подсчёт обновляется в реальном времени при публикации списков + контактов NIP-02 +- Начальное множество (вручную разрешённые pubkey) настраивается при + запуске реле diff --git a/docs/threat-model-and-workarounds.md b/docs/threat-model-and-workarounds.md new file mode 100644 index 0000000..1f0f868 --- /dev/null +++ b/docs/threat-model-and-workarounds.md @@ -0,0 +1,243 @@ +# Morpheus — Threat Model & Workarounds + +## Legal Posture + +Morpheus is a **compliant, principled** operation: + +- We register where required and operate within applicable law +- We respond to lawful data requests with data we actually have +- We use NIP-44 end-to-end encryption for DMs — meaning DM content is not data we have in readable form +- We will never add backdoors, key escrow, or weaken encryption under any circumstances +- We are transparent: if asked for data we cannot provide, we explain why + +This is the Apple/WhatsApp model applied to social networking: +cooperate fully, but the architecture makes certain requests technically impossible. + +--- + +## The Core Distinction: Private ≠ Anonymous + +Morpheus is **private**, not **anonymous**. + +| | Anonymous | Private (Morpheus) | +| --- | --- | --- | +| Identity | Hidden, disposable | Real, persistent, reputation-bearing | +| Public content | Untraceable to author | Author known — that's the point | +| DMs | Nobody can read them | Nobody can read them (NIP-44) | +| Metadata | Hidden (Tor-level) | Available to relay operators | +| Legal posture | Evades identification | Compliant; encryption protects content | +| Vibe | Dark web, paranoia | Normal social life with real protection | + +**Morpheus position:** "Everyone knows your name. Nobody reads your messages." + +NIP-44 encrypts the *content* of direct messages. Metadata (who talked to whom, when) +is visible to relay operators. This is an honest and defensible position: +we protect the conversation, not the fact that it happened. + +--- + +## Problem 1: Target Audience vs. Value Proposition Mismatch + +**Problem:** Teens don't buy "privacy." They buy speed, aesthetics, and social status. + +**Workarounds:** + +1. **Lead with product, not protocol.** Marketing never mentions Nostr, relays, or encryption upfront. It says: "the fastest social app" or "group chats that actually work." + +2. **Privacy as texture, not feature.** Instead of a "privacy settings" page, privacy manifests as: + - A subtle lock icon on DMs (always there, never toggleable — it just works) + - "Messages are encrypted" shown once during onboarding, then never again + - No "last seen" or "read receipts" by default (privacy = social comfort for teens) + +3. **Speed IS the feature.** Teens compare apps by how fast they feel. Invest disproportionately in perceived performance: optimistic UI, instant message sending, preloaded feeds, aggressive caching. + +4. **Social proof matters more than features.** Get 5 popular creators on the platform before public launch. Teens follow people, not protocols. + +--- + +## Problem 2: Nostr Technical Limitations + +**Problem:** Nostr lacks native support for features teens expect. + +### 2a. Group Chats + +**Current state:** NIP-29 (relay-based groups) is basic. No rich features. + +**Workaround:** + +- Build on NIP-29 for public groups (relay-moderated, discoverable) +- For private groups: use NIP-44 encryption with a shared group key, rotated when members change +- Implement group features at the client level: replies, reactions, pins, mentions, threads +- This is custom work but gives competitive advantage — "best group chats on Nostr" + +### 2b. Media Hosting + +**Current state:** Nostr events are text. Media requires external hosting. + +**Workaround:** + +- Run managed Blossom (BLOb Simple Storage) servers for media uploads +- NIP-96 file storage as standard — users upload via the app, served via CDN +- Aggressive client-side compression (WebP/AVIF for images, H.265 for video) +- Progressive loading: thumbnail → medium → full resolution +- Storage quota tied to account tier (free = reasonable, Pro = generous) +- Content-addressed storage (deduplication by hash) saves costs + +### 2c. Search & Discovery + +**Current state:** No global search. Relay search is relay-specific. + +**Workaround:** + +- Client-side full-text index of followed users' content (SQLite/Realm on device) +- "Explore" powered by curated relay aggregation — Morpheus runs an indexing relay +- Trending topics computed from public event volume across Morpheus community relays +- Hashtag-based discovery (NIP-12 generic tag queries) +- "People you might know" based on social graph overlap (computed client-side, not server-side) +- Human-curated featured accounts and communities (editorial, not algorithmic) + +### 2d. Key Management / Identity Recovery + +**Current state:** Lose your nsec = lose everything. Unacceptable for teens. + +**Workaround:** + +- **Social key recovery (primary):** Shamir's Secret Sharing — split the recovery key among N trusted contacts, require K of N to reconstruct. "Choose 5 friends. Any 3 can help you recover your account." +- **Encrypted cloud backup (optional):** Encrypt nsec with a user-chosen passphrase, store encrypted blob in iCloud/Google Drive. User controls the encryption key. +- **Device-bound keys:** Store nsec in device Secure Enclave / Android Keystore. Biometric unlock. Key never leaves the device in plaintext. +- **NIP-46 (Nostr Connect):** Remote signer pattern — the key lives in a signer app, Morpheus never touches it directly. Advanced users can use this. +- **Progressive disclosure:** New users get device-bound key + cloud backup prompt. Power users can export nsec and manage it themselves. + +### 2e. Stories / Ephemeral Content + +**Current state:** No native Nostr primitive for disappearing content. + +**Workaround:** + +- Use NIP-40 (expiration timestamp) on events — relays delete after TTL +- Client enforces expiration display-side (even if a rogue relay keeps the event) +- Stories rendered as a carousel of kind:20 (short text notes) or kind:1063 (file metadata) events with 24h expiration +- Not truly "disappearing" in the Signal sense — but matches Instagram/Telegram stories UX + +--- + +## Problem 3: Government Blocking + +**Problem:** Roskomnadzor can block relay domains and IPs. + +**Context:** Morpheus operates compliantly, but blocking may happen regardless (as it did with Telegram in 2018-2020). The goal is not to evade law enforcement — it's to ensure service availability for users. + +**Workarounds:** + +### Layer 1: Standard resilience + +- WebSocket over TLS (wss://) looks like normal HTTPS traffic to DPI +- Run relays behind Cloudflare or similar CDN — blocking the CDN blocks millions of sites +- Multiple relay domains in different TLDs — redundancy, not evasion +- App automatically falls back to working relays if some are unreachable + +### Layer 2: Distribution resilience + +- Android: available via Google Play, RuStore, direct APK download, F-Droid +- iOS: App Store, PWA as fallback if removed from store +- Web app always available as baseline +- APK/PWA links shared via existing channels (Telegram bots, QR codes) + +### Layer 3: Proactive engagement + +- Engage with regulators proactively — explain what data we have and provide it +- Demonstrate compliance willingness to reduce motivation for blocking +- Maintain dialogue — blocking is often a negotiation, not a binary + +**Note:** If Morpheus is blocked despite compliance, the Nostr protocol ensures users +can access their data through any other Nostr client. Their social graph and messages +are not locked in our infrastructure. This is the ultimate resilience. + +--- + +## Problem 4: Legal Compliance (Yarovaya Law / SORM) + +**Problem:** Russian law requires storing and providing access to user communications. + +**Approach: Cooperate fully, explain architecture honestly.** + +1. **Register as required.** Operate a legal entity (jurisdiction TBD based on legal advice). Register as an information distribution organizer if required. + +2. **Store what we can store.** Public posts, metadata, connection logs — these exist on our relays and we can provide them. + +3. **Explain what we cannot store.** DM content is encrypted client-side with NIP-44. We never hold decryption keys. This is not evasion — it is the documented, auditable architecture. We cannot provide what we do not have. + +4. **Open source supports our claims.** Any technical audit of the codebase will confirm that the server never has access to plaintext DMs. This is verifiable, not just claimed. + +5. **Legal precedent.** WhatsApp, Signal, and iMessage operate E2E encryption in many jurisdictions. The legal landscape for E2E encryption is complex but there is significant precedent. + +6. **No user registration data collection beyond what's needed.** If registration requires phone/email for legal compliance, we collect it. But we don't collect more than required. + +**The key principle:** We never refuse to cooperate. We explain the technical reality. What is encrypted is encrypted — not because we choose not to decrypt it, but because we cannot. + +--- + +## Problem 5: Monetization Without Ads + +**Problem:** No ads, ever. Need alternative revenue. + +**Approach:** See [monetization.md](./monetization.md). Summary: + +- Morpheus Pro subscription (premium features, customization, higher limits) +- Sticker/theme marketplace (creator economy with commission) +- Creator tools (paid analytics, subscriber-only content) +- Business profiles (flat monthly fee, organic reach only) +- Managed relay hosting (infrastructure-as-a-service for communities) + +All revenue streams are opt-in and require no user profiling. + +--- + +## Problem 6: Content Moderation + +**Problem:** Teens on the platform require responsible content moderation without undermining privacy. + +**Approach:** + +1. **Public content is moderatable.** Public posts are... public. We can and will moderate public content on relays we operate. Standard community guidelines apply. This does not conflict with privacy — public speech has never been "private." + +2. **Encrypted DMs are not moderatable by us — and that's okay.** Just like the postal service doesn't read your letters. Client-side safety features (block, report, mute) give users control. + +3. **Layered moderation for public content:** + - **Relay-level:** Morpheus-operated relays enforce published community guidelines (no CSAM, no doxxing, no harassment). Content that violates guidelines is removed from our relays. + - **Community-level:** Group moderators manage their own spaces. NIP-56 reporting flows to moderators. + - **Client-level:** Spam filters, content warnings, mute/block tools. + +4. **CSAM compliance:** Hash-matching (PhotoDNA or equivalent) on media uploaded to Morpheus-operated media servers. This is a non-negotiable legal and ethical obligation. Happens server-side on the media CDN before content is distributed. + +5. **Transparency reports.** Publish quarterly: how many moderation actions, how many legal requests, what data was provided. Build trust through accountability. + +--- + +## Problem 7: Cold Start / Network Effects + +**Problem:** A social network with no users is useless. + +**Workarounds:** + +1. **Launch as a messenger first, social network second.** Group chats don't need network effects — they need 5-10 friends. "Move your friend group to Morpheus" is a tractable pitch. + +2. **Telegram bridge.** Bot that cross-posts between Telegram groups and Morpheus groups. Reduces switching cost. Users can migrate gradually. + +3. **Target specific communities, not "everyone":** + - University student groups + - Gaming communities + - Music/art scenes + - Tech-savvy early adopters + +4. **Creator partnerships.** Get popular Russian content creators to use Morpheus. Their audiences follow. + +5. **"Import your group" feature.** Create a Morpheus group from an existing Telegram/VK group, auto-invite members. Minimize friction. + +6. **Referral mechanics.** "Invite 3 friends → unlock exclusive sticker pack." Simple, proven, no ads needed. + +7. **Ship a killer feature that doesn't exist elsewhere:** + - Voice messages with automatic transcription (huge in Russian-speaking communities) + - Built-in meme editor + - Anonymous Q&A on profiles (like ASKfm — fun and viral) + - Superior sticker creation tools diff --git a/docs/web-of-trust.md b/docs/web-of-trust.md new file mode 100644 index 0000000..2d96021 --- /dev/null +++ b/docs/web-of-trust.md @@ -0,0 +1,78 @@ +# Morpheus — Web of Trust + +## Core Concept + +The Morpheus relay only accepts events from pubkeys that are followed by +at least **N** existing members on the relay. This uses the follow graph +that already exists in Nostr (NIP-02 contact lists) — no custom NIPs, +no invite tokens, no special vouch events. + +## How It Works + +1. User A publishes a NIP-02 contact list that includes User B's pubkey +2. The relay counts how many existing members follow User B +3. If the count reaches the threshold (e.g., 3), the relay starts + accepting events from User B +4. If User B's follower count drops below the threshold (unfollows), + the relay stops accepting new events from them + +```text +Relay receives event from pubkey X + → Count NIP-02 contact lists on this relay that include X + → If count >= N: accept event + → If count < N: reject with auth-required or closed message +``` + +## Why This Works + +- **Spam dies naturally** — bots cannot accumulate real follows from + established members, so they never reach the threshold +- **No moderation overhead** — the follow graph is the moderation layer; + no admin has to manually approve or ban users +- **Community stays coherent** — the seed community is Russian-speaking, + and follows propagate through real social ties, so the network stays + culturally and linguistically coherent without explicit language filters +- **Irrelevant noise disappears** — the relay only serves events from + the member set, so random global Nostr traffic never enters the feed +- **Zero custom protocol** — uses only NIP-01 (events) and NIP-02 + (contact lists), which every Nostr client already supports +- **Decentralized trust** — no single gatekeeper; trust is distributed + across the follow graph + +## Threshold Tuning + +| N | Effect | +| --- | --- | +| 1 | Minimal gate — one follow from any member lets you in. Easy growth, weak spam protection. | +| 3 | Balanced — requires a small social cluster. Good for early growth phase. | +| 5+ | Tight community — harder to get in, strong spam resistance. Good for mature network. | + +The threshold can be dynamic — lower during early growth, raised as the +network matures. It can also differ per event kind (e.g., posting +requires 3 follows, but DMs only require 1). + +## Edge Cases + +- **Bootstrap problem** — the first N users must be manually allowlisted + (seed set). This is the founding community. +- **Lurkers** — users who read but don't post still need follows to + interact. Read access can optionally be open. +- **Cross-relay** — users can still connect to public relays alongside + the Morpheus relay. The WoT gate only applies to the Morpheus relay + feed. +- **Sybil resistance** — creating fake accounts to follow yourself is + possible but costly at scale (each fake needs N real followers itself). + The recursion makes sybil attacks exponentially harder. +- **Follower loss** — if someone unfollows you and your count drops + below N, your existing events stay on the relay, but new events are + rejected until count recovers. + +## Implementation Notes + +- The relay maintains a materialized view of the follow graph (NIP-02 + kind:3 events) +- On each incoming event, it checks the author's inbound follow count + against the threshold +- The count updates in real-time as NIP-02 contact lists are published +- The seed set (manually allowlisted pubkeys) is configured at relay + startup diff --git a/justfile b/justfile new file mode 100644 index 0000000..7119576 --- /dev/null +++ b/justfile @@ -0,0 +1,3 @@ +# Lint all Markdown files +lint-md: + markdownlint-cli2 "**/*.md" diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 0000000..7b32868 --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,5 @@ +pre-commit: + commands: + lint-markdown: + glob: "*.md" + run: markdownlint-cli2 {staged_files} diff --git a/sketches/chat-mockup.png b/sketches/chat-mockup.png new file mode 100644 index 0000000..6915315 Binary files /dev/null and b/sketches/chat-mockup.png differ diff --git a/sketches/community-mockup.png b/sketches/community-mockup.png new file mode 100644 index 0000000..e820b26 Binary files /dev/null and b/sketches/community-mockup.png differ diff --git a/sketches/feed-mockup.png b/sketches/feed-mockup.png new file mode 100644 index 0000000..6411fe3 Binary files /dev/null and b/sketches/feed-mockup.png differ