LOBBY
Internal.
A platform for those who've been let in. Please identify yourself.
Norwegian mobile number
Only numbers on the allow-list can proceed.
Access is by invite. Ask Sivert or Aleksander.
Enter the 6-digit code
Sent to .
Resend · Change number
00Home · Overview

LOBBY.

Sport is the unifier. Lobby uses it to connect people who already live near each other, and then to put real decisions — who we help, where proceeds go, what the rules are — back in their hands.
Matches tonight
14/ Oslo
+3 from last Friday
Registered players
247
internal test cohort
Open proposals
3 / 5 total
2 closing this week
Treasury pot
kr 0
activates at monetization
Codebase
70 files
Rust · Swift · Kotlin
01Manifesto · Why Lobby exists

The
Manifesto.

Lobby is dressed as a sports app. It is not. It is civic infrastructure — a way for communities already in motion to direct the proceeds of that motion, together.

Sport is the unifier.
The rest is democracy.
Pickup football is universal, ritualistic, and weekly. It assembles people who otherwise wouldn't meet. Lobby turns that assembly into a civic muscle: the better you play, the more your community earns, and the people who played decide where it goes. A soup kitchen. A school. A local pitch that needs resurfacing. Direct influence from sport — by the people who showed up.
II

The feed is matches, not people.

No follows, likes, or profile scrolling. Every byte of attention is aimed at the question: are you playing tonight? Social features are toxic in sports apps; we refuse them on purpose.

III

Skill is honest, not optional.

Self-reported skill bootstraps Elo; Elo makes every future match fair. Honesty is rewarded because dishonest ratings break matchmaking fast and visibly.

IV

Distance beats prestige.

A great game 400 m away is ranked above a "featured" one across the city. Lobby favors people who can actually show up, in time, to play.

V

Local honour is the primary currency.

Neighbourhood leaderboards. District championships. Best-in-your-area isn't a badge — it's a public role. Before money flows, reputation does.

VI

The community votes where money goes.

When Lobby generates revenue, the players who generated it propose and vote on how it's spent — kitchens, schools, pitches, coaching programs. No central committee picks.

VII

Football is the first sport. Not the only one.

Everything is architected so basketball, padel, and futsal drop in without rewriting the governance layer. Sport is the shell. The civic logic is the product.

VIII

Trust is the substrate.

