Stack, domains, layers and code organisation

Architecture

4 min readUpdated August 2026

This page describes Xedul's technical architecture. It's aimed at people building on the product or evaluating its foundations, not at end users.

Stack

LayerTechnology
FrontendNext.js 15 with App Router, React 19, TypeScript 5.8
StylingTailwind CSS with a token-based design system
StateReact Query for remote data, a light store for interface state
BackendSupabase: PostgreSQL, auth, realtime, storage
AuthenticationSupabase Auth with role-based access control
RealtimeSupabase Realtime subscriptions with caching
Internationalisation`next-intl` with dynamic language switching

Repository structure

Xedul/
├── app-web/          Next.js application
│   └── src/
│       ├── app/            App Router routes
│       ├── domains/        domain logic
│       ├── infrastructure/ API, database, realtime, providers
│       ├── shared/         reusable components, hooks, utilities
│       ├── translations/   translation files
│       └── types/          TypeScript definitions
├── integrations/     Gmail and Outlook add-ons, manifests
├── supabase/         configuration and migrations
├── tooling/          lint, repository scripts
└── Doc/              internal documentation

Domain architecture

Business logic is organised by domain, not by file type. Each domain holds what its area needs: types, hooks, API calls, components.

The domains present include auth, customers, contacts, projects, tasks, calendar, documents, comments, notifications, reminders, organization, users, statuses, chat, and the two email-integration domains.

The practical consequence: adding a feature to one area almost always touches a single domain folder, instead of spreading across five folders organised by type.

The infrastructure layer

Beneath the domains sits infrastructure, insulating the rest of the application from technical detail:

  • API controllers — separate business logic from route handlers.
  • Database layer — data access with a repository pattern and typing.
  • Provider composition — application state and React context management.
  • Realtime system — change synchronisation with caching, to avoid repeating the same requests.

Layered type system

Xedul carries type safety from the database up to the interface, distinguishing layers with different responsibilities:

LayerRole
Database typesSchema and database operations
Domain typesBusiness logic
UI typesComponent props and interface state
Adapter typesData transformation and external integrations
Branded typesTyped identifiers, so two different IDs can't be confused

Branded types deserve a note: they prevent, at compile time, passing a client identifier where a case identifier is required. At runtime that mistake would be silent.

Route structure

The App Router organises pages into groups:

  • (marketing) — public pages.
  • (auth) — sign-in, sign-up, password recovery, email confirmation.
  • (authenticated) — the application proper, behind authentication.
  • api/ — server endpoints per domain.
  • gmail/ and outlook/ — bridging pages for the email integrations.

Route groups let each area carry its own layout and providers. Marketing pages, for instance, don't load the application's providers: the bundle stays small.

Database schema

The schema is multi-tenant, with the organisation as root entity.

Core entities — organisations, users, customers, projects, contacts, tasks.

Supporting entities — sectors, lead sources, company sizes, project stages, task statuses, documents, metrics.

Every work table carries the organisation reference. That's the foundation of the isolation described in Security.

Realtime

Changes propagate to subscribed clients through Supabase Realtime. The caching layer in front of subscriptions avoids invalidating more than necessary: the aim is that two people on the same case see the same state without reloading, and without generating traffic proportional to the number of open tabs.

Design system

The interface rests on a token system: colours, typography, spacing, radii, shadows and animations are defined centrally and consumed by components.

The defining traits: Inter as the interface typeface, a lot of white and light grey, near-black grey for primary actions, blue as the accent for links and focus states, generous radii on foreground containers and very soft shadows.

The landing page and the documentation you're reading use different typography from the product, to read as communication material, but share the palette, radii and spacing relationships.

Environments and release

The project uses a continuous integration and delivery pipeline with quality gates — lint, type-check, tests, security audit — before every deployment. The development branch publishes to a preview environment; the main branch follows a strategy that validates the deployment before applying schema changes to production.

Architecture — Xedul