Guides / Project structure
A place for every change.
Start with your intention. Caramel’s conventions give it a home, and its tools help you check the result.
| Contract | Value |
|---|---|
| Covers | Endpoints, stored data, pages, background jobs, languages, the domain model, seed data, tenants and the production build |
| You will have | The files that own each kind of change, the commands that check it, and the page that states its rules |
| Proved by | frappe check · frappe corretto |
Find the file for a change
Each row names the files, the commands that check them, and the page that states the rules.
| I want to… | It goes in | Check it with |
|---|---|---|
| Add or change an endpoint Routes and contracts → | config/routes.cr app/actions/ spec/requests/ | frappe routes · frappe check · frappe corretto |
| Change the data the application stores SugarORM → | app/models/ app/changesets/ db/migrations/ | frappe db diff · frappe migrate · frappe corretto |
| Change what the browser renders Views → Test rendered HTML → | app/views/ app/assets/ spec/requests/ | frappe check · frappe corretto |
| Move work into a background job Cold Brew → | app/jobs/ spec/requests/ | frappe check · frappe corretto |
| Translate the application Internationalization → | app/locales/ config/application.cr | frappe translations · frappe check · frappe corretto |
| Model the domain in SweetTalk SweetTalk → | app/domain/ spec/domain/ .claude/skills/sweettalk/SKILL.md | frappe check · frappe db diff · frappe corretto |
| Seed development data Local environment → | db/seeds.cr | frappe seed |
| Serve many accounts from one application Multi-tenancy → | The tenant block in config/routes.cr app/models/ | frappe make tenancy · frappe routes · frappe corretto |
| Build for production Production → | The committed tree; public/ in the artifact | frappe build · APP jobs unknown |
Your application’s files are the extension point. Best practices says what to do when the public API falls short →
Meet the framework
Seven components, one job each, all standing on PostgreSQL, and one opt-in language on top of them.
| Component | What it does |
|---|---|
| Blueprint | HTML written in typed Crystal |
| SugarORM | Schemas, changesets and queries |
| Cold Brew | Background work, backed by PostgreSQL |
| Corretto | Application tests with real data |
| Crema | Logs, metrics and traces |
| Frappé | Your developer command line |
| Latte | Local services and named HTTPS |
| SweetTalk | An opt-in language for the domain model, experimental |
What does not compile
A change in the wrong place is caught by frappe check, before any request. Each page linked above states its own rules; these are the ones a newcomer meets first.
| Condition | Outcome |
|---|---|
| A route parameter without a field in the action’s contract | fails compilation |
| An association a view reads without a preload | fails compilation, reported as N_PLUS_ONE |
| Two schemas that name one table | fails compilation |
| A mocking library compiled beside Corretto | fails compilation |
Not covered yet
app/commands/is generated empty andconfig/application.crdoes not require it; a command registered withCaramel::Crema.commandlives in a file you require yourself.spec/system/andstorage/are generated empty; no page describes browser tests or file storage.- Caramel ships no command that provisions servers or deploys.
Prove it
Check the change you made
frappe check
frappe correttoPassing: frappe check exits 0 and frappe corretto ends with Corretto: N of N workers passed.