
Woojik
ShiftWorkMatchingPlatform
Designing and building a time-based matching engine for Korea's shift work economy
Role
Design · Engineering
Duration
1.5 Weeks
Platform
Web · Marketplace
Team
Solo — Design & Engineering
Users
Part-time workers, local businesses in Seoul
I designed and engineered the complete product — dual-role UX flows, matching algorithm, calendar system, map exploration, and booking state machine. Built with AI as my pair programmer.
Overview
Outcome Snapshot
What shipped, why it mattered, and how impact was measured.
Woojik (우직) is a shift work matching platform I designed and engineered end-to-end. Workers input their available time slots, businesses post staffing needs, and a matching engine connects them by time overlap, role, and location. Think calendar-based matching — not job boards.
Korea's part-time work market is massive but coordination is still manual. Workers post availability on community boards, businesses call candidates one by one, and scheduling conflicts emerge after verbal agreements. The core inefficiency: time matching happens in people's heads, not in software.
88
Tests passing
2
Complete user flows
E2E
Design & Engineering
Challenge
Scheduling Shift Work is Still Manual
In Korea's part-time work market, matching is done by phone. A café owner posts on a community board, gets 20 messages, calls each person to check availability, discovers half can't work the needed hours, and starts over. Workers face the inverse: they're available Tuesday and Thursday afternoons, but have no way to discover which businesses need those exact hours.
Both sides waste hours on coordination that doesn't convert. The fundamental problem is that time matching — the most critical variable in shift work — has no dedicated tool.
- Manual Coordination — Phone calls and messages to check availability, one candidate at a time
- Time Blindness — No tool lets workers say 'I'm free these hours' and instantly see matching shifts
- Two-Way Mismatch — Businesses can't see who's available when; workers can't see who needs them when
Solution
Calendar-Based Matching Engine
I designed a matching system around the natural unit of shift work: time slots. Workers draw availability on a visual calendar. Businesses post demand slots with roles, headcount, and wages. The matching engine scores every worker-demand pair by time overlap — overlap_minutes / 480, capped at 1.0 — surfacing the best matches for both sides.
- Drag-to-select calendar for intuitive availability input with week and month views
- Automatic matching engine with overlap scoring algorithm
- Two-way acceptance flow — OFFERED, ACCEPTED, CONFIRMED — with expiration handling
- Map-based exploration with desktop split view and mobile bottom sheet
- Role-based routing — completely separate Worker and Business UX flows
- Weekly shift recommendations combining 2–3 optimal shift options with earnings estimates
Architecture
Role-Separated Architecture
The architecture mirrors the two-sided UX: separate route trees for workers (/worker/*) and businesses (/business/*), shared components for common patterns, and Context-based state management for slots and bookings.
- Next.js 16 (App Router) with TypeScript and Tailwind CSS 4
- Supabase for auth, database, and row-level security
- MapLibre GL JS for open-source map exploration with Carto Positron tiles
- Context API for global state — SlotContext, BookingContext, AuthContext
- Vitest + Testing Library for 88 tests covering core matching and booking flows
- Booking state machine with automatic expiration handling via useExpiryCheck hook
Result
MVP Complete — Two Full User Flows
Both worker and business flows are complete and tested. The matching engine pairs availability with demand, the booking state machine handles the full lifecycle, and the map exploration lets workers discover nearby opportunities.
88
Tests passing
2
Complete role flows
5
Core features shipped
Live
woojik.vercel.app
Reflection
Key Learnings
01
Time is the Natural Matching Unit
I tried location-first and role-first matching before landing on time slots. Time overlap turned out to be the strongest predictor of a successful shift match — workers will travel for the right hours.
02
Two UX Flows, One Shared Truth
Workers and businesses see completely different interfaces operating on the same data. Designing the shared data model first, then deriving both UX flows from it, prevented countless sync issues.
03
Maps Need Boundaries
Unbounded map exploration caused performance issues and irrelevant results. 'Search This Area' — updating results only on explicit user action — solved both problems with one small UX decision.
Next Project