All tags / #wheels-4

#wheels-4

42 posts

Internationalization in an Afternoon: wheels-i18n

Peter Amiri

i18n usually arrives as an emergency. wheels-i18n makes the mechanical part boring: t() and tp() with interpolation and pluralization, JSON or database catalogs, session-based locale switching, and the fallback chain that makes incremental translation actually shippable.

The Debug Bar: A Complete Tour of Wheels 4's Development Cockpit

Peter Amiri

Most developers use a fifth of the debug bar and writeDump() around the rest. The full tour: what each panel answers, the developer tools behind the last tab, the throughput cost worth knowing, and why the bar can't follow you to production — by design.

Calculated Properties: SQL-Defined Values Without the N+1 (or the Bloat)

Peter Amiri

Declare fullName or commentCount once as SQL on the model and it behaves like a column everywhere — sortable, selectable, never stale. And Wheels 4's select=false + includeCalculated pair fixes the cost problem calculated properties always created: expensive expressions run only where they're asked for, additively.

wheels console: The Debugging Move You're Not Using

Peter Amiri

A REPL inside your running app: models resolve, scopes chain, the DI container answers, settings read back. The sessions that replace writeDump-and-refresh archaeology, the slash-commands, and why console and repl are different tools that look alike.

Channels: Pub/Sub for Wheels 4, No Extra Infrastructure

Peter Amiri

SSE gives you the pipe; channels answer the harder question — how the model callback that knows something happened reaches the connection three requests away. publish(), subscribeToChannel(), channelSSETag(), the memory-vs-database adapter decision, and the named-event gotcha that catches almost everyone.

Processing 400,000 Rows Without Melting the JVM: findEach and findInBatches

Peter Amiri

findAll on 400,000 rows materializes everything into memory at once — and the request cache holds it there. Wheels 4's findEach and findInBatches walk big result sets a page at a time, with three built-in optimizations you'd forget to hand-roll and two sharp edges worth knowing first.

Running Wheels 4 the CommandBox Way

Peter Amiri

CommandBox teams do not have to switch. The complete box-native workflow for Wheels 4 — install from ForgeBox, engine selection with cfengine, datasources via CFConfig, every framework task's in-app equivalent, CI with setup-commandbox, and an honest accounting of what the wheels CLI adds if you ever want it.

How Wheels Actually Reads Your Configuration

Peter Amiri

Why exporting WHEELS_ENV=production doesn't flip your app into production — and everything else about the config pipeline: the three-file load order, the .env chain that shadows OS variables, what production mode really changes, and the reload gate's fail-closed mechanics.

Request IDs, /up, and Logs a Machine Can Read: Observability in Wheels 4

Peter Amiri

Three small pieces of plumbing turn 'the site gave me an error around lunchtime' into a single grep: the RequestId middleware, the /up health endpoint your app already ships, and a forty-line JSON logging pattern. Plus the two health-endpoint mistakes everyone makes once.

CORS in Wheels 4: Deny by Default, Open It Correctly

Peter Amiri

Wheels 4 denies cross-origin requests until you say otherwise — and the Cors middleware refuses the popular ways of saying it wrong. The deny-all breaking change, single-origin resolution, Vary: Origin, preflight handling, and the legacy-settings trap the framework defuses for you.

One Authenticator, Three Doors: Sessions, Tokens, and JWTs in Wheels 4

Peter Amiri

Wheels 4 ships session, API-token, and JWT authentication as pluggable strategies behind one Authenticator registry. Wiring up all three doors — with the sharp edges: private filters, dynamic finders, the 32-byte JWT secret minimum, and the inline-closure constructor that crashes Adobe ColdFusion.

Wheels 4 Without the Tooling: Two Zips, Zero Dependencies

Peter Amiri

The manual install that took the community two days to reverse-engineer in Wheels 3 is now two zip files and zero external dependencies. How to install, migrate, test, seed, and upgrade a Wheels 4 app with no CLI, no CommandBox, and no package manager — plus the new guides that document every step.

Sending Email in Wheels 4.0: sendEmail, Templates, and Background Delivery

Peter Amiri

A complete how-to for sending email in Wheels 4.0 — the sendEmail controller helper, how email view templates resolve, multipart text+html, attachments, and the correct way to deliver mail from a background job. Includes the sharp edges that actually bite.

File Uploads in Wheels 4.0, the Idiomatic Way

Peter Amiri

Wheels 4.0 has no ActiveStorage-style attachment system — and that's fine. This how-to walks the honest idiomatic upload flow end to end: fileField/fileFieldTag form helpers, the startFormTag multipart trap, native cffile in the controller, model validation over the result, and traversal-safe downloads with sendFile.

Caching in Wheels 4.0: Actions, Queries, Partials, and Invalidation

Peter Amiri

A practical, source-grounded tour of every cache Wheels 4.0 actually ships — action caching, query caching, partial and page caching — plus the honest truth about invalidation: there's no clearCache(key), so you live on short expiry times and full reloads.

Associations Deep-Dive: hasMany, belongsTo, Nested Properties, and Eager Loading

