SalastilandClaude Sonnet 5.5 cf5a66cde7 config: let the public port settle the link scheme
`server.https` picked the scheme for every generated link, and it also
decides whether cookies are marked Secure. The two are separate
questions, and a config that said `publicPort = 443` with `https =
false` produced `http://host:443` in every feed `<link>`, `<guid>`, the
OpenSearch template and the unfurl metadata. Nothing serves plain HTTP
on 443, so no such link was ever usable, and nothing warned about it.

Take the scheme from the port when the port is 443 or 80 -- they only
mean one thing -- and from `https` otherwise, so `https://host:8443`
still works. A default port is never appended. The `https` flag keeps
governing cookies, and startup now logs a warning when the port says TLS
and the flag does not, since the cookies are then not Secure.

The logic moves into a small pure function so the combinations can be
tested exhaustively rather than through a loaded config.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-11 21:03:10 -04:00
2026-10-04 21:32:46 -04:00
2026-03-01 22:38:26 -05:00
2026-03-01 22:38:26 -05:00
2026-03-01 22:38:26 -05:00
2026-03-01 22:38:26 -05:00
2026-09-21 18:46:14 -04:00
2026-07-14 20:13:41 -04:00
2026-03-01 22:38:26 -05:00

teapot

A privacy-focused Twitter/X frontend written in Rust.

Features

  • Privacy-focused: No third-party JavaScript, tracking, ads, or remote fonts
  • RSS feeds: Subscribe to any user's tweets
  • FxEmbed-style Discord embeds:
    • Multiple images displayed in carousel on mobile
    • Videos play directly in the embed
    • Proper image dimensions for better layout
    • ActivityPub JSON endpoint for rich embeds

Requirements

  • Rust 1.96.1+
  • Twitter/X session tokens for API access

Building

cargo build --release

Configuration

  1. Copy the example config:
cp config/teapot.example.toml config/teapot.toml
  1. Edit config/teapot.toml with your settings.

  2. Create a sessions file with your Twitter/X credentials:

cp sessions.example.jsonl sessions.jsonl
# Edit sessions.jsonl with your auth_token and ct0 from browser cookies

Cookie sessions use auth_token and ct0. OAuth sessions use oauth_token and oauth_secret. See sessions.example.jsonl for the JSONL shape. Never commit a real session or generated teapot.toml.

Running

# Development
cargo run

# Production
./target/release/teapot

The server will start on http://localhost:8080 by default.

Getting Twitter Sessions

To use the Twitter API, you need session tokens from a logged-in Twitter account:

  1. Log into Twitter/X in your browser
  2. Open Developer Tools (F12) → Application → Cookies
  3. Copy the values of auth_token and ct0
  4. Add them to sessions.jsonl

Project Structure

teapot/
├── src/
│   ├── main.rs          # Entry point
│   ├── config.rs        # Configuration
│   ├── error.rs         # Error types
│   ├── types/           # Data structures (User, Tweet, Timeline, etc.)
│   ├── api/             # Twitter API client, OAuth, parsing
│   ├── cache/           # In-process caching
│   ├── routes/          # HTTP route handlers
│   ├── views/           # Maud HTML templates
│   └── utils/           # Utilities (HMAC, formatters)
├── public/              # Static assets (CSS, JS, fonts)
├── config/              # Configuration files
└── Cargo.toml           # Dependencies

Embed Improvements

This rewrite includes FxEmbed-style improvements for Discord embeds:

Multiple Images

Discord can display all images from a tweet in a carousel. This works via an ActivityPub JSON endpoint at /users/{username}/statuses/{id} that returns media attachments.

Video Playback

Videos can be played directly in Discord embeds using twitter:player meta tags:

  • twitter:player - Embed URL
  • twitter:player:stream - Direct MP4 URL
  • twitter:player:width/height - Dimensions

Image Dimensions

All images include og:image:width and og:image:height meta tags for proper layout.

License

GNU Affero General Public License v3.0

S
Description
No description provided
Readme AGPL-3.0
2.2 MiB
Languages
Rust 83.1%
CSS 12.7%
Nix 3.3%
JavaScript 0.9%