Phone-verified accounts (BankID when we're ready). One person, one vote. We'd rather have 247 real neighbours than 24,700 anonymous accounts.

IX

We build slowly, for keeps.

We are not a growth-hacked startup. Lobby is built to last decades, to be boringly reliable, and to earn its users' trust through physical consistency — the match happens on time, every time.

02Manifesto · The Moat

The Moat.

What stops a bigger player from copying Lobby? Three things, in order of strength. They compound — each one makes the next harder to dislodge.

01

Rating integrity.

An Elo system is easy to write and impossibly hard to seed. After a hundred matches in a district, our skill ratings are accurate in a way no newcomer's are. Every match widens the gap. A new competitor starts cold; we start with a year of signal.

Defensibility
02

Local ritual density.

Pickup football is a habit, not a transaction. Once Tuesday 19:30 at Frognerparken runs through Lobby for six weeks, it is Lobby. Migrating a ritual is exponentially harder than switching apps, because you'd have to migrate every player at once. Rituals are the network effect, not user counts.

Defensibility
03

Civic gravity.

The moment Lobby routes a kroner to a real soup kitchen a real player voted on, we stop being an app. We become a thing the community owns. Governments partner with that. Sponsors pay premiums to it. Copycats cannot fake it. Civic legitimacy is the deepest moat there is — and the slowest to build.

Defensibility
CLASSIFIED

Trade secrets.

Share only with people on the access list. These are the mechanics outside competitors can't guess from the product alone — the levers that turn Lobby from "an app we made" into "a system that keeps compounding."

Elo > Stars Users see a 1–10 skill number; internally we use Elo. That gap is intentional — the simple UI gets honest input, and the sophisticated backend does the real work. Never surface Elo directly.
Ritual-first acquisition We don't pay for users. We convert recurring games — whole groups with a standing Tuesday slot. One convinced organiser brings 10–22. Target: pub football, corporate leagues, uni alumni games.
Distance-weighted ranking Formula is public in code, but the coefficients aren't. Skill-weight 0.4, distance-weight 0.6, within a 15 km hard cap. Tuning these for each region unlocks a second-order moat: local density.
Governance as retention Players don't stay for the matchmaking. They stay because they have voting power over real money. Every active voter is worth 5× a passive user in lifetime retention.
Sport-agnostic core The domain layer has no "football" strings. Any 1v1 — 11v11 team sport drops in with a new enum and a skin. Don't advertise this externally until we're ready to move.
Civic partnerships before ads Revenue path is: sponsorships from municipalities and foundations who want to fund community sport anyway. Ads are the last resort, not the first. Keep the ad code out.
A competitor can copy the app in a month. They cannot copy the Tuesday 19:30 habit of 10 guys in Frogner. That's the whole game.
03Product · Design system

Design
system.

The aesthetic is fanzine crossed with constitution: paper, ink, blood, grass. Loud when it matters, quiet when it doesn't. Never generic. Every surface — web, iOS, Android — shares these tokens.

01Colour

Paper#F1EDE4
Paper·2#E8E2D4
Ink#0A0A0A
Blood#C8321E
Grass#1F4D2C
Grass·Br#2E7A42
Mustard#D4A017
Sky#86B8D6

Rule of thirds for accent use: Ink does structure. Paper tones do the surface. Blood is a scalpel — use it for exactly one thing per screen: the action, the warning, the headline. If two things are red, neither is.

02Typography

DisplayBebas Neue
400 / condensed
Tonight's games.
Frognerparken 5v5.
AccentInstrument Serif
italic
A match, not a meeting. Show up on time.
BodyJetBrains Mono
400 / 500 / 700
5 v 5 · SKILL 4–7 · GRASS · 0.4 KM
HOST: Bror Neby H. · KICKOFF 21:10

Bebas does the shouting. Instrument is the human voice in the margins. JetBrains is the data. Never use two display fonts together. Never use monospace for headlines. No exceptions.

03Motion & texture

One looping grain overlay on every surface (radial-gradient dots at 3px, 5% opacity, multiply blend). Animations exist only where they're load-bearing: a pulsing dot for "live," a slow drift behind the solo-queue card, a countdown arc on the timer. No micro-interactions on static elements. If a button doesn't do something, it doesn't shake.

Phone mockups are rotated by 0.3–0.8 degrees, never more. The typewriter-slight-crookedness is the whole point: Lobby is hand-assembled, not stamped.

04Cross-platform tokens

TokenWeb (CSS var)iOS (Swift)Android (Kotlin)
Paper--paperLobbyColor.paperLobbyColors.Paper
Ink--inkLobbyColor.inkLobbyColors.Ink
Blood--bloodLobbyColor.bloodLobbyColors.Blood
Display font'Bebas Neue'LobbyFont.displayBebasNeue
Body font'JetBrains Mono'LobbyFont.monoJetBrainsMono
04Product · Architecture

How it's built.

Three surfaces, one spine. The Rust backend owns all logic. The native clients are dumb renderers — on purpose — so business rules never drift between platforms.

                       ┌────────────────────┐
                       │  CLIENTS (renderers) │
                       └────────────────────┘
     ┌─────────────────────┼─────────────────────┐
     │                     │                     │
  iOS (Swift)          Android (Kotlin)       Web (prototype)
  SwiftUI + Combine     Compose + Ktor        HTML / CSS / JS
     │                     │                     │
     └─────────────┬───────┴─────────────────────┘
                   │    JSON · HTTPS · WebSocket┌───────────────────────┐
           │  RUST BACKEND (axum)   │
           ├───────────────────────┤
           │  domain/               │  ← pure data (Player, Match, Elo)
           │  matchmaking/          │  ← pure fns (rank, form teams)
           │  governance/  (v0.2)   │  ← proposals, votes, treasury
           │  api/          (HTTP) │
           │  realtime/    (WS)    │
           └───────────────────────┘
                   │
                   ▼
           ┌───────────────────────┐
           │ PostgreSQL + PostGIS   │
           │ (ST_DWithin magic)     │
           └───────────────────────┘

aThe pure-logic rule

domain/ and matchmaking/ in the Rust backend have zero framework dependencies. They can be unit-tested without a database, compiled to WebAssembly if we want an offline-first mode, and swapped between HTTP frameworks without touching business logic. This is not optional. Any PR adding axum/sqlx types to these modules gets bounced.

bClients speak JSON. That's it.

The iOS and Android apps mirror the same domain types, generated by hand for now (small surface). When domain/ grows past ~30 types, we auto-generate Swift and Kotlin bindings from the Rust types with uniffi-rs or a custom script. Not before. Premature tooling is the thief of shipping.

cGovernance is a first-class module

The voting system isn't bolted on — it's a governance/ module with the same architectural weight as matchmaking. Proposals, votes, vote-weighting (we'll want "match-hours played in last 30 days" as a weight multiplier), treasury allocation, audit log. All of it pure logic, all of it testable, all of it one HTTP endpoint away from both apps.

05Product · Roadmap

Roadmap.

Four phases. Each one earns the right to the next. We do not skip.

Phase 00 · shipped
Foundation
  • Rust domain + matchmaking
  • REST API + PostGIS schema
  • iOS SwiftUI app
  • Android Compose app
  • Web prototype
  • Internal platform (this)
Phase 01 · now
Real pilot
  • BankID / Vipps login
  • WebSocket live roster
  • Post-match rating → Elo
  • Host-a-match flow
  • 20–50 real players, Oslo
  • Weekly standing-slot invites
Phase 02 · Q3
Civic layer
  • Per-district leaderboards
  • Proposal creation in-app
  • Treasury activation
  • First cause partnership
  • Vipps for split-pay pitches
Phase 03 · 2027
Expansion
  • Second sport (basketball or padel)
  • Regional championships
  • Municipality partnerships
  • Export to second city
  • Sport-agnostic core hardening
06Governance · Proposals & votes

Vote.

This is the working prototype of the civic layer. Same mechanics as what players will eventually see in-app. Your vote is recorded against your verified phone number — one person, one vote.

How this will work in production: Every active player can propose a rule change or allocation. Proposals that cross a quorum threshold (10% of active players in the relevant district) enter a 7-day voting window. Simple majority passes; 60% supermajority is required for treasury allocations over kr 10,000.
07Governance · Treasury

Treasury.

The pot is collectively owned, collectively spent. Activates when Lobby starts generating real revenue in Phase 02. These allocations are from the last closed vote.

kr 0  — idle
Projected Phase 02 pot:
kr 85,000 from first-year pitch-rental split-pays and municipality grants. See Proposal #003 for how the community has provisionally allocated it.
Frogner Soup Kitchen
Direct grant · weekly
40%
Majorstuen Youth Football
Equipment · coaching
25%
Voldsløkka pitch resurfacing
Local infrastructure
20%
Operational reserve
Server · legal · audit
15%

§Treasury principles

1. No hidden balance. The pot is public down to the øre. The backend exposes /treasury/ledger as an append-only log.

2. No discretionary spending. Not by Sivert, not by any founder, not by any employee. Every kroner leaves the pot because a vote passed.

3. Operational reserve is capped at 15%. If we need more, we propose it and the community votes. This keeps us honest.

4. Causes must be verifiable. Every recipient has a Norwegian organisasjonsnummer or a verified community ledger entry. We do not route to individuals.

08Team · Access & roles

Access.

Five roles, ranging from view-only to root. Trust is granular — a new engineer doesn't get Treasury approve rights on day one. Phone number is the identity anchor.

Founder · Lead
Sivert S.
Built it. Owns the vision, the stack, the keys.
root deploy treasury invite
Co-founder · Catalyst
Aleksander Tofting Ferreira
The shove that turned "I've been thinking about this…" into shipped code.
admin invite proposals
Seat · reserved
— open —
Next hire: someone who either writes Rust in their sleep or runs Oslo's amateur football circuit. No third option.
tbd

aRole matrix

RoleCanCannot
rootEverything. Deploy prod, invite anyone, spend emergency reserve.(Nothing. Use carefully.)
adminInvite new internal members, moderate proposals, view all metrics.Deploy prod, spend reserve.
engineerPush to staging, read all code, open PRs.Merge prod, access treasury data.
viewerRead this platform. Read product metrics.Write anything.
playerUse the app. Vote. Propose.See internal platform.

bInvite flow

Adding a new internal member: admin or root adds the phone number to the allow-list. That person receives SMS (later: BankID prompt), picks a role, signs. Their first action is logged. Removal is immediate and invalidates all sessions.