This document describes the high-level architecture of Cella.
- Only build what you are going to use yourself.
- Stay humble and remain a template, not a framework. So prevent abstraction layers.
- A single, opinionated stack: ie. Cella uses Drizzle ORM and will not make it replaceable with another ORM.
- Modularity. As CellaJS will grow, we need to make sure you can scaffold only the modules that you need.
- Open standards. Our long term vision is that each Cella - as in each cell - can speak fluently with other cells.
.
├── backend
| ├── .db Location of db when using pglite
| ├── emails Email templates with jsx-email
│ ├── drizzle DB migrations
│ ├── seed Seed scripts
│ ├── src
│ │ ├── cron
│ │ ├── db Connect, table schemas
│ │ ├── lib Init library code & important helpers
│ │ ├── middlewares Hono middlewares
│ │ ├── modules Modular distribution of routes, schemas etc
│ │ └── types Split between common and app-specific
│ │ └── utils
├── config Shared config: default, development, production
├── frontend Frontend SPA
│ ├── public
│ ├── src
│ │ ├── api API functions with RPC
│ │ ├── hooks
│ │ ├── json
│ │ ├── lib Library code and helper functions
│ │ ├── modules Modular distribution of components
│ │ ├── routes Code-based routes
│ │ ├── store Zustand data stores
│ │ ├── types Split between common and app-specific
│ │ ├── utils
├── info General info
├── locales Translations
└── tus TUS server
Entities can be split in four types:
- All entities (user, organization)
- PageEntity: Entity that can be searched for (user, organization)
- ContextEntity: Has memberships (organization)
- ProductEntity: Content related entities without membership
The default cella setup has one example product entity - attachments
- and one context: organizations
.
An OpenAPI is built with zod-openapi. Please read the readme in this middleware before you get started.
Both frontend and backend already have modules, such as authentication
, users
and organizations
. The backend modules are split mostly by functionality. The frontend modules are split by the user interface: home
, organizations
, marketing
. The benefit of modularity is twofold: better code (readability, portability etc) and to make receiving cella updates possible.
Zooming in on some of the frontend modules:
common
: a cella-predefined set of reusable react componentsui
: Full with shadcn UI components. They have some small tweaks however and it is to be expected you will customize them yourself further.attachments
: product entity module that has support for offline, optimistic updates and realtime sync.
A similar situation can be found in the types
folders of both frontend and backend. you have app-specific types in app.ts
and predefined cella types in common.ts
.
In the frontend we decided - for now - to keep routes
, stores
, hooks
and api
together and not nest them in each respective module. This has pros and cons but the idea here is that having them together gives you a quick look into what the complete app has to offer, and to make it easier to strive for consistency. This benefit wil reduce when cella gets more stable, so its likely this will change in the future.
Link to valuable resources: