Ikena
2025 - Present
Built a map-based web app for exploring and sharing geographic points of interest. Engineered the backend API with Bun and Hono, featuring multi-resolution image processing, BullMQ job queues, and Cloudflare R2 storage.
About
Ikena started as a simple question: what if discovering interesting places felt as natural as scrolling a feed? The map is the primary interface, not a secondary feature. You open it, you see what’s around you, and you can drop a pin for anything worth remembering. It’s the kind of app I wanted to exist, so I built it.
Architecture
The system follows a clean client-server split. The backend is a Bun-powered Hono API server handling authentication, image processing, and spatial data queries. The frontend is a Remix/React SSR application with an interactive MapLibre GL map as the primary interface.
All image uploads flow through a background processing pipeline: the API accepts the raw upload, queues it via BullMQ, and a worker generates three resolution variants (thumbnail, medium, full) using Sharp before pushing them to Cloudflare R2. This keeps the upload endpoint fast while ensuring optimized images are served to clients.
The database layer uses Supabase (PostgreSQL) with PostGIS extensions for efficient spatial queries. Redis handles both the job queue backing store and response caching for frequently accessed map tiles.
The entire stack is deployed on a Hetzner VPS managed through Coolify, with Docker Compose orchestrating the API, Redis, BullMQ worker, and frontend containers. Uptime monitoring and log aggregation keep everything observable in production.
My Role
I built the entire backend from architecture to deployment, the map interaction layer, data fetching, and components on the frontend, and the full infrastructure: provisioning the Hetzner VPS, configuring Coolify, domains, SSL, the Docker Compose stack, CI/CD, and monitoring.
What I Learned
This project pushed me to think carefully about async processing patterns, specifically how to design APIs that acknowledge work without blocking on it. The BullMQ pipeline was my first production job queue, and getting the retry/dead-letter logic right taught me a lot about resilience in distributed systems.
Working with geospatial data at scale also changed how I think about database indexing. A naive SELECT * WHERE ST_DWithin(...) on unindexed geometry columns was a 3-second query. After adding GiST indexes and tuning the query planner, it dropped to under 50ms.
On the DevOps side, this was the project where I learned to own the full deployment pipeline. Setting up Coolify on a raw VPS, wiring up Docker Compose for multi-container orchestration, configuring reverse proxies, SSL, and CI/CD from scratch gave me a much deeper understanding of what happens between git push and a live production URL.