Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dimkr/tootik
A federated nanoblogging service with a Gemini frontend.
https://github.com/dimkr/tootik
activitypub activitypub-server fediverse finger finger-protocol gemini gemini-protocol gemini-server go golang gopher gopher-protocol social social-media social-network sqlite
Last synced: 19 days ago
JSON representation
A federated nanoblogging service with a Gemini frontend.
- Host: GitHub
- URL: https://github.com/dimkr/tootik
- Owner: dimkr
- License: apache-2.0
- Created: 2023-03-19T14:01:48.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-10-29T09:53:36.000Z (about 1 month ago)
- Last Synced: 2024-10-29T11:53:28.655Z (about 1 month ago)
- Topics: activitypub, activitypub-server, fediverse, finger, finger-protocol, gemini, gemini-protocol, gemini-server, go, golang, gopher, gopher-protocol, social, social-media, social-network, sqlite
- Language: Go
- Homepage: gemini://hd.206267.xyz
- Size: 1.21 MB
- Stars: 123
- Watchers: 3
- Forks: 4
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- my-awesome-github-stars - dimkr/tootik - A federated nanoblogging service with a Gemini frontend. (Go)
README
```
.. . .. ..
... . .... ...
... . . . . ... .. . . . . ... ...
.. . . .. . . .. . .. .. . .
., . . . . .. . .. . .
. . . .. .. .... . . . . .. ..
. .. ... . . . . . .. . .
. . . .. . .. ...' .. . . . . .
. . . . . __ . .__ _ __ ,; .'. . . ....
. . . / /____ ___ /./_(_) /__ .' .. . . . .
.. ... . . . /.__/ _ \/ _ \/ __/./ '_/. . .. . . .
.' ... . \__/\___/\___/\__/_/_/\_\ . . . .
. . . . . . ... ... . . ..
.. .. . . .... .. . . .. . . . . . ... ....' .
... . . . .. . ... ... . .. .. .,.. .....
. .. ...... . .''. . .. . . . ...
' . .. .. .. . . ... ......::. .. .,. . .. .... ..
. .... . ..... . .. . . ... . .,'. . .. ,.. ..
. . . . . .. . . .. . . .. .. . . . . . . .'
. .... '... ... . . .. . ... . '. ' ...# localhost.localdomain:8443
Welcome, fedinaut! localhost.localdomain:8443 is an instance of tootik, a federated nanoblogging service.
ββββ
π» My feed
π Mentions
β‘οΈ Followed users
π My profile
π‘ Local feed
ποΈ Communities
π₯ Hashtags
π View profile
π Bookmarks
π Search posts
π£ New post
βοΈ Settings
π Status
π Help
```[![Latest release](https://img.shields.io/github/v/release/dimkr/tootik)](https://github.com/dimkr/tootik/releases) [![Build status](https://github.com/dimkr/tootik/actions/workflows/ci.yml/badge.svg)](https://github.com/dimkr/tootik/actions) [![Go Reference](https://pkg.go.dev/badge/github.com/dimkr/tootik.svg)](https://pkg.go.dev/github.com/dimkr/tootik)
## Overview
tootik is a text-based social network.
tootik is federated: users can join an existing server or [set up](SETUP.md) their own instance. A tootik user can interact with others on the same instance, users on other tootik instances, [Mastodon](https://joinmastodon.org/) users, [Lemmy](https://join-lemmy.org/) users and users of other [ActivityPub](https://www.w3.org/TR/activitypub/)-compatible server.
Unlike other social networks, tootik doesn't have a browser-based interface or an app: instead, its minimalistic, text-based interface is served over [Gemini](https://geminiprotocol.net/):
```
Gemini ActivityPub (HTTPS)
β β
βββββββββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββ
β Bob's Gemini client β£ββββ« tootik instance β ββ¬ββ€ Another tootik instance β
β£ββββββββββββββββββββββββ« β£ββββββββββββββββββ« β βββββββββββββββββββββββββββ
β2024-01-01 alice β β$ ./tootik ... β β ββββββββββββββββββ
β> Hi @bob and @carol! β βββ³ββββββββββββββββ βββ€ Something else β
β... β β β ββββββββββββββββββ
βββββββββββββββββββββββββ β β βββββββββββββββββββββ
βββββββββββββββββ»ββββββββ βββ€ Mastodon instance βββ
β Alice's Gemini client β βββββββββββββββββββββ β
β£ββββββββββββββββββββββββ« ββββββββββββββββββββ΄βββββ
β2024-01-01 bob β β Carol's web browser β
β> Hi @alice! β βββββββββββββββββββββββββ€
β... β ββββ alice β
βββββββββββββββββββββββββ ββββ 17h agoβ
βHi @bob and @carol! β
β β
β βββ bob β
β βββ 16h agoβ
β Hi @alice! β
βββββββββββββββββββββββββ€
βββββββββββββββββββββββββ
ββ Hola ββPublishββ
βββββββββββββββββββββββββ
βββββββββββββββββββββββββ
```This makes tootik lightweight, private and accessible:
* Its UI supports [Gemini](https://geminiprotocol.net/) but also Gopher, Finger and [Guppy](https://github.com/dimkr/guppy-protocol): there's a wide variety of clients to choose from and some work great on old devices.
* Rich content is reduced to plain text and links: it's a fast, low-bandwidth UI suitable for screen readers.
* Anonymity: you authenticate using a TLS client certificate and don't have to share your email address or real name.
* No promoted content, tracking or analytics: social networking, with the slow and non-commercial vibe of the small internet.
* It's a single static executable, making it easy to [set up your own instance](SETUP.md) and update it later.
* All instance data is stored in a single file, a [sqlite](https://sqlite.org/) database that is easy to backup and restore.
* It's lightweight: a <=$5/mo VPS or a SBC is more than enough for a small instance.
* It implements the subset of ActivityPub required for its feature set but not more, to stay small, reliable and maintainable.
* It's written in two languages ([Go](https://go.dev/) and SQL), making the codebase suitable for educational purposes and easy to hack on.
* It's permissively-licensed.## Features
* [Good compatibility with various fediverse servers](FEDERATION.md)
* Text posts, with 3 privacy levels
* Public
* To followers
* To mentioned users
* Sharing of public posts
* Users can follow each other to see non-public posts
* With support for [Mastodon's follower synchronization mechanism](https://docs.joinmastodon.org/spec/activitypub/#follower-synchronization-mechanism), aka [FEP-8fcf](https://codeberg.org/fediverse/fep/src/branch/main/fep/8fcf/fep-8fcf.md)
* Multi-choice polls
* [Lemmy](https://join-lemmy.org/)-style communities
* Follow to join
* Mention community in a public post to start thread
* Community sends posts and replies to all members
* Bookmarks
* Full-text search within posts
* Upload of posts and user avatars, over [Titan](gemini://transjovian.org/titan)
* Account migration, in both directions## Using tootik
You can join an [existing instance](gemini://hd.206267.xyz) or [set up your own](SETUP.md).
## Building
go generate ./migrations
Then:
go build ./cmd/tootik -tags fts5
or, to build a static executable:
go build -tags netgo,sqlite_omit_load_extension,fts5 -ldflags "-linkmode external -extldflags -static" ./cmd/tootik
## Architecture
```
βββββββββ ββββββββββ βββββββββββ βββββββββββ
β notes β β shares β β persons β β follows β
β£ββββββββ« β£βββββββββ« β£ββββββββββ« β£ββββββββββ«
βobject β βnote β βactor β βfollower β
βauthor β βby β β... β βfollowed β
β... β β... β β β β... β
βββββββββ ββββββββββ βββββββββββ βββββββββββ
```Most user-visible data is stored in 4 tables in tootik's database:
1. `notes`, which contains [Object](https://pkg.go.dev/github.com/dimkr/tootik/ap#Object) objects that represent posts
2. `shares`, which records "user A shared post B" relationships
3. `persons`, which contains [Actor](https://pkg.go.dev/github.com/dimkr/tootik/ap#Actor) objects that represent users
4. `follows`, which records "user A follows user B" relationships`notes.author`, `shares.by`, `follows.follower` and `follows.followed` point to rows in `persons`.
`shares.note` points to a row in `notes`.
```
βββββββββ ββββββββββ βββββββββββ βββββββββββ ββββββββββ ββββββββββ
β notes β β shares β β persons β β follows β β outbox β β inbox β
βββββββββ€ ββββββββββ€ βββββββββββ€ βββββββββββ€ β£βββββββββ« β£βββββββββ«
βobject β βnote β βactor β βfollower β βactivityβ βactivityβ
βauthor β βby β β... β βfollowed β βsender β βsender β
β... β β... β β β β... β β... β β... β
βββββββββ ββββββββββ βββββββββββ βββββββββββ ββββββββββ ββββββββββ
```Federation happens through two tables, `inbox` and `outbox`. Both contain [Activity](https://pkg.go.dev/github.com/dimkr/tootik/ap#Activity) objects that represent actions performed by the users in `persons`.
`inbox` contains activities by users on other servers, while `outbox` contains activities of local users.
```
ββββββββββββ βββββββββββββββββββ
β gmi.Wrap β£ββ« gemini.Listener β
ββββββββββββ ββββββββββ³βββββββββ
βββββββββ»ββββββββββββ
β front.Handler β
βββββββββββ³ββββββββββ
βββββββββ ββββββββββ ββββββΈβββββ βββββββββββ ββββββββββ ββββββββββ
β notes β β shares β β persons β β follows β β outbox β β inbox β
βββββββββ€ ββββββββββ€ βββββββββββ€ βββββββββββ€ ββββββββββ€ ββββββββββ€
βobject β βnote β βactor β βfollower β βactivityβ βactivityβ
βauthor β βby β β... β βfollowed β βsender β βsender β
β... β β... β β β β... β β... β β... β
βββββββββ ββββββββββ βββββββββββ βββββββββββ ββββββββββ ββββββββββ
```[gemini.Listener](https://pkg.go.dev/github.com/dimkr/tootik/front/gemini#Listener) is a Gemini server that handles requests using [Handler](https://pkg.go.dev/github.com/dimkr/tootik/front#Handler). It adds rows to `persons` during new user registration and changes rows when users change properties like their display name.
[gemini.Listener](https://pkg.go.dev/github.com/dimkr/tootik/front/gemini#Listener) provides [Handler](https://pkg.go.dev/github.com/dimkr/tootik/front#Handler) with a [writer](https://pkg.go.dev/github.com/dimkr/tootik/front/text/gmi#Wrap) that builds a Gemini response and asynchronously sends it to the client in chunks, while [Handler](https://pkg.go.dev/github.com/dimkr/tootik/front#Handler) continues to handle the request and append more lines to the page.
```
ββββββββββββ βββββββββββββββββββ
β gmi.Wrap βββ€ gemini.Listener β
ββββββββββββ ββββββββββ¬βββββββββ
βββββββββ΄ββββββββββββ
βββββββββββββ₯ front.Handler β
β ββ°βββββββββ¬ββββββββ°ββ
βββββΈββββ ββββββββΈββ ββββββ΄βββββ ββΈβββββββββ ββββββββββ ββββββββββ
β notes β β shares β β persons β β follows β β outbox β β inbox β
βββββββββ€ ββββββββββ€ βββββββββββ€ βββββββββββ€ ββββββββββ€ ββββββββββ€
βobject β βnote β βactor β βfollower β βactivityβ βactivityβ
βauthor β βby β β... β βfollowed β βsender β βsender β
β... β β... β β β β... β β... β β... β
βββββββββ ββββββββββ βββββββββββ βββββββββββ ββββββββββ ββββββββββ
```In addition, Gemini requests can:
* Add rows to `notes` (new post)
* Change rows in `notes` (post editing)
* Add rows to `shares` (user shares a post)
* Remove rows from `shares` (user no longer shares a post)
* Add rows to `follows` (user A followed user B)
* Remove rows from `follows` (user A unfollowed user B)
* ...```
ββββββββββββ βββββββββββββββββββ
β gmi.Wrap βββ€ gemini.Listener β
ββββββββββββ ββββββββββ¬βββββββββ
βββββββββ΄ββββββββββββ
βββββββββββββ€ front.Handler ββββββββββββ
β ββ¬βββββββββ¬ββββββββ¬ββ β
βββββ΄ββββ ββββββββ΄ββ ββββββ΄βββββ ββ΄βββββββββ βββΈβββββββ ββββββββββ
β notes β β shares β β persons β β follows β β outbox β β inbox β
βββββββββ€ ββββββββββ€ βββββββββββ€ βββββββββββ€ ββββββββββ€ ββββββββββ€
βobject β βnote β βactor β βfollower β βactivityβ βactivityβ
βauthor β βby β β... β βfollowed β βsender β βsender β
β... β β... β β β β... β β... β β... β
βββββββββ ββββββββββ βββββββββββ βββββββββββ ββββββββββ ββββββββββ
```User actions like post creation or deletion are recorded as [Activity](https://pkg.go.dev/github.com/dimkr/tootik/ap#Activity) objects written to `outbox`.
```
βββββββββββββββββ
ββββββββββββ βββββββββββββββββββ β outbox.Mover β
β gmi.Wrap βββ€ gemini.Listener β β outbox.Poller β
ββββββββββββ ββββββββββ¬βββββββββ β fed.Syncer β
βββββββββ΄ββββββββββββ βββββ³ββββββ³ββββββ
βββββββββββββ€ front.Handler βββββββββββββ
β ββ¬βββββββββ¬ββββββββ¬ββ β ββ
βββββ΄ββββ ββββββββ΄ββ ββββββ΄βββββ ββ΄ββββββββΈβ βββ΄βΈββββββ ββββββββββ
β notes β β shares β β persons β β follows β β outbox β β inbox β
βββββββββ€ ββββββββββ€ βββββββββββ€ βββββββββββ€ ββββββββββ€ ββββββββββ€
βobject β βnote β βactor β βfollower β βactivityβ βactivityβ
βauthor β βby β β... β βfollowed β βsender β βsender β
β... β β... β β β β... β β... β β... β
βββββββββ ββββββββββ βββββββββββ βββββββββββ ββββββββββ ββββββββββ
```tootik may perform automatic actions and push additional activities to `outbox`, on behalf of the user:
1. Follow the new account and unfollow the old one, if a followed user moved their account
2. Update poll results for polls published by the user, and send the new results to followers
3. Handle disagreement between `follows` rows for this user and what other servers know```
βββββββββββββββββ
ββββββββββββ βββββββββββββββββββ β outbox.Mover β
β gmi.Wrap βββ€ gemini.Listener β β outbox.Poller β
ββββββββββββ ββββββββββ¬βββββββββ β fed.Syncer β
βββββββββ΄ββββββββββββ βββββ¬ββββββ¬ββββββ
βββββββββββββ€ front.Handler βββββββΌββββββ
β ββ¬βββββββββ¬ββββββββ¬ββ β ββ
βββββ΄ββββ ββββββββ΄ββ ββββββ΄βββββ ββ΄ββββββββ΄β βββ΄β΄ββββββ ββββββββββ
β notes β β shares β β persons β β follows β β outbox β β inbox β
βββββββββ€ ββββββββββ€ βββββββββββ€ βββββββββββ€ ββββββββββ€ ββββββββββ€
βobject β βnote β βactor β βfollower β βactivityβ βactivityβ
βauthor β βby β β... β βfollowed β βsender β βsender β
β... β β... β β β β... β β... β β... β
βββββββββ ββββββββββ βββββββββββ βββββββββ°ββ ββ°ββββββββ ββββββββββ
ββ»βββββ»ββββββ
β fed.Queue β
βββββββββββββ
```[fed.Queue](https://pkg.go.dev/github.com/dimkr/tootik/fed#Queue) polls `outbox` and delivers these activities to followers on other servers. It uses the `deliveries` table to track delivery progress and retry failed deliveries.
```
βββββββββββββββββ
ββββββββββββ βββββββββββββββββββ β outbox.Mover β
β gmi.Wrap βββ€ gemini.Listener β β outbox.Poller β
ββββββββββββ ββββββββββ¬βββββββββ β fed.Syncer β
βββββββββ΄ββββββββββββ βββββ¬ββββββ¬ββββββ
βββββββββββββ€ front.Handler βββββββΌββββββ
β ββ¬βββββββββ¬ββββββββ¬ββ β ββ
βββββ΄ββββ ββββββββ΄ββ ββββββ΄βββββ ββ΄ββββββββ΄β βββ΄β΄ββββββ ββββββββββ
β notes β β shares β β persons β β follows β β outbox β β inbox β
βββββββββ€ ββββββββββ€ βββββββββββ€ βββββββββββ€ ββββββββββ€ ββββββββββ€
βobject β βnote β βactor β βfollower β βactivityβ βactivityβ
βauthor β βby β β... β βfollowed β βsender β βsender β
β... β β... β β β β... β β... β β... β
βββββββββ ββββββββββ ββββββ°βββββ βββββββββ¬ββ ββ¬ββββββββ ββββββββββ
β ββ΄βββββ΄ββββββ
βββββββββ»βββββββ ββββββ₯ fed.Queue β
β fed.Resolver β£ββ βββββββββββββ
ββββββββββββββββ
```[Resolver](https://pkg.go.dev/github.com/dimkr/tootik/fed#Resolver) is responsible for fetching [Actor](https://pkg.go.dev/github.com/dimkr/tootik/ap#Actor)s that represent users of other servers, using `user@domain` pairs and [WebFinger](https://datatracker.ietf.org/doc/html/rfc7033). The fetched objects are cached in `persons`, and contain properties like the user's inbox URL and public key.
[fed.Queue](https://pkg.go.dev/github.com/dimkr/tootik/fed#Queue) uses [Resolver](https://pkg.go.dev/github.com/dimkr/tootik/fed#Resolver) to make a list of unique inbox URLs each activity should be delivered to. If this is a wide delivery (a public post or a post to followers) and two recipients share the same `sharedInbox`, [fed.Queue](https://pkg.go.dev/github.com/dimkr/tootik/fed#Queue) delivers the activity to both recipients in a single request.
```
βββββββββββββββββ
ββββββββββββ βββββββββββββββββββ β outbox.Mover β
β gmi.Wrap βββ€ gemini.Listener β β outbox.Poller β
ββββββββββββ ββββββββββ¬βββββββββ β fed.Syncer β
βββββββββ΄ββββββββββββ βββββ¬ββββββ¬ββββββ ββββββββββββββββ
βββββββββββββ€ front.Handler βββββββΌββββββ ββββ« fed.Listener β£βββββββ
β ββ¬βββββββββ¬ββββββββ¬ββ β ββ β βββββββ³βββββββββ β
βββββ΄ββββ ββββββββ΄ββ ββββββ΄βββββ ββ΄ββββββββ΄β βββ΄β΄βββββΈβ βββββββΈβββ β
β notes β β shares β β persons β β follows β β outbox β β inbox β β
βββββββββ€ ββββββββββ€ βββββββββββ€ βββββββββββ€ ββββββββββ€ ββββββββββ€ β
βobject β βnote β βactor β βfollower β βactivityβ βactivityβ β
βauthor β βby β β... β βfollowed β βsender β βsender β β
β... β β... β β β β... β β... β β... β β
βββββββββ ββββββββββ ββββββ¬βββββ βββββββββ¬ββ ββ¬ββββββββ ββββββββββ β
β ββ΄βββββ΄ββββββ β
βββββββββ΄βββββββ ββββββ€ fed.Queue β β
β fed.Resolver βββ βββββββββββββ β
βββββββββ°βββββββ β
β β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
```Requests from other servers are handled by [fed.Listener](https://pkg.go.dev/github.com/dimkr/tootik/fed#Listener), a HTTP server.
It extracts the signature and key ID from a request using [httpsig.Extract](https://pkg.go.dev/github.com/dimkr/tootik/httpsig#Extract), uses [Resolver](https://pkg.go.dev/github.com/dimkr/tootik/fed#Resolver) to fetch the public key if needed, validates the request using [Verify](https://pkg.go.dev/github.com/dimkr/tootik/httpsig#Signature.Verify) and inserts the received [Activity](https://pkg.go.dev/github.com/dimkr/tootik/ap#Activity) object into `inbox`.
In addition, [fed.Listener](https://pkg.go.dev/github.com/dimkr/tootik/fed#Listener) allows other servers to fetch public activity (like public posts) from `outbox`, so they can fetch some past activity by a newly-followed user.
```
βββββββββββββββββ
ββββββββββββ βββββββββββββββββββ β outbox.Mover β
β gmi.Wrap βββ€ gemini.Listener β β outbox.Poller β
ββββββββββββ ββββββββββ¬βββββββββ β fed.Syncer β
βββββββββ΄ββββββββββββ βββββ¬ββββββ¬ββββββ ββββββββββββββββ
βββββββββββββ€ front.Handler βββββββΌββββββ ββββ€ fed.Listener ββββββββ
β ββ¬βββββββββ¬ββββββββ¬ββ β ββ β βββββββ¬βββββββββ β
βββββ΄ββββ ββββββββ΄ββ ββββββ΄βββββ ββ΄ββββββββ΄β βββ΄β΄βββββ΄β βββββββ΄βββ β
β notes β β shares β β persons β β follows β β outbox β β inbox β β
βββββββββ€ ββββββββββ€ βββββββββββ€ βββββββββββ€ ββββββββββ€ ββββββββββ€ β
βobject β βnote β βactor β βfollower β βactivityβ βactivityβ β
βauthor β βby β β... β βfollowed β βsender β βsender β β
β... β β... β β β β... β β... β β... β β
βββββ°ββββ βββββ°βββββ ββββββ¬βββββ ββββββ°βββ¬ββ ββ¬ββββββββ ββββββββ°ββ β
β β β β ββ΄βββββ΄ββββββ ββββββ»βββββββββ β
β β βββββββββ΄βββββββ ββββββ€ fed.Queue β β inbox.Queue β β
β β β fed.Resolver βββ β βββββββββββββ βββ³ββ³ββ³ββββββββ β
β β βββββββββ¬βββββββ βββββββββββββββββββββββ β β β
β βββββββββββββΏββββββββββββββββββββββββββββββββββββ β β
βββββββββββββββββββββββΏββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
```Once inserted into `inbox`, [inbox.Queue](https://pkg.go.dev/github.com/dimkr/tootik/inbox#Queue) processes the received activities:
* Adds new posts received in `Create` activities to `notes`
* Edits posts in `notes` according to `Update` activities
* Records `Announce` activities in `shares`
* Marks a follower-followed relationship in `follows` as accepted, when the followed user sends an `Accept` activity
* Adds a new row to `follows` when a remote user sends a `Follow` activity to a local user
* ...```
βββββββββββββββββ
ββββββββββββ βββββββββββββββββββ β outbox.Mover β
β gmi.Wrap βββ€ gemini.Listener β β outbox.Poller β
ββββββββββββ ββββββββββ¬βββββββββ β fed.Syncer β
βββββββββ΄ββββββββββββ βββββ¬ββββββ¬ββββββ ββββββββββββββββ
βββββββββββββ€ front.Handler βββββββΌββββββ ββββ€ fed.Listener ββββββββ
β ββ¬βββββββββ¬ββββββββ¬ββ β ββ β βββββββ¬βββββββββ β
βββββ΄ββββ ββββββββ΄ββ ββββββ΄βββββ ββ΄ββββββββ΄β βββ΄β΄βββββ΄β βββββββ΄βββ β
β notes β β shares β β persons β β follows β β outbox β β inbox β β
βββββββββ€ ββββββββββ€ βββββββββββ€ βββββββββββ€ ββββββββββ€ ββββββββββ€ β
βobject β βnote β βactor β βfollower β βactivityβ βactivityβ β
βauthor β βby β β... β βfollowed β βsender β βsender β β
β... β β... β β β β... β β... β β... β β
βββββ¬ββββ βββββ¬βββββ ββββββ¬βββββ ββββββ¬βββ¬ββ ββ¬βββββββ°β ββββββββ¬ββ β
β β β β ββ΄βββββ΄βββββββ ββββββ΄βββββββββ β
β β βββββββββ΄βββββββ ββββΌββ€ fed.Queue βββββββ₯ inbox.Queue β β
β β β fed.Resolver βββ β βββββββββββββ βββ¬ββ¬ββ¬ββββββββ β
β β βββββββββ¬βββββββ βββββββββββββββββββββββ β β β
β βββββββββββββΌββββββββββββββββββββββββββββββββββββ β β
βββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
```Sometimes, a received or newly created local [Activity](https://pkg.go.dev/github.com/dimkr/tootik/ap#Activity) is forwarded to the followers of a local user:
* When a remote user replies in a thread started by a local user, the received [Activity](https://pkg.go.dev/github.com/dimkr/tootik/ap#Activity) is inserted into `outbox` and forwarded to all followers of the local user.
* When a user creates a new post, edits a post or deletes a post in a local community, the [Activity](https://pkg.go.dev/github.com/dimkr/tootik/ap#Activity) is inserted into `outbox` and forwarded to all community members.```
βββββββββββββββββ
ββββββββββββ βββββββββββββββββββ β outbox.Mover β
β gmi.Wrap βββ€ gemini.Listener β β outbox.Poller β
ββββββββββββ ββββββββββ¬βββββββββ β fed.Syncer β
βββββββββ΄ββββββββββββ βββββ¬ββββββ¬ββββββ ββββββββββββββββ
βββββββββββββ€ front.Handler βββββββΌββββββ ββββ€ fed.Listener ββββββββ
β ββ¬βββββββββ¬ββββββββ¬ββ β ββ β βββββββ¬βββββββββ β
βββββ΄ββββ ββββββββ΄ββ ββββββ΄βββββ ββ΄ββββββββ΄β βββ΄β΄βββββ΄β βββββββ΄βββ β
β notes β β shares β β persons β β follows β β outbox β β inbox β β
βββββββββ€ ββββββββββ€ βββββββββββ€ βββββββββββ€ ββββββββββ€ ββββββββββ€ β
βobject β βnote β βactor β βfollower β βactivityβ βactivityβ β
βauthor β βby β β... β βfollowed β βsender β βsender β β
β... β β... β β β β... β β... β β... β β
βββββ¬ββββ βββββ¬βββββ ββββββ¬βββββ ββββββ¬βββ¬ββ ββ¬βββββββ¬β ββββββββ¬ββ β
β β β β ββ΄βββββ΄βββββββ ββββββ΄βββββββββ β
β β βββββββββ΄βββββββ ββββΌββ€ fed.Queue βββββββ€ inbox.Queue β β
β β β fed.Resolver βββ β βββββββββββββ βββ¬ββ¬ββ¬ββ°ββββββ β
β β βββββββββ¬ββ°βββββ βββββββββββββββββββββββ β β β β
β βββββββββββββΌββββββββββββββββββββββββββββββββββββ β β β
βββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββ
```To display details like the user's name and speed up the verification of future incoming replies, [inbox.Queue](https://pkg.go.dev/github.com/dimkr/tootik/inbox#Queue) uses [Resolver](https://pkg.go.dev/github.com/dimkr/tootik/fed#Resolver) to fetch the [Actor](https://pkg.go.dev/github.com/dimkr/tootik/ap#Actor) objects of mentioned users (if needed).
```
ββββββββββββββββββββββββββββββββββββββββ
β βββββββββββββββββ β
ββββββββββββ βββββββββββββββββββ β β outbox.Mover β β
β gmi.Wrap βββ€ gemini.Listener β β β outbox.Poller β β
ββββββββββββ ββββββββββ¬βββββββββ β β fed.Syncer β β
βββββββββ΄βββββββββββΈβ βββββ¬ββββββ¬ββββββ ββββββββββββββββ β
βββββββββββββ€ front.Handler βββββββΌββββββ ββββ€ fed.Listener ββββββββ
β ββ¬βββββββββ¬ββββββββ¬ββ β ββ β βββββββ¬βββββββββ β β
βββββ΄ββββ ββββββββ΄ββ ββββββ΄βββββ ββ΄ββββββββ΄β βββ΄β΄βββββ΄β βββββββ΄βββ ββββββββ»ββ β
β notes β β shares β β persons β β follows β β outbox β β inbox β β feed β β
βββββββββ€ ββββββββββ€ βββββββββββ€ βββββββββββ€ ββββββββββ€ ββββββββββ€ β£βββββββββ« β
βobject β βnote β βactor β βfollower β βactivityβ βactivityβ βfollowerβ β
βauthor β βby β β... β βfollowed β βsender β βsender β βnote β β
β... β β... β β β β... β β... β β... β β... β β
βββ°ββ¬ββββ βββ°ββ¬βββββ ββββ°ββ¬βββββ ββββ°ββ¬βββ¬ββ ββ¬βββββββ¬β ββββββββ¬ββ ββββββββ³ββ β
β β β β βββββββββ β β β ββ΄βββββ΄βββββββ ββββββ΄βββββββββ β β
β β β β β βββββββββ΄βββββββ ββββΌββ€ fed.Queue βββββββ€ inbox.Queue β β β
β β β β β β fed.Resolver ββββ β βββββββββββββ βββ¬ββ¬ββ¬ββ¬ββββββ β β
β β β β β βββββββββ¬ββ¬βββββ β βββββββββββββββββββββββ β β β β β
β β β βββββββββββββΌββΌββββββββββββββββββββββββββββββββββ β β β β
β βββββββββββββββββββββββΌββΌββββββββββββββββββββββββββββββββββββ β β β
β β β βββΌββββββββββββββββββββββββββββββββββββββΌββββββββββββ
βββ»ββββββββββ»ββββ»ββββ βββββββββββββββββββββββββββββββββββββββ β
β inbox.FeedUpdater β£ββββββββββββββββ β
βββββββββββ³ββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```To speed up each user's feed, [inbox.FeedUpdater](https://pkg.go.dev/github.com/dimkr/tootik/inbox#FeedUpdater) periodically appends rows to the `feed` table. This table holds all information that appears in the user's feed: posts written or shared by followed users, author information and more, eliminating the need for `join` queries, slow filtering by post visibility, deduplication and sorting by time when a user views their feed. This table is indexed by user and time, allowing fast querying of a single feed page for a particular user.
## More Documentation
* [Setup guide](SETUP.md)
* [Frontend](front/README.md)
* [Migrations](migrations/README.md)
* [Compatibility](FEDERATION.md)## Credits and Legal Information
tootik is free and unencumbered software released under the terms of the [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0); see LICENSE for the license text.
The ASCII art logo at the top was made using [FIGlet](http://www.figlet.org/).