Files
eranos/README.md
T
Alex Gleason b8773c47d7 Automate App Store releases via self-hosted Mac runner
Mirror the existing Android publishing flow for iOS. The pipeline
gains two jobs: build-ipa runs on a self-hosted Mac runner and
produces a signed App Store IPA; publish-app-store runs on a shared
Linux runner and submits the prebuilt IPA to App Store Connect.

Build pipeline (.gitlab-ci.yml):
- build-ipa (Mac, stage build, parallel with build-apk): decodes the
  ASC API key, runs match (with api_key, so cert validity is verified
  against Apple before xcodebuild starts), builds web assets, syncs
  Capacitor, stamps MARKETING_VERSION. Uploads Ditto-${CI_COMMIT_TAG}
  .ipa to GitLab's Generic Packages registry.
- publish-app-store (Linux ruby:3.3, needs: [build-ipa]): gem
  install fastlane, decode the ASC API key, extract the changelog
  section into release_notes.txt, fastlane submit_release with
  IPA_PATH pointing at the inherited artifact. No Xcode, no signing,
  no keychain \u2014 pure Apple API call.
- release job now needs both build-apk and build-ipa, and links three
  assets (APK / AAB / IPA).

fastlane (ios/fastlane/Fastfile, Matchfile, Appfile, metadata/):
- Four lanes: build_ipa (CI build), submit_release (CI publish, reads
  IPA_PATH from env), release (single-step convenience for local
  dev), submit_only (debug lane to re-submit an already-uploaded
  build).
- Match config points at the private gitlab.com/soapbox-pub
  /certificates repo. App Store Connect API key is built inline in
  the Fastfile to avoid a collision with match's APP_STORE_CONNECT
  _API_KEY_PATH env var (match wants a JSON descriptor, the action
  writes a raw .p8). CI overrides CODE_SIGN_STYLE=Manual via xcargs
  so the Xcode project can stay on Automatic for local development.

Vite config (vite.config.ts):
- Renames the build-time config override env var from CONFIG_FILE to
  DITTO_CONFIG_FILE. GitLab Runner sets CONFIG_FILE to its own TOML
  config in job env, which broke vite's loader.

App-side changes:
- ios/App/App.xcodeproj/project.pbxproj: team GZLTTH5DLM stamped in;
  MARKETING_VERSION gets stamped from the tag at build time.
- public/CHANGELOG.md, package.json: v2.14.3.

Skills + AGENTS.md updated to reflect the six-job pipeline (test /
deploy unchanged, build now has two jobs, release / publish updated)
and to document Mac-runner operations, fastlane match cert rotation,
and local debugging workflows.
2026-05-11 12:59:04 -07:00

4.7 KiB

Ditto

Your content. Your vibe. Your rules. A fun, customizable Nostr client that puts you in control.

ditto.pub | Docs | Source

About

Ditto is an open-source, decentralized social media client built on the Nostr protocol. It's designed for people who want to have fun online without feeding the Big Tech machine. Express yourself with custom themes, Lightning payments, and an ever-growing set of content types -- all while owning your identity and data.

Made by Soapbox.

Features

  • Theming -- 9 built-in theme presets, 19 CSS token properties for full customization, and the ability to publish and share themes as Nostr events
  • Infinite Content Types -- Text notes, articles, short-form videos (Divines), live streams, polls, follow packs, color moments, magic decks, geocaching, and Webxdc mini-apps
  • Lightning Payments -- Zap posts and profiles with sats via Nostr Wallet Connect (NWC) or WebLN
  • Comments -- Comment on anything: posts, URLs, profiles, hashtags, books, and more (NIP-22)
  • Self-Hosting -- Builds to static HTML/JS/CSS. Deploy anywhere -- GitHub Pages, Netlify, Vercel, a VPS, or a Raspberry Pi
  • Mobile -- Android native app via Capacitor, responsive design for all screen sizes

Getting Started

Prerequisites

Development

git clone https://gitlab.com/soapbox-pub/ditto.git
cd ditto
npm install
npm run dev

The dev server starts at http://localhost:8080.

Build

npm run build

The built site is output to dist/.

Test

Runs type-checking, linting, unit tests, and a production build:

npm test

Configuration

Ditto is configured through a ditto.json file at the project root, read at build time. This file is gitignored so each deployment can have its own configuration.

{
  "theme": "dark",
  "relayMetadata": {
    "relays": [
      { "url": "wss://relay.ditto.pub", "read": true, "write": true }
    ]
  },
  "blossomServers": ["https://blossom.ditto.pub"],
  "feedSettings": {
    "showPosts": true,
    "showReposts": true,
    "showArticles": true
    // ...and more content type toggles
  }
}

Configuration is resolved in three layers (highest priority first):

  1. User settings stored in localStorage
  2. Build config from ditto.json
  3. Hardcoded defaults

Use an alternate config file path with: DITTO_CONFIG_FILE=./my-config.json npm run build

Custom Branding

For self-hosted instances:

  • Replace public/logo.svg and public/logo.png with your logo
  • Update the app name in index.html and public/manifest.webmanifest
  • Replace public/og-image.jpg for social sharing previews
  • Set default relays and upload servers in ditto.json

Deployment

Ditto builds to static files and can be deployed anywhere that serves HTML.

  • GitHub Pages / GitLab Pages -- Push to main and CI auto-deploys
  • Netlify / Vercel -- Connect your fork and deploy. A _redirects file is included for SPA routing
  • VPS / Any web server -- Build and copy dist/ to your server. Configure SPA routing (e.g., Nginx try_files $uri $uri/ /index.html)

Android

Build a native Android app with Capacitor:

npm run build
npx cap sync
npx cap open android

Tech Stack

Layer Technology
Framework React 18
Build Vite
Language TypeScript
Styling TailwindCSS 3 + shadcn/ui
Routing React Router 6
Data TanStack Query
Nostr Nostrify + nostr-tools
Mobile Capacitor
Testing Vitest + React Testing Library

Project Structure

src/
  components/     UI components (100+), including shadcn/ui primitives
  hooks/          Custom React hooks (65+)
  pages/          Page components for each route (30+)
  contexts/       React context providers
  lib/            Utilities and shared logic
  test/           Test setup and helpers
public/           Static assets, icons, manifest

Contributing

We welcome contributions but have high standards. Please read the full Contributing Guide before submitting a merge request. The short version:

  • Bug fixes: One bug, one MR. Keep it small and focused.
  • New features: Must link to an existing issue and align with the Ditto Philosophy.
  • Required: Live preview URL, before/after screenshots, completed self-review checklist.
  • Required tools: Claude Opus 4.6 (or latest frontier model), an AI coding agent with plan mode.

Read the Ditto Philosophy to understand what Ditto is and isn't.

License

AGPL-3.0