The problem
Small service businesses -- think a pottery workshop in Lyon or a freelance consultant in Paris -- do not have the same tools as a SaaS company or a medical practice. Most booking solutions either give you a bare-bones scheduling link, like Calendly, or a bloated all-in-one platform built for enterprise teams. What these businesses actually need is something in between: a personalized booking website, a way to manage customers, integrated payments, and automated reminders, without stitching together five different services.
That is the gap Atoly fills. Not just a booking link, but a full web presence for each business, with a dashboard that handles the day-to-day operations of running a service-based business.
What I built
Atoly is an all-in-one scheduling and business-management platform. Each business that signs up gets a public-facing booking website, not just a link, a back-office dashboard for managing events, customers, and orders, and a mobile app for managing things on the go. Under the hood, the platform connects to Google Calendar, Microsoft Outlook, Stripe, and sends transactional emails and SMS automatically.
The scope was significant. I shipped five distinct applications from a single codebase: the main web app, the public-facing booking pages, a React Native mobile app, a marketing website, and an admin tool. All of them share business logic through a monorepo with 18 internal packages.
Architecture decisions that mattered
Early on, I made a few architectural bets that shaped everything downstream. The first was multi-tenancy with true database isolation. Rather than a shared database with tenant columns, the easier path, each organization gets its own SQLite database, synced to the cloud via Turso. This means zero risk of cross-tenant data leaks and the ability to scale each tenant independently. A central platform database handles users, organizations, and memberships.
The second decision was to go domain-driven from day one. The codebase is organized into bounded contexts -- @atoly/booking, @atoly/sales, @atoly/notifications, @atoly/organization -- each with its own entities, repositories, and use cases. This kept the code navigable even as features piled on, and made it possible for different parts of the system to evolve independently.
# Monorepo structure
apps/
atoly-webapp # Full-stack web app (React Router + Hono)
atoly-mobile # React Native + Expo
atoly-frontends # Public booking pages
marketing # atoly.co
packages/
@atoly/core # Domain models, value objects
@atoly/booking # Scheduling engine
@atoly/sales # Payments, orders, pricing
@atoly/notifications # Email and SMS pipelines
@atoly/infrastructure # DB, API layer, repositories
@atoly/ui # Shared component library
# ...and 12 moreThe third was choosing event-driven workflows via Inngest for anything asynchronous. When a booking is created, a domain event fires. That event triggers confirmation emails, calendar syncs, payment captures, and analytics tracking, all as separate, retryable steps. This kept the core booking logic clean and made the notification and integration layer easy to extend without touching the scheduling engine.
The tech stack
I chose every tool deliberately, optimizing for type safety, developer speed, and long-term maintainability.
Frontend
React 19, React Router 7, Tailwind CSS 4, Radix UI, Jotai for state, React Hook Form plus Zod for forms, and Vite 7.
Backend
Node.js 22, Hono, Drizzle ORM, TypeScript end to end, and Neverthrow for error handling.
Database
SQLite plus Turso with embedded replicas, Drizzle Kit for migrations, and a dual-database architecture.
Mobile
React Native with Expo 54, Expo Router, TanStack Query, and shared domain packages from the monorepo.
Integrations
Stripe Connect, Google Calendar API, Microsoft Graph, Resend for email, Twilio for SMS, and Giftup for gift cards.
Infrastructure
Fly.io, Docker, Turborepo, Sentry, GrowthBook for feature flags, PostHog for analytics, and Playwright for end-to-end tests.
Why Hono over Express or Fastify?
Hono is lightweight, runs anywhere, from workers to Node to the edge, and starts almost instantly. For a platform that needed both server-rendered pages and API routes in the same process, it was the right fit: fast to develop with and fast at runtime.
Key challenges I solved
Calendar sync is deceptively hard. Google Calendar and Microsoft Outlook have very different APIs, webhook models, and reliability characteristics. Google uses push notifications that expire and need renewal. Outlook uses subscriptions with their own lifecycle. I built a @atoly/external-calendars package that abstracts both behind a unified interface, handles webhook renewal automatically, and deals with the edge cases: deleted events, timezone mismatches, and all-day events that span midnight differently depending on the provider.
Payments in a marketplace model. Atoly uses Stripe Connect so that each business receives payments directly into its own Stripe account while the platform takes a fee. This means handling onboarding flows, account verification, webhook events for payment intents, refunds, and subscription billing, all with proper error handling and retry logic through Inngest workflows.
Sharing code across web and mobile without compromise. The monorepo architecture lets the web app and mobile app share domain logic, validation schemas, and type definitions through internal packages. But I was careful not to leak web-specific code into mobile or vice versa. The @atoly/core package contains only pure TypeScript: no React imports and no Node APIs, so it runs everywhere.
What I shipped
The result is a production SaaS with real users, handling real bookings and processing real payments. The numbers tell part of the story: 1,500+ commits, 18 workspace packages, 15+ third-party integrations, and 5 applications shipped from a single monorepo. What matters more is that I went from an empty repository to a live, multi-tenant platform, with a mobile app, while maintaining clean architecture and comprehensive test coverage with Vitest for unit and integration work and Playwright for end-to-end coverage.
The platform supports internationalization in English and French, works as a Progressive Web App, uses feature flags for controlled rollouts, and has full observability through Sentry error tracking and PostHog analytics.
Atoly demonstrates what one developer working solo can ship when the architecture is right from the start. No rewrites, no tech-debt bailouts, just steady, iterative delivery from day one.
What this means for your project
Building Atoly required the kind of decisions that come up in every serious software project: how to structure a growing codebase, how to isolate tenant data, how to integrate with flaky third-party APIs, and how to share code across platforms without creating a mess. These are not theoretical problems for me. They are challenges I have solved in production.
If you are thinking about building a SaaS product, a booking platform, or any application that needs multi-tenancy, payment processing, or cross-platform delivery, I have done it before and I can do it for you.
