Ulula.
Hospitality SaaS
I designed and built all of Ulula from zero: the SaaS web app, the four mobile apps around it, the shared library and the multi-provider payments integration. Today it's in production, with active customers and verified VeriFactu e-invoicing.

The problem
Hospitality in Spain faces a perfect storm: a law on the way, commissions that choke margins, and tools that don't talk to each other.
E-invoicing becomes mandatory, with fines up to €150,000. Most businesses don't even know it exists.
Meanwhile the day-to-day runs on a PDF menu, paper tickets and WhatsApp bookings. Every disconnected tool is one more point of failure.
The thesis
Seven tools in one. If orders, payments, kitchen, bookings, events, delivery and invoicing live in one place and in real time, the copy-paste errors between systems disappear. That was the bet.
The solution
Ulula is an all-in-one platform for restaurants, shops, services and events: a no-install web app plus a six-app ecosystem. The business charges through its own gateway —0% commission— and is live in five minutes. I designed and built it end to end.

The suite
Six apps from a single React Native + Expo codebase. Each solves one side of the business; all share the same backend.
uQRCheck-in
uKDSKitchen
uBookingBookings





Real-time orders
The customer scans the table QR and orders from their phone; it goes straight to the kitchen. Dine-in, delivery or pickup, with statuses from received to delivered and urgent-order alerts. What you charge is what gets prepared.
// Del TPV a la cocina, en tiempo real
supabase
.channel('orders')
.on('postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'orders' },
({ new: order }) => kds.enqueue(order))
.subscribe()
Point of sale
Web POS + native app with cash sessions: opening, closing count and automatic discrepancy detection. Multi-cashier, tips, X/Z reports, and offline mode with a local queue that syncs on reconnect.









Events, bookings and QR menu
Events with capacity and ticketing, QR check-in (uQR) and bookings with menu selection. Services with a calendar and Google Calendar sync. A digital menu per table, multi-language and real-time, with reminders to cut no-shows.

Everything inside
- ✓Public business profile
- ✓Digital menu with QR per table
- ✓Dine-in, delivery and pickup orders
- ✓Own delivery with map zones
- ✓Kitchen Display System
- ✓Events, ticketing and check-in
- ✓Services and appointment booking
- ✓Table management and coupons
- ✓Point of sale with cash reconciliation
- ✓Per-business blog and followers
Integrations
- ✓Payments: Stripe Connect, Redsys, PayPal, Square, TropiPay, RalioPay
- ✓Google Maps, Places and Calendar
- ✓WhatsApp for order statuses
- ✓VeriFactu e-invoicing
- ✓Multi-currency and multi-tenant
Engineering challenges solved
Building this solo meant solving production problems, not tutorial ones.
Gateways forbid asking for a business's keys. I moved charging to Stripe Connect / OAuth: each business connects its account, Ulula never stores their secrets and money goes straight to them. Compliance by design.
Six apps from one codebase force clean per-variant separation: each with its bundle id and GoogleService-Info. Using the wrong plist silently breaks push and analytics.
// Cada variante con su propio Firebase plist
function plistFor(variant) {
if (variant === 'consumer') return './GoogleService-Info.plist'
const p = `./GoogleService-Info-${variant}.plist`
return exists(p) ? p : fallback() // si no, [I-COR000008] y push roto
}The POS can't go down if WiFi drops on a Friday at 10pm: sales queue locally and sync on reconnect, with no duplicates.
The stack
I've been building product daily for 4+ years. Ulula is a monorepo: web on Next.js 15 + React 19, mobile on Expo / React Native, and a Supabase backend with 50+ Edge Functions (Deno), 120+ migrations and Realtime. TypeScript end to end.
// 6 apps desde un solo codebase (Expo)
const APP_VARIANTS = {
consumer: { name: 'ululando', bundleId: 'com.seracreativo.ululando' },
provider: { name: 'uBusiness', bundleId: 'com.seracreativo.ululando.business' },
tpv: { name: 'uTPV', bundleId: 'com.seracreativo.ululando.tpv' },
checkin: { name: 'uQR' }, kds: { name: 'uKDS' }, booking: { name: 'uBooking' },
}
// APP_VARIANT=tpv eas build → otra app, el mismo códigoThe model
Four plans, from free to enterprise. A business starts free and scales when it needs to.
Ambassadors program
Ulula Ambassadors: for every business that joins with your code you earn 20% recurring commission for 12 months, and the business gets 20% off for the first 6 months. Sign up with Google + Stripe, pick your code, get paid on the 15th. Global, via Stripe Connect.

2026 Roadmap
Bootstrapping and product-led growth, neighborhood by neighborhood, toward default alive.
- Q1Ground Zero
10 evangelist businesses, 0% churn, manual onboarding and a polished happy path.
- Q2Viral engine
Activate the B2B2C loop: foot traffic becomes ululando users. Target: 1,000 active.
- Q3Pro value
uKDS in the kitchen, profitability reports and the VeriFactu lever. Target: 30% to paid plans.
- Q4Automation and scale
Self-onboarding (menu photo → AI → catalog) and positive cashflow.
Result
Ulula is in production with active clients, on the App Store and Google Play. Design, code and publishing, end to end, by me.
If it doesn't scale with one founder, it doesn't scale: ship small and daily, an audit ledger instead of silent fixes, and RLS from day one.
Ulula