I built a dating app that runs in your terminal and it's backend-less

Published: (March 27, 2026 at 04:10 AM EDT)
6 min read
Source: Dev.to

Source: Dev.to

Overview

Every developer I know loves working in the terminal, and they’re some of the nicest people around.
In Vietnam the news constantly runs stories about our declining population, and the solution most people reach for is Tinder, Bumble, or FB Dating – the first two charge you money for the privilege of being their product.

The CLI trend is obvious – it makes integrating LLM/AI a breeze. I love CLI tools: they’re lightweight, smooth and look slick.

So, why not combine all the ideas above and build a proper dating app for our beloved software developers that runs in their terminal?

Will it amount to anything? I don’t know. But the engineer spirit is that nothing is for sure – we just have to give it a try.

First Constraint: Near‑Zero Budget

  • No VPS, no managed database, no monthly bill.
  • A matching platform still needs a backend and a database – somewhere to store profiles, run validation, process matches.
  • The expense should be minimal; the wars are out there and gas prices keep skyrocketing.

I spent a while thinking about what services in the market could fill those roles, and eventually it hit me: GitHub gives you all of it for free.

GitHub primitiveWhat it can replace
RepositoryStorage
GitHub ActionsEvent‑driven compute (like AWS Lambda)
Issues (with labels)API endpoints / routes
Releases (assets)CDN / static assets

When I mapped the architecture onto GitHub’s primitives, it looked absurd but plausible:

  • Registration → an Issue or a PR
  • Profile validation & encryption → a GitHub Action
  • Discovery index → a Release asset

Since a dating/matching app isn’t real‑time, sub‑millisecond latency isn’t required.

Decentralised Discovery

The most fundamental feature of a dating app is Discovery. Normally this requires a centralized DB and backend.

What if we let each user download the database to their machine and run ranking/matching locally?

The dilemma

  1. Privacy – profiles must not be exposed freely.
  2. Discovery can’t work with encrypted data.
  3. If the DB is downloadable, anyone could scrape the whole thing in seconds.

Traditional apps rely on a private server, private DB, private ranking engine, and API rate‑limiting to prevent bulk extraction. We want to avoid a centralized server altogether – that’s the fun part.

Chain‑Encryption (Verifiable Delay Function)

I explored verifiable delay functions and proof‑of‑work schemes and settled on a design I call chain‑encryption:

  • Imagine a chain of locked boxes, each containing a profile and a hint to open the next box.
  • Opening a box requires a few seconds of brute‑force computation with no shortcuts.
  • A legitimate user sees one profile every few seconds – human speed.
  • An attacker is stuck at the exact same pace; there is no “premium tier” to bypass the limit because the cost is baked into the math.

A caching mechanism can make repeated encounters near‑instant, rewarding normal usage and punishing bulk extraction.

How it works

  • Lock‑combination = AES encryption.
  • Every user gets three separate hashes for registration, discovery, and chat, linked by a secret salt that lives only in the pool’s GitHub Actions secrets.
  • Without the salt, the namespaces are completely unlinkable – browsing profiles reveals nothing about GitHub usernames, and chat partners can’t find each other in the index.
id_hash    = sha256(pool:provider:user_id)          # 64 hex chars
bin_hash   = sha256(salt:id_hash)[:16]              # 16 hex chars → .bin filename
match_hash = sha256(salt:bin_hash)[:16]             # 16 hex chars → chat handle

End‑to‑End Encrypted Chat Relay

The chat relay extends the privacy guarantees:

  • Messages are encrypted before leaving your machine.
  • Authentication is a stateless time‑based signature plus a Merkle‑like verification.
  • The relay only routes ciphertext it cannot read.
  • Compromise the server → you only get encrypted blobs; there’s nothing to steal.

Tooling & Stack

A single binary, no app store, no web hosting, two commands:

brew install vutran1710/tap/op
op

The TUI handles onboarding, discovery, and chat with a proper dark‑themed interface.

  • Language: Go
  • UI framework: Bubble Tea + Lip Gloss (deserves far more attention than it gets)

Architecture diagram

┌──────────┐       ┌──────────────────┐       ┌─────────────┐
│  CLI/TUI │──────▶│  Pool Repo       │       │  Registry   │
│  (Go)    │       │  (GitHub)        │◀─────▶│  (GitHub)   │
│          │       │  pool.yaml       │       └─────────────┘
│          │       │  users/{h}.bin   │
│          │       │  matches/        │
│          │       └──────────────────┘
│          │              ▲
│          │──────▶┌───────┴───────────┐
│          │       │  Relay Server    │
└──────────┘       │  (per‑pool)      │
                   └──────────────────┘

Relay Server – The Only Backend Cost

Eventually a relay is unavoidable, meaning the system isn’t 100 % backend‑less in the traditional sense. However, it’s still minimal:

  • GitHub acts as the database.
  • GitHub Actions act as the main backend (validation, encryption, indexing).
  • The relay server is the only component that someone has to pay for – it’s a dumb, stateless message‑routing service.

By the nature of Go, the relay can be tiny, cheap to host, and horizontally scalable if needed.

Closing Thoughts

The engineer spirit is to try, even when the odds are unclear. By leveraging free GitHub primitives, a verifiable‑delay chain‑encryption scheme, and a minimal Go‑based relay, we can build a terminal‑first dating app that respects privacy, stays virtually cost‑free, and gives developers a fun, CLI‑centric way to meet each other.

Give it a spin, hack on it, and let the community decide whether this absurd idea can become a useful tool. Happy coding!

Overview

It can handle the load pretty well & inexpensively—until the pool operator realizes he can actually monetize his own pool.

The “grinding” delay during discovery actually makes browsing deliberate; you can’t mindlessly swipe when each profile costs a few seconds.

Finally, the matching engine turned out to be general‑purpose by accident: the schema is just YAML, so anyone could fork the template and run a job board, study‑group finder, or freelancer marketplace with zero code changes.

Configuration

name: "

Tags

#go #golang #opensource #cli #terminal #cryptography #decentralized #privacy #sideproject

0 views
Back to Blog

Related posts

Read more »