Why the Community Needed Its Own Platform
The Ukrainian diaspora in Spain was growing fast, but community infrastructure hadn't kept up. Information lived in fragmented, unmoderated channels that couldn't scale.
Scattered Information
Businesses, events, housing, and job listings were scattered across Facebook groups, Telegram chats, and word of mouth. Finding reliable, up-to-date information meant scrolling through endless feeds with no search, no filters, and no structure.
No Quality Control
Without moderation, listings were full of spam, outdated content, and unverified businesses. There was no way to report bad actors, verify legitimacy, or ensure that posted information was still accurate.
Language Barrier
The community needed a platform that works natively in both Ukrainian and Spanish - not just translated labels, but fully localized UX including content, validation messages, date formats, and culturally appropriate flows.
Manual Data Decay
All information was entered manually and quickly became outdated. Business hours changed, events passed, housing got rented - but listings stayed up indefinitely. No automated enrichment, no expiration, no cleanup.
How Data Gets In Without a Content Team
The platform launched with 200+ businesses and 80+ events on day one. No content team, no manual data entry. Here is how each data pipeline works and how the platform maintains quality over time.
Business Discovery
Google Places API finds and enriches businesses automatically
Google Places Text Search runs queries across all Spanish cities, looking for Ukrainian-relevant businesses
Three-layer relevance filtering: Cyrillic in name, .ua domains in website, Ukrainian-language Google reviews
Matched businesses get auto-enriched: coordinates, working hours, photos, Google rating, and reviews
Combined trust score merges portal reviews + Google reviews so users see one reliable rating
Result: 200+ businesses on the platform from day one - no manual data entry, no empty directory
Eight Verticals, Each With Its Own Data Strategy
Some verticals are auto-discovered via APIs, some are aggregated from public sources, some grow organically through user submissions. One architecture serves all of them.
Business Directory
Google Places APIAuto-discovered, enriched with hours/photos/ratings, owner verification with document upload
Community Events
Public aggregationSourced from ticketing platforms and community channels, geocoded for map view, auto-archived on expiry
Job Board
Community channelsCurated from community sources, employer verified via Google Places, 90-day auto-expiration
Housing Board
User submissionsRent, share, short-term, sale - moderated listings with auto-expiration and map search
Classifieds
User submissions16 categories for buying, selling, and giving away items within the community
Shipping Directory
Pre-populated + enriched31 ES-UA delivery services with Google Places verification and four delivery modes
Community Meetups
Seeded + user-drivenRecurring meetups with auto-approval for low friction, rrule-based scheduling
Resume Board
User submissionsPDF upload to Vercel Blob, professional categories, cross-linked with job board
Key Architectural Decisions
Every major design choice had a context, alternatives, and specific reasoning. Here's what was chosen and why.
Self-populating content pipeline
A community platform is only useful when it has content. Waiting for users to manually submit and fill out every field means the platform launches empty and stays empty.
Batch CLI pipeline: discover → import → enrich → validate. Google Places Text Search finds businesses by city, filters by relevance, and populates listings automatically.
Seed manually, rely on organic user submissions.
One pipeline run populates an entire city with verified data. The platform launched with 200+ enriched businesses on day one, not an empty directory waiting for submissions.
Cold start problem solved. Every business gets coordinates, photos, hours, and ratings before a single user signs up.
Two apps, one database, zero sync
The platform needs a public portal optimized for end users and an internal admin panel optimized for data-heavy moderation workflows. Different audiences, different UX requirements.
Two independent Next.js apps sharing PostgreSQL via identical Prisma schema. Portal uses shadcn/ui. Admin uses MUI + DataGrid. Separate auth, separate deployments.
Single app with role-based route protection and shared UI framework.
Admin deploys independently without risking the public site. UI framework matches the use case: shadcn for consumer UX, MUI for admin data tables. No bundle penalty for end users.
Both apps operate on live data with zero sync. Each ships on its own cycle. Admin outages never affect the public portal.
Three-strategy Google Places matching
Matching user-submitted business data to Google Places is unreliable. Names are spelled differently, addresses are incomplete, phone formats vary between countries.
Cascading search: phone number first (most unique), then name+address, then address-only. Results filtered by Haversine distance (2km radius) and Dice coefficient fuzzy name matching.
Single-strategy search with manual fallback for mismatches.
Phone-first catches most matches instantly. Fuzzy name matching handles transliteration differences (Cyrillic/Latin). The cascade maximizes match rate without false positives.
Matched businesses get coordinates, photos, hours, and ratings automatically. Combined portal + Google review scores give users trustworthy signals from day one.
What's Next
The platform runs itself today. These features will push automation further - from AI-powered moderation to self-marketing and intelligent search.
AI Content Moderation
LLM pre-screens every listing against the 8-point quality checklist before human review. Flags spam, low-quality descriptions, and miscategorized content automatically - reducing moderator workload to edge cases only.
AI-Powered Event Discovery
LLM analyzes raw web pages from ticketing platforms to extract structured event data - dates, venues, prices - without brittle scraping. Falls back gracefully when page structure changes, replacing manual source maintenance entirely.
Semantic Search Across All Verticals
Natural language queries like "Ukrainian hairdresser near Valencia" search across businesses, events, jobs, and housing simultaneously. Powered by embeddings and vector similarity - not just keyword matching.
What AI-Driven Delivery Looks Like
AI operates at every level: discovering content, building features, testing quality, and maintaining the platform. Here is what one developer with AI delivers compared to a traditional team setup.
Launched With Content, Not Empty
- ✓200+ businesses discovered and enriched via Google Places before the first user signed up
- ✓100+ events found via AI-powered search across 20+ ticketing platforms
- ✓31 shipping services pre-populated and verified for the ES-UA corridor
- ✓One CLI command populates a new city with enriched, verified data
Runs Itself After Launch
- ✓Cron-driven lifecycle: expired content auto-archives, orphaned files auto-clean, digests auto-send
- ✓Social media content generated from platform data and published automatically — no content team
- ✓8-point moderation checklist with full audit trail for every decision
- ✓Sentry monitoring + Vercel Analytics in production from day one
Built and Maintained Solo
- ✓Two independent apps (portal + admin) with separate deployments and UI frameworks
- ✓Unified entity pattern: adding a new content vertical follows the same proven structure
- ✓Polymorphic moderation system serves all 8 entity types from single tables
- ✓Full delivery: architecture, data pipelines, moderation, testing, production - one developer
Interested in building something similar?