Skip to content

Start Here

Why Wheels?

You’re evaluating web frameworks. You’ve probably used at least one of Rails, Laravel, or Django. This page is an honest comparison — what Wheels shares, where it differs, and when it’s the wrong tool.

You’ll learn:

  • What CFML actually is (two paragraphs)
  • How Wheels maps to Rails / Laravel / Django concepts
  • When to reach for Wheels and when not to

CFML is a server-side language. It’s been around since 1995, which makes it older than PHP. The syntax reads like a blend of JavaScript and Ruby: loose typing, structs and arrays as first-class values, closures, lots of built-in functions for web work.

Two runtime engines implement CFML. Lucee is open source, free, and community-maintained; it’s what Wheels 4.0 targets by default. Adobe ColdFusion is a commercial product from Adobe. Both run on the JVM. You write CFML, Lucee or ACF compiles it to Java bytecode at request time. You don’t install a Ruby / Python / PHP runtime — you install Lucee via the wheels CLI, and it brings its own.

One common confusion: “ColdFusion” the language is CFML. “Adobe ColdFusion” is one of two implementations. Wheels does not require Adobe’s commercial product.

Closest conceptual neighbor. Both descended from the same Rails-era design.

ConcernRailsWheels
LanguageRubyCFML (runs on JVM)
ORM styleActiveRecordActiveRecord-style (Model base class)
ConventionStrongStrong — same “fat models, thin controllers” shape
CLIbin/rails / gem install railswheels
Scaffoldrails generate scaffoldwheels generate scaffold
Migrationsdb/migrate/*.rbapp/migrator/migrations/*.cfc
View layerERB / Haml / etc..cfm templates (inline expressions via #...#)
HotwireBundled (Turbo Drive / Frames / Streams)Via wheels-hotwire package (opt-in activation)
TestingMinitest / RSpecWheelsTest (BDD, describe/it)
JobsActive Job + Sidekiq/etc.Built-in DB-backed job queue (wheels jobs work worker)

If you know Rails, the tutorial will feel familiar in pacing and idioms. The differences that bite most often:

  • Hash-delimited expressions in CFML strings. "Hello #user.name#" interpolates user.name. This is different from Ruby’s "Hello #{user.name}"; the # pairs are delimiters, not escape-plus-braces.
  • Named-argument style matters. Wheels functions often take positional OR named args, never a mix. hasMany(name="comments", dependent="delete") — not hasMany("comments", dependent="delete").
  • No bundler / Gemfile. The framework lives in vendor/wheels/, copied into the app by the CLI. There’s a package system (first-party packages are standalone repos indexed by the wheels-dev/wheels-packages registry and installed into vendor/<name>/), but there’s no lockfile — intentional.

Laravel is more spiritually aligned than structurally. Both are opinionated, both emphasize developer experience, both have generators and a robust CLI.

ConcernLaravelWheels
ORMEloquent (ActiveRecord-ish)Wheels Model (ActiveRecord)
RoutingPHP closures + controllersCFML script (mapper()...end())
ViewsBlade.cfm (inline) or partials
CLIArtisanwheels
AuthSanctum / Fortify / BreezeBuilt-in wheels.auth (session / JWT / token strategies)
QueuesHorizon + Redis / SQSBuilt-in job queue with DB backing
Real-timeLivewire / BroadcastingServer-Sent Events (native) + Turbo Streams (via package)
Package managerComposerCurated wheels-packages registry; install into vendor/<name>/

The closest comparison point is Laravel’s scaffold ethos. wheels generate scaffold Post title:string body:text produces the same “everything-you-need-to-see-a-CRUD-interface-running” result as php artisan make:model Post -a + make:controller. Wheels goes a step further: the scaffolded views use Basecoat UI (when the basecoat package is activated) so you get a modern-looking app without writing CSS.

Livewire has no direct Wheels analog. For similar “server-rendered, JavaScript-light interactivity,” use Turbo Frames from the hotwire package.

Bigger gap. Django is DataMapper (models + views + serializers are separate concerns); Wheels is ActiveRecord (models carry behavior). Django emphasizes explicit over implicit; Wheels emphasizes conventional over configured.

ConcernDjangoWheels
ORMDataMapper (Django ORM)ActiveRecord (Wheels Model)
URL routingurls.py, explicit patternsroutes.cfm, resources("posts") + conventions
AdminAuto-generated /adminwheels generate admin ModelName (scaffolded, not auto)
Migrationsmakemigrations + migratewheels generate migration + wheels migrate latest
TemplatesJinja-like DSL.cfm (inline expressions)
Formsforms.py with Form classesView helpers (textField, textArea, etc.)
Authdjango.contrib.authwheels.auth

The sharpest difference is philosophy. Django expects you to be explicit about URLs, form fields, admin configs. Wheels expects you to follow the conventions and only override when you need to. If you reach for Django because “explicit is better than implicit,” Wheels will feel too magical. If you reach for Rails because conventions let you move fast, Wheels is in the same family.

Django’s auto-generated admin panel has no Wheels equivalent. wheels generate admin User produces a scaffolded admin section you own and customize — more like Rails’ rails_admin gem than Django’s built-in admin.

  • Database-heavy line-of-business apps. Invoicing, inventory, CMS, internal tools. Wheels’ ORM + scaffolds + migrations + admin generator ship these fast.
  • Teams with existing CFML or Java infrastructure. You already have Lucee or ACF servers, or you’re comfortable on the JVM. Wheels fits the existing stack.
  • Apps where “scaffold and ship” beats “latest runtime feature.” Wheels is mature and boring in good ways. Monthly releases, clear upgrade paths, no weekly framework-rearchitecture.
  • Teams migrating from legacy CFML. The 3.x → 4.0 upgrade guide is well-trodden. If you’re on CFWheels 2.x, the path forward is clear.
  • GraphQL-first APIs. Wheels ships a REST-style controller surface. GraphQL works but isn’t native; you’ll wire it yourself.
  • Realtime-first apps. SSE is native, Turbo Streams cover in-page updates, and WebSocket support is available — but if your product is a chat app or collaborative editor, Phoenix / Elixir, Rails + ActionCable, or Django Channels fit better.
  • Cloud-native serverless. CFML is JVM-hosted. Cold starts are slow. If you need AWS Lambda-style per-request provisioning, pick a runtime that targets it.
  • Frontend-heavy SPAs. If your app is 90% React or Vue talking to an API backend, pick a framework that specializes in API-only. Wheels can do it, but you’re leaving most of the framework on the table.