Peter Amiri

A comprehensive Wheels 4.0 guide to model associations — hasMany, belongsTo, and hasOne, the exact dynamic methods each one generates, dependent-delete cascades, nested properties from form params, eager loading with include=, has-many-through, and polymorphic associations — with the sharp edges that bite in practice.

Form Helpers in Wheels 4.0: Object Forms, HTML5 Fields, and Error Rendering

Peter Amiri

A worked how-to on Wheels 4.0 form helpers: object-bound fields that round-trip into params.user.email, the real HTML5 single-input helpers, and the two error-rendering helpers — plus the sharp edges that bite first.

Validations Beyond Presence: Conditional Rules, Custom Validators, and Enum Integration

Peter Amiri

A practical Wheels 4.0 guide to the full validation surface — conditional rules with condition/unless/when, custom validate() methods, enum() integration, and how to read the error API correctly. Built end-to-end around one User model, with every behavior grounded in the framework source.

Routing Deep-Dive: Resources, Nested Callbacks, and Route Model Binding

Peter Amiri

A complete Wheels 4.0 routing guide — RESTful resources, nested resources via callback vs manual nested=true, and route model binding that resolves params.post before your action runs. Plus the sharp edges: route order, the protected-helper-names trap, and how a missing record 404s.

Seeding Your Database the Idempotent Way

Peter Amiri

Wheels 4.0 ships a convention-based seeder built around seedOnce() — an idempotent helper that creates a record only if a matching one doesn't already exist, wrapped in a transaction that rolls the whole run back on any failure. This is the worked guide: file conventions, the CLI, composite uniqueness, and the sharp edges.

Dependency Injection in Wheels 4.0: services.cfm, Scopes, and Auto-Wiring

Peter Amiri

A user-facing how-to for the Wheels 4.0 DI container: register services in config/services.cfm with singleton/request/transient scopes, resolve them anywhere with service(), declare them in controllers with inject(), and let constructor auto-wiring fill in the rest.

Writing Your Own Middleware in Wheels 4.0

Peter Amiri

A from-scratch guide to authoring custom middleware in Wheels 4.0 — the one-method interface, the singleton-per-app lifecycle and the thread-safety it demands, how to short-circuit, and how to register globally or per route.

Pagination That Isn't a Pain: paginationNav and the Preset System

Peter Amiri

A complete how-to on Wheels 4.0's paginationNav helper — the all-in-one nav, the bootstrap5/bootstrap4/tailwind preset system, the auto/always/never anchor tri-state, and the dev-time guardrails that catch typos before they ship.

Real-Time Without WebSockets: Server-Sent Events in Wheels 4.0

Peter Amiri

A worked guide to Wheels 4.0's Server-Sent Events helpers — renderSSE for one-shot events, the initSSEStream/sendSSEEvent/closeSSEStream trio for long-lived streams, plus isSSERequest content negotiation, keep-alive heartbeats, and the engine-fragility sharp edges to test for.

Beyond findAll: Scopes, Enums, and the Chainable Query Builder

Peter Amiri

Wheels 4.0 ships three model-side features that compose into one design: scopes name reusable query fragments, enums turn property values into auto-generated checkers and scopes, and the chainable query builder swaps raw WHERE strings for fluent, type-aware composition. This post walks all three through one worked example and surfaces the bug I hit while writing it.

Wheels 4.0.5: a hardening release — 100+ fixes across security, performance, and deploy, now installable anywhere

Peter Amiri

Wheels 4.0.5 is out, and together with 4.0.4 it's one of the most substantial hardening passes on the 4.0 line — 100+ changes spanning security (open-redirect and info-disclosure fixes, fail-closed gates, SQL-surface tightening), warm-path performance, a much tougher `wheels deploy`, and Adobe CF / BoxLang cross-engine fixes. 4.0.5 then makes the whole thing installable the same way on every major platform — Homebrew, Scoop, apt, dnf — including arm64 Linux, verified daily.

Wheels + Claude: Building a Feature via the stdio MCP

Peter Amiri

Wheels 4.0 ships a stdio MCP server that exposes the CLI to AI editors — not as a chat sidekick, but as a tool surface a model can call. This post walks the architecture (reflection over a single CFC), builds a commenting feature end-to-end via Claude, and is honest about the config-template drift I hit while writing it.

Migrations That Survive a Team: the Wheels 4.0 Migrator

Peter Amiri

A broad how-to on the Wheels 4.0 migrator: write up()/down() migrations, drive the TableDefinition column builder (including the three-column timestamps() and the columnNames-preferred helpers), seed with inline SQL, and run the migrate CLI — including the doctor/info/forget/pretend commands that keep a shared dev database honest.

Anatomy of a Wheels Package

Peter Amiri

Wheels 4.0 replaces plugins with a package system that treats your filesystem as the registry. This post takes a small package from empty directory to installed-and-mixed-in, names every field in the manifest, and is honest about the rough edges I hit while writing it.

Wheels 4.0.3: rebuilt CLI argument parsing, honest exit codes, and wrong-database guardrails

