Caramel today.
The supported APIs, development requirements, and current limits of Caramel 0.8.0.
Upgrading to 0.8.0
Upgrade Caramel and Frappé together: the schema document frappe db diff reads is now version 2, and SugarORM::Catalog::ForeignKey holds columns and references_columns so a key can span several columns.
- Run
frappe migrate. Two framework migrations addcaramel_jobs.contextandcaramel_metrics. - Run
latte stoponce if Latte is running, so the next command starts the new one. Frappé, Corretto and Latte.app now use Latte’s control API 2. The managed PostgreSQL restarts once to preload its statistics modules. - To keep per-minute aggregates, add
require "caramel/crema/recorder"afterrequire "caramel"inconfig/application.cr. New applications already have it. - Logging now sets itself up: JSON in production, text in development and test. The old
error_typelog line is gone; theerrorline carrieserror_classandfingerprint.
Internationalization
Caramel has opt-in, typed translations. Run frappe make locale CODE to add Crystal catalogs and enable translated resource generation. Views and actions use t for messages and l for number and time formatting. Language selection supports a switch, optional URL prefixes, cookies, and browser preferences.
Contract and changeset errors, JSON error messages, and framework pages use the request’s locale. Missing translations fall back, and frappe translations reports what remains. Background jobs carry their language explicitly.
Runtime and local tools
Caramel is a source-built Crystal framework. Its managed toolchain pins Crystal 1.21.1 and PostgreSQL 18. The local development workflow targets Apple Silicon macOS with Apple Command Line Tools. Frappé creates projects, generates resources, and supervises builds; Latte supplies managed services and named HTTPS.
Install from v0.8.0 with the getting-started guide. An application’s shard.lock selects its framework release, and Frappé dispatches to the matching installation.
Requests and responses
Typed action contracts bind route and query values, URL-encoded forms, multipart uploads, and JSON objects. The default policy checks CSRF for writes and limits ordinary request input to 2 MiB; multipart uploads have a separate 64 MiB budget. Use per-action ingress for a custom limit, authenticated APIs, or exact raw webhook bytes.
Actions return HTML or JSON according to the request. render_errors handles errors found after contract binding. Blueprint views write typed HTML with escaped text and attributes; htmx partial responses update selected page regions.
Data and resource generation
SugarORM provides typed schemas, changesets, queries, and explicit preloads. Derive a migration with frappe db diff, review it, and apply it with frappe migrate. frappe make resource generates application-owned models, changesets, actions, views, routes, migrations, and request specs.
Use :server for fields populated by the action, :unique for unique indexes and constraint checks, and :url for URL validation and inputs. --only=create,show generates a smaller action set; create and show are required, and edit needs new and update.
Background work
Cold Brew stores jobs in PostgreSQL and supports transactional enqueueing, retry policies, durable status, retry/failure hooks, recurring schedules, PubSub, and cache. The application binary runs queues through serve or a worker-only work process with queue and concurrency options. External calls can repeat, so use a stable identifier for deduplication.
Development and testing
Corretto drives in-process application requests against isolated test databases. Its client sends forms, multipart uploads, JSON, or exact raw bodies. Blueprint-shaped have_html expectations inspect decoded rendered HTML; render_partial can check an envelope’s target, swap, and content together.
Generated applications pin Lexbor 3.6.4 under development dependencies. Development installs need cc, ar, and network access for the verified native parser source. Production installs omit the parser. Put application-owned test settings in committed .env.test; development .env does not reach specs.
frappe check
frappe corretto
frappe lintMulti-tenancy
An application can be multi-tenant. frappe make tenancy MODEL adds the tenant schema, sign-up and home pages, and a tenant block in the routes; resources generated afterwards belong to the tenant, and --central makes one every tenant shares.
Observability
Every routed request, job and schedule run gets a request id, a trace and one canonical log line. In development, frappe dev adds an inspector, a toolbar, richer error pages and the frappe traces, trace and errors commands. In production, an owner-only ops socket serves status, Prometheus text, recent errors and a console; the recorder and the OTLP exporter are opt-in. Latte adds statement statistics, menu-bar error counts and notifications, per-site access logs and a local trace collector on 127.0.0.1:4318.
Read the observability guide →
Current limits
File upload parsing is available, but the cookbook still needs a complete storage and cleanup example. A complete production deployment recipe, optional authentication generator, smaller individual generators, a Frappé extension point for custom commands, and a consumer installer remain unfinished. An application can add commands to its own binary with Caramel::Crema.command. Draft recipes identify application examples that still need end-to-end validation.