Flying clubs and FBOs (fixed-base operators) still run on dated software like MyFBO. Azimuth is a modern replacement covering the full operational core: members and their pilot credentials, the aircraft fleet and its maintenance, scheduling and dispatch, flight logging, and member billing. The whole loop is where a reservation becomes a checked-out aircraft, becomes a logged flight, becomes a posted charge on a member's ledger. It's built multi-tenant from day one (every domain table is org-scoped, so adding a second club needs no schema change) and access is capability-based, not role-based. As Heurix Corp's three-person team, we built it end to end (schema, server actions, auth, RBAC, and UI), won a competitive evaluation against the incumbent vendors, and migrated the client off their legacy system. Azimuth is live in production today, running daily operations for a roster of roughly 1,500 members.
What it's built with.
Application
- Next.js 16 (App Router)
- React 19 Server Actions
- TypeScript
- Tailwind CSS v4
Data & Auth
- PostgreSQL
- Drizzle ORM (migrations)
- Auth.js v5 (JWT)
- Multi-Tenant org scoping
Domain & Ops
- Capability-Based RBAC
- Scheduling & Conflict Detection
- Maintenance / Currency Tracking
- Vercel Cron Automation
How it works.
The operational loop
Running a flying club is a chain of dependent events, and the value of the software is in keeping that chain consistent. A member books a reservation; a dispatcher checks the aircraft out to them; the flight is flown and logged, which advances the Hobbs and Tach meters; logging the flight auto-posts the rental and instruction charges to the member's ledger and closes the reservation. Azimuth models that whole loop as connected modules rather than disconnected CRUD screens.
The maintenance side runs in parallel: each aircraft tracks inspection due-points (annual, 100-hour, etc.) against its current Hobbs/Tach, and an aircraft that goes out of currency or picks up a grounding squawk is automatically removed from the dispatchable fleet, so the scheduling module can't book a plane that shouldn't fly.
Multi-tenant and capability-based from day one
Even though it serves a single organization in production today, Azimuth is built multi-tenant from the schema up. A user is a global identity (one login), and a membership joins that user to an organization with a role; all club data references a membership, not a user, and every domain table carries an org_id that scopes every query. Adding a second club later is an org switcher that re-issues the session token, no schema migration.
Authorization is capability-based, not role-based. Roles (admin, dispatcher, instructor, member, student, mechanic) are just bundles of 89 fine-grained capabilities, and every server action and UI affordance checks the capability, dispatch:write, maintenance:manage, schedule:manage_others, rather than testing the role directly. That keeps permission logic in one place and makes it safe to add a new role or re-scope an existing one without hunting through the codebase.
Modern stack, real automation
Azimuth is built on Next.js 16 with React 19 Server Components and Server Actions as the primary data path, Auth.js v5 for credentials auth with edge-safe middleware, and a Drizzle/Postgres backend with a versioned migration history (245 and counting). It deploys to Vercel against hosted Postgres (Supabase / Neon), with TLS auto-enabled.
Beyond request/response it runs real operational automation, and the part worth saying out loud is what it holds: a flying club’s records include pilot medical certificates, licences and endorsements, which are health and identity documents about real people. Those are treated as a separate, higher-sensitivity class from everyday profile data, reachable only by the roles whose work requires them, and never served from the same path as public assets. Scheduled jobs authenticate and fail closed rather than open. The specifics of how that is implemented are intentionally not on this site — publishing them would only ever help someone attacking a system real members depend on.
The things I'm proudest of.
- ▹Won the account against established competitors in the space: Heurix presented a one-hour walkthrough and live demo to the client's board of directors and came away with unanimous approval to replace their existing vendor. Azimuth is now their production system of record, serving a roster of roughly 1,500 members.
- ▹Executed the cutover off the legacy platform, moving roughly 25 years of accumulated operational history: 29,172 reservations, 14,740 flights totalling over 18,000 Hobbs hours, and 5,167 weight-and-balance loadings, reconciled against the source system and re-runnable end to end via idempotency keys so a repeat import writes zero rows.
- ▹Built the full operational loop across ten documented modules and 133 page routes, Members & roles, Fleet & maintenance, Scheduling & dispatch, Flight logging, Training, Billing, Weather & weight-balance, and Community, where logging a flight advances Hobbs/Tach meters, auto-posts rental + instruction charges to the member's ledger, and closes the reservation in one transaction.
- ▹Designed a 149-table PostgreSQL schema with Drizzle ORM (245 forward-only migrations), multi-tenant from day one: a global users identity, memberships joining a user to an organization with a role, and an org_id on every domain table so all queries are org-scoped, a second club requires no schema change.
- ▹Implemented capability-based access control (lib/rbac.ts): six default roles (admin, dispatcher, instructor, member, student, mechanic) map to 89 fine-grained capabilities, granted per organization rather than hardcoded (e.g. dispatch:write, maintenance:manage, schedule:manage_others), and every server action + UI surface checks capabilities, not raw roles.
- ▹Built on Next.js 16 (App Router, React 19 Server Components + Server Actions) with Auth.js v5 (credentials, JWT sessions, edge-safe middleware), reservation conflict detection, inspection-due tracking (annual / 100-hr) with aircraft grounding, and a per-member A/R ledger.
- ▹Handled genuinely sensitive records with the care they need: the platform holds pilot medical certificates, licences and endorsements for a live membership. Those documents are treated as their own class rather than as ordinary profile data, access is limited to the roles whose job actually requires it, and scheduled automation authenticates and fails closed rather than open. I deliberately do not publish the implementation details of any of that.
What it looks like.