Peter Amiri

Wheels 4.0.3 is the third patch on the 4.0 line, focused on making the `wheels` CLI trustworthy in scripts and CI: argument parsing is rebuilt end-to-end (`--no-*` negations and named-only flags finally reach every command), failures exit non-zero, and write-side commands refuse to attach to a different project's server. Plus PostgreSQL/CockroachDB foreign-key migration fixes, pre-23c Oracle support, preserved column casing in model output, and a fix that stops framework helpers from being URL-invokable as controller actions.

Wheels 4.0.2: shared-database migration reconciliation and native apt/yum repos

Peter Amiri

Wheels 4.0.2 is the second patch on the 4.0 line. It teaches the migrator how to cope with a database that more than one developer shares — orphan-version detection, a `migrate doctor` health report, and `forget` / `pretend` reconciliation commands — fixes a class of silent migration rollbacks on MSSQL, makes the migrator's column-name helpers consistent, and ships native signed apt.wheels.dev / yum.wheels.dev package repositories so Linux installs and upgrades are a one-liner.

Wheels 4.0.1: Adobe CF hardening, Windows Scoop fixes, and the post-GA shakeout

Peter Amiri

Wheels 4.0.1 is out — the first patch on the 4.0 line. It hardens Adobe ColdFusion 2023/2025 compatibility, fixes the Windows Scoop install regressions reported after GA, adds CSS-framework presets to paginationNav(), short-circuits whereIn([]) so empty filters stop emitting invalid SQL, and threads about a hundred smaller fixes through the rest of the framework.

Skip the Plugin: Building a Rate-Limited API in Wheels 4.0

Peter Amiri

Wheels 4.0 ships a real middleware pipeline, and three of the things you used to reach for a plugin to add — rate limiting, CORS, and security headers — are built in. This post walks through wiring a JSON API with per-API-key rate limits, sane proxy handling, and the right ordering so you do not accidentally weaken the very headers you were trying to add.

From WireBox to wheelsdi — The Framework Gets Leaner

Peter Amiri

Wheels 4.0 decomposes the framework's rim against the CFML engine, pulls dependency injection and the test runner in-house as wheelsdi and WheelsTest, and breaks the monolithic boot sequence into discrete phases. Nothing a user of the framework notices at the surface. Everything a contributor notices when they try to add the next feature.

Upgrading from Wheels 3.x

Peter Amiri

Wheels 4.0 lands with seven breaking changes and a Legacy Compatibility Adapter for teams that cannot touch every call site this quarter. This post is the honest map: what breaks, how to detect it, how to fix it, and when the adapter is the right answer instead.

Wheels 4.0: Closing the Maturity Gap

Peter Amiri

For years, the same rows showed up red in every framework comparison: no bulk ops, no polymorphic associations, no advisory locks, no middleware, no browser testing. Wheels 4.0 closes those gaps. This is a guided tour of what changed and where the framework still trails.

LuCLI and the Zero-Docker Developer Experience

Peter Amiri

Wheels 4.0 ships with a new inner-loop story: a single native binary, a sixty-second full test run, and a multi-phase migration that quietly moved the framework off Docker for day-to-day development. This post walks through how we got here, what LuCLI is, and why cross-engine matrix testing still belongs in Docker.

Multi-Tenancy Built In

Peter Amiri

Wheels 4.0 lifts multi-tenancy out of plugin territory and into the framework core. Per-request datasource switching catches every query and every job on the way to the database, and tenant-aware background jobs come along for the ride.

Background Jobs Without Redis

Peter Amiri

Wheels 4.0 ships a production-ready job queue that needs only your database. You get a persistent CLI worker, live monitoring, configurable backoff, and tenant-aware enqueueing without any extra services. Redis still wins for very high throughput and pub/sub fan-out — this post names where the DB-backed queue is the right call and where it is not.

Testing in Wheels 4.0

Peter Amiri

Wheels 4.0 completes the test pyramid: BDD unit tests, a fluent HTTP TestClient for integration, and Playwright-powered browser automation for end-to-end — all running in parallel. The category that was most embarrassing in 3.0 is the most complete in 4.0.

Security Hardening in Wheels 4.0

Peter Amiri

Wheels 4.0 shipped more than forty security-hardening pull requests across eight categories — SQL, path handling, session integrity, CORS, rate limiting, auth and dev surfaces, CLI and MCP, and view helpers. The common thread is a shift in posture: the framework's defaults are now safe first, convenient second.

Porting Kamal to CFML: How wheels deploy Ships 4.0 Apps Without Ruby

Peter Amiri

Wheels 4.0 ships with a new command: wheels deploy. It's a port of Basecamp's Kamal into the Wheels CLI — zero-downtime Dockerized deploys to Linux servers over plain SSH, no Ruby runtime required. This post covers what got ported, the one deliberate divergence from Kamal, and the byte-compatibility contract that lets you take over a Kamal-managed server without cleanup.

Newsletter

Release notes and new posts, once a month. No spam.

Prefer RSS? Subscribe to the feed →