Skip to main content

Inbloom API Documentation

Welcome to the Inbloom API docs. Inbloom is an event-based social/dating platform: users create events, invite friends as co-authors, and approve groups of interested participants. Dating happens through joining events together, not through 1:1 swiping.

Core concept

Users create events → Friends invited as authors → Users form like groups →
Authors approve groups → Approved group gets private chat → Dating happens through events

Architecture

The API is a thin Hono server on Bun that talks to a Supabase project for auth and storage. We deliberately reuse Supabase's production-grade building blocks (GoTrue, PostgREST, Realtime, Storage) instead of reimplementing them.

LayerTechnology
RuntimeBun
HTTP frameworkHono
ValidationZod
AuthSupabase Auth (GoTrue) — JWT verified server-side
DatabaseSupabase Postgres (accessed via Drizzle ORM)
Realtime (planned)Supabase Realtime channels
Storage (planned)Supabase Storage
Loggingpino
Lint/formatBiome

Why this stack

  • Simplicity over micro-services. One Hono app, one Postgres, one Supabase project. No Redis, no BullMQ, no separate WebSocket server, no S3/Minio cluster.
  • Reuse battle-tested pieces. Auth, file storage, realtime fan-out and row-level security all come from Supabase. We don't write them.
  • Type safety end-to-end. Zod for request validation, Drizzle for query types, Supabase JS for auth response types.

Repository layout

api/
├── src/
│ ├── main.ts # Bun.serve entrypoint
│ ├── core/ # config, logger, server, middleware
│ ├── feats/ # feature modules (e.g. profiles/)
│ ├── infra/ # db (drizzle) + supabase clients
│ ├── libs/ # shared utilities (errors, etc.)
│ └── ts/ # ambient TS declarations
└── drizzle/ # generated migrations

Each feature under src/feats/<name>/ is self-contained: <name>.router.ts, <name>.service.ts, <name>.schemas.ts, <name>.constants.ts.

Status

This is an early-stage codebase. The Profile module is shipped; the rest of the surface described in this wiki is planned and tagged as such.

ModuleStatus
Auth (via Supabase)✅ Shipped
Profile (/profiles)✅ Shipped
Reference data (lookups + languages)✅ Shipped
Friends🚧 Planned
Events🚧 Planned
Like groups + approval🚧 Planned
Chat🚧 Planned
Notifications🚧 Planned
Moderation🚧 Planned

User roles

Roles are application-level, encoded as JWT claims (not Postgres roles).

RolePermissions
UserCreate events, like events, chat, send friend requests
ModeratorSoft-delete events/messages, ban users, remove groups
AdminAll moderator + restore content

Authentication contract

All non-auth endpoints require a Supabase-issued JWT:

Authorization: Bearer <supabase-access-token>

The API verifies the token via supabase.auth.getUser(token) and attaches the resolved user to the request context (see src/core/middleware/auth.middleware.ts). See the Auth doc for the full client flow.

Pagination (planned)

Cursor-based pagination is the planned standard for list endpoints:

?cursor=xxxxx&limit=20
{
"data": [...],
"nextCursor": "encoded-cursor-or-null"
}

Realtime (planned)

Real-time updates use Supabase Realtime channels rather than a custom WebSocket server. Clients subscribe via @supabase/supabase-js:

ChannelEvents
chat:{chatId}message.created, message.updated, message.deleted
group:{groupId}group.approved, group.updated
event:{eventId}event.updated

The two patterns we'll mix:

  • Postgres changes — automatic events from row INSERT/UPDATE/DELETE, filtered by RLS so users only get rows they can read.
  • Broadcast — server-emitted ephemeral events for things that aren't rows (typing indicators, presence-style ticks).

Rate limits (planned)

Endpoint groupLimit
Auth (Supabase-side)Per Supabase plan
Event creation10 req/min
General API60 req/min

Support