A social pastebin built on atproto.
1[](https://github.com/alyraffauf/morsels/actions/workflows/build.yml) [](https://www.gnu.org/licenses/agpl-3.0) [](https://ko-fi.com/alyraffauf)
2
3<div align="center">
4 <h1>morsels</h1>
5 <h3>Small bites, big ideas.</h3>
6 <p>A social pastebin on the <a href="https://atproto.com">Atmosphere</a>.</p>
7</div>
8
9## Features
10
11- **Share bites**: Paste anything, share it with a link.
12- **Built on atproto**: Your bites are stored in your own repo as `blue.morsels.bite` records. Anyone can view them with a morsels instance.
13- **OAuth login**: Sign in with your Bluesky handle or any atproto account. No passwords stored.
14- **Replies**: Comment on bites. Replies are `blue.morsels.reply` records in your repo.
15- **Syntax highlighting**: Auto-detected via [Pygments](https://pygments.org/).
16- **Self-hostable**: One Docker command to run your own instance.
17
18## Quick start
19
20### Docker (recommended)
21
22```bash
23docker run -d -p 8000:8000 -v morsel-data:/data ghcr.io/alyraffauf/morsels:latest
24```
25
26Or with Docker Compose:
27
28```bash
29git clone https://github.com/alyraffauf/morsels.git
30cd morsel
31docker compose up -d
32```
33
34Visit `http://localhost:8000`. First run auto-generates secrets.
35
36### From source
37
38Requires Python 3.14+ and [uv](https://docs.astral.sh/uv/).
39
40```bash
41git clone https://github.com/alyraffauf/morsels.git
42cd morsel
43uv sync
44uv run flask --app main run --debug
45```
46
47## Architecture
48
49morsels is a thin client, so it doesn't store your data. Bites and replies live in each user's atproto repo. The server handles:
50
51- **OAuth sessions** in SQLite (`morsel.db`)
52- **App signing key** in `secrets.json`
53- **In-memory caches** for identity resolution, profiles, and the recent bites feed
54
55External services:
56
57- [Slingshot](https://slingshot.microcosm.blue/) — cached record fetching
58- [Constellation](https://constellation.microcosm.blue/) — reply backlink index
59- [UFOs](https://ufos.microcosm.blue/) — recent bites feed
60
61## Configuration
62
63All configuration is automatic. On first run, morsels generates:
64
65- `secrets.json` — Flask secret key and OAuth client signing key
66- `morsel.db` — SQLite database for OAuth sessions
67
68Set `MORSEL_DATA_DIR` to control where these files are stored (default: current directory, `/data` in Docker).
69
70## License
71
72[AGPL-3.0](LICENSE.md)