Wheels-The Fast & Fun
CFML Framework!

Build apps quickly with an organized, Ruby on Rails-inspired
structure. Get up and running in no time!

Latest From the Wheels Dev Blog

Why We Rebuilt Our CI Pipeline From 40 Minutes to 82 Seconds

# Why We Rebuilt Our CI Pipeline From 40 Minutes to 82 Seconds *April 9, 2026 — Peter Amiri, Wheels Core Team* --- For years, the Wheels CI pipeline ran every commit through a gauntlet: five CFML engines, seven databases, Docker Compose orchestrating it all. It was thorough. It was comprehensive. And it was killing our velocity. Today we shipped a fundamentally different approach. Our primary CI now runs in **82 seconds**. No Docker. No CommandBox. Just LuCLI, Lucee 7, and SQLite — the same tools a developer uses on their laptop. This post explains the reasoning behind the change, what we learned, and why we think this pattern applies to any framework project fighting its own CI. ## The Problem We Were Solving Our previous CI pipeline tested every push to `develop` against this matrix: | | MySQL | PostgreSQL | SQL Server | H2 | CockroachDB | Oracle | SQLite | |---|---|---|---|---|---|---|---| | **Lucee 5** | | | | | | | | | **Lucee 6** | | | | | | | | | **Lucee 7** | | | | | | | | | **Adobe 2023** | | | | | | | | | **Adobe 2025** | | | | | | | | | **BoxLang** | | | | | | | | That's up to 42 engine-database combinations. Each engine needed a Docker image built from `ortussolutions/commandbox`, which downloads CommandBox, installs Lucee or Adobe CF, warms up the server, installs dependencies, and then starts. The database containers needed their own startup time — Oracle alone takes 2-3 minutes to accept connections. A typical CI run took **30-45 minutes**. On a bad day with flaky Oracle connections or BoxLang compilation issues, it could take over an hour. More critically, this matrix had become a **development tax**. Every feature branch had to pass every engine. Every refactor had to work identically on Lucee, Adobe CF, and BoxLang. The cross-engine differences weren't just slowing CI — they were slowing the design of the framework itself. ## The Cost of Universal Compatibility When you maintain compatibility across three fundamentally different CFML engines, every abstraction carries hidden weight. Here are real examples from the weeks before this change: **The `invoke()` BIF**: Adobe ColdFusion requires positional arguments for `invoke()`. Lucee accepts named arguments. BoxLang requires extracting the method reference and calling it directly. A single line of code — "call this method on this object" — needed an engine adapter with three implementations. **The `interface` keyword**: We added a CFML `interface` file for documentation. It compiled fine on Lucee and Adobe. BoxLang's CFC scanner choked on it during directory traversal, crashing the entire application before a single test could run. **Oracle TIMESTAMP coercion**: Oracle's JDBC driver returns `oracle.sql.TIMESTAMP` objects instead of standard dates. BoxLang needed these coerced to CFML dates. Adobe CF didn't — until we added a unified adapter, which then broke Adobe's timestamp comparison tests. Fixing Adobe broke BoxLang's `hasChanged()` method. Each fix for one engine destabilized another. **The `$wheels` lifecycle**: During application startup, the framework stores configuration in `application.$wheels`, then copies it to `application.wheels` at the end of initialization. Code that runs mid-initialization needs to check both locations. This was invisible for years until the engine adapter PR introduced a function that was called during route loading — before the copy happened. Every engine crashed, but each with a different error message. These aren't exotic edge cases. They're the daily reality of cross-engine CFML development. Every one of them turned a 30-minute feature into a multi-day debugging session, with CI as the bottleneck for each iteration. ## The Strategic Decision: Pick a Primary Platform We made a deliberate choice: **Lucee 7 and SQLite are the primary supported platform for Wheels going forward.** This doesn't mean we're dropping support for other engines or databases. It means we're changing the relationship between primary and secondary platforms: - **Primary (Lucee 7 + SQLite)**: Hard CI gate. Every PR. Every merge. Must pass to ship. - **Secondary (everything else)**: Monitored weekly. Failures are tracked and addressed, but they don't block development. This mirrors how most successful open-source projects operate. Rails doesn't block releases on JRuby compatibility. Django doesn't require every commit to pass on MySQL, PostgreSQL, and SQLite simultaneously. They pick a reference platform, optimize the inner loop for it, and run broader compatibility checks on a separate cadence. ### Why Lucee 7 Lucee is where Wheels development happens. It's the engine the core team runs locally. It's the engine most Wheels applications deploy on. And with LuCLI — our new Lucee-native CLI — it's the engine we're investing in for the AI-native development experience (MCP tools, code generation, interactive REPL). Lucee 7 specifically because it's the current mainline release with active development and the best performance characteristics. ### Why SQLite SQLite eliminates external dependencies entirely. No Docker container to start. No connection pooling to configure. No 3-minute Oracle startup to wait for. The SQLite JDBC driver is a single JAR file. For a framework test suite that exercises ORM behavior, query building, migrations, and data validation, SQLite covers the vast majority of code paths. Database-specific behavior (stored procedures, vendor-specific SQL) is tested in the weekly compatibility matrix. ## The New Architecture ### Primary CI: LuCLI Native (82 seconds) ``` checkout -> setup JDK 21 -> install LuCLI binary (38MB download) -> create SQLite test databases -> lucli server run (starts Lucee 7 natively on the runner) -> install SQLite JDBC into Lucee classpath -> run 2,482 tests via curl -> parse results, generate JUnit XML -> upload artifacts ``` No Docker. No CommandBox. LuCLI downloads as a single Linux binary from GitHub Releases. It starts Lucee Express directly on the GitHub Actions runner JVM. The test suite runs against localhost. The total job time is **82 seconds**, including JDK setup, Lucee download (cached after first run), server startup, and running all 2,482 tests. ### Develop Pipeline: Fast Test Gates Release ``` fast-test (82s) -> build snapshot (ForgeBox publish) -> sync docs (wheels.dev) ``` The snapshot release to ForgeBox only happens if the fast test passes. This is the same gate that existed before — it just runs 30x faster. ### Compatibility Matrix: Weekly + Manual The full 5-engine x 7-database Docker Compose matrix now runs on a weekly schedule (Sunday 02:00 UTC) and via manual dispatch. It uses the exact same `tests.yml` workflow that was previously the primary CI. Nothing was deleted — it was relocated. This gives us: - **Early drift detection**: If Adobe CF 2025 breaks on a Wheels change, we'll know within a week. - **No noise on every push**: Developers don't see red badges for BoxLang compilation issues they can't fix. - **On-demand deep testing**: Before a release, anyone can trigger the full matrix manually. ## What LuCLI Means for CI LuCLI is more than a CommandBox replacement — it's a statement about where Wheels is headed. By using LuCLI in CI, the pipeline validates the same tool developers use locally: - `lucli server start` starts the same Lucee instance in CI and on your laptop - `lucli server stop` cleanly shuts it down - The `lucee.json` configuration file is the single source of truth for server config When CI and local development use the same tools, "works on my machine" and "works in CI" converge. There's one mental model, one set of troubleshooting steps, one path from code change to verification. ## The Datasource Pattern: Engine-Level to App-Level The move from CommandBox to LuCLI surfaced an important architectural shift in how datasources are configured. In the CommandBox/Docker world, datasources lived at the **engine level**. CommandBox supports CFConfig — a JSON file that injects datasource definitions directly into Lucee's server configuration before the application starts. Our Docker Compose files used `CFConfig.json` to define all seven database connections (MySQL, PostgreSQL, SQL Server, H2, CockroachDB, Oracle, SQLite) at the engine layer. The application never needed to know how those connections were established — it just referenced them by name. LuCLI doesn't support CFConfig. Rather than building a compatibility shim, we took this as an opportunity to move datasource definitions where they arguably belong: **at the application level**. CFML has supported `this.datasources` in `Application.cfc` for years, but the ecosystem's reliance on engine-level admin panels and CFConfig meant most developers never used it. In Wheels, `config/app.cfm` is the recommended place for Application-level configuration — it's included by `Application.cfc` and keeps the framework file clean: ```cfm // config/app.cfm if (server.system.environment.WHEELS_CI ?: "" == "true") { this.datasources["wheelstestdb_sqlite"] = { class: "org.sqlite.JDBC", connectionString: "jdbc:sqlite:#expandPath('../')#wheelstestdb.db" }; } ``` This is a better pattern for several reasons. App-level datasources are version-controlled with your code. They're portable across engines without engine-specific admin tools. They're visible in code review. And they work identically whether you're running LuCLI locally, deploying to a server, or running in CI — no separate configuration layer to keep in sync. The `WHEELS_CI` environment variable gates the test datasources so they only activate in CI. Production applications define their real datasources in the same file, ungated, or read connection strings from environment variables. ## Lessons Learned ### 1. Comprehensive doesn't mean fast A 42-combination test matrix is comprehensive. It's also 42x slower than testing one combination. For the inner development loop — where a developer pushes a commit and wants to know if it works — comprehensive is the enemy of productive. ### 2. Engine differences are architectural, not incidental The differences between Lucee, Adobe CF, and BoxLang aren't bugs to be papered over. They're fundamental architectural differences in how these engines handle compilation, class loading, struct member functions, and Java interop. Treating them as incidental (just add an `if` statement) leads to an ever-growing thicket of conditional code. Treating them as architectural (pick a primary, adapt others) leads to cleaner abstractions. ### 3. CI time is developer time multiplied If your CI takes 40 minutes and your team pushes 10 times a day, that's nearly 7 hours of CI time daily. Even if developers context-switch during that time, the cognitive cost of interrupted flow is real. At 82 seconds, the feedback is practically synchronous — push, grab a coffee, see results. ### 4. The legacy matrix is still valuable — just not as a gate We didn't delete the compatibility matrix. We decoupled it from the critical path. The weekly run still catches drift. The manual trigger is available before releases. But it no longer holds every commit hostage to Oracle startup times and BoxLang compilation quirks. ## What's Next This CI change is part of a larger strategic shift toward Lucee 7 as the reference platform for Wheels: - **LuCLI as the recommended CLI**: Replacing CommandBox for Wheels-specific workflows (generation, testing, migration, MCP) - **Engine adapters**: The adapter pattern from the W-004 PR centralizes cross-engine behavior, making it easier to maintain secondary engine support without polluting the main codebase - **Docker simplification**: Local development moves to `lucli server start` instead of `docker compose up`. Docker stays for the compatibility matrix and production deployment The goal is a development experience where the distance between idea and verified code is measured in seconds, not minutes. --- *The CI pipeline changes are in [PR #2032](https://github.com/wheels-dev/wheels/pull/2032). The compatibility matrix runs weekly and is available via manual dispatch at [Actions > Wheels Compatibility Matrix](https://github.com/wheels-dev/wheels/actions/workflows/compat-matrix.yml).*

April 09, 2026 by Peter Amiri

Wheels CLI Asset Commands: precompile, clean & clobber

# Introduction So far in this series, we’ve explored how the Wheels CLI in 3.x helps you manage your application’s environments, databases, plugins, and testing workflows. Now we’re discussing another critical aspect of modern web applications: # Asset management. Every production-ready application depends on optimized frontend assets — CSS, JavaScript, images, fonts, and other static resources. During development, assets are often served individually for easier debugging. But in production, they must be optimized for performance. That’s where Wheels CLI asset commands come in. Instead of manually bundling, clearing, or rebuilding static files, Wheels 3.x provides structured commands to manage the asset pipeline directly from your terminal. The CLI now supports: ``` wheels assets precompile wheels assets clean wheels assets clobber ``` These commands transform asset handling from a manual deployment step into a repeatable, production-ready workflow. # Why Asset Commands Matter In real-world applications, asset management affects: * Page load speed * Caching efficiency * SEO performance * Production stability * Deployment reliability Without proper asset control, you may encounter: * Old CSS or JS being cached * Missing compiled files * Conflicts between development and production builds * Bloated static assets * Inconsistent deployments The Wheels CLI asset commands solve these issues with clarity and structure. # wheels assets precompile `wheels assets precompile` This command prepares your assets for production. It typically: * Compiles CSS and JavaScript * Bundles files * Minifies output * Generates fingerprinted filenames * Optimizes static resources When to Use It * Before deploying to staging * Before deploying to production * During CI/CD pipelines * After frontend updates Instead of relying on runtime compilation, precompiling ensures assets are ready before the application goes live. **Benefits** * Faster production performance * Reduced runtime overhead * Improved caching behavior * Stable, predictable deployments Precompilation shifts processing from runtime to build time — which is a best practice in modern web architecture. # wheels assets clean `wheels assets clean` Over time, your compiled assets directory may accumulate outdated files. The **clean** command removes old or unused compiled assets while preserving necessary ones. **Why This Is Important** Without cleaning: * Disk usage grows * Old fingerprinted files remain * Confusion increases during debugging * Deployment directories become cluttered **When to Use It** * After multiple deployments * When troubleshooting asset conflicts * Before running a fresh precompile * During maintenance It keeps your asset directory organized and efficient. # wheels assets clobber `wheels assets clobber` The **clobber** command is more aggressive. It removes all compiled assets completely. Think of it as a full reset. **When to Use It** When assets are corrupted After major frontend restructuring When switching build strategies During deep troubleshooting After running: ``` wheels assets clobber wheels assets precompile ``` You get a completely fresh build from scratch. **Why It’s Powerful** * Eliminates stale artifacts * Removes hidden conflicts * Forces a clean rebuild * Ensures consistency Use it carefully — but confidently. # Example Production Workflow **Before Deployment** ``` wheels assets clean wheels assets precompile ``` **If Something Feels Off** ``` wheels assets clobber wheels assets precompile ``` **CI/CD Example** `wheels assets precompile || exit 1` Automated builds become reliable and predictable. # How These Commands Improve Team Workflows They bring: * Standardized build processes * Cleaner deployment cycles * Faster load times * Reduced caching bugs * Better frontend stability * Easier troubleshooting Instead of manually managing static files, everything is controlled via CLI — just like databases, environments, and plugins. # The Bigger Picture Earlier development workflows often mixed runtime asset handling with manual production steps. Wheels 3.x introduces structured asset lifecycle management. Just like: * Database commands manage data * Environment commands manage configuration * Testing commands ensure quality * Plugin commands extend functionality Asset commands manage performance and deployment consistency. This completes the development lifecycle. # What This Means for Wheels Developers With precompile, clean, and clobber, you gain: * Faster production performance * Reliable build processes * Cleaner deployments * Reduced frontend-related bugs * Better CI/CD automation Assets are no longer an afterthought. They are part of your deployment discipline. # Conclusion The Wheels CLI asset commands in 3.x bring structure to frontend asset management: * `assets precompile` → Prepare for production * `assets clean` → Remove outdated builds * `assets clobber` → Reset everything completely If environment commands help you deploy safely… If testing commands help you ensure quality… If plugin commands help you extend your app… Asset commands help you deliver performance. And in modern web development, performance is not optional — it’s expected. Stay tuned for more deep dives into the evolving Wheels CLI ecosystem.

March 19, 2026 by Zain Ul Abideen

Wheels CLI Plugin Commands: search, install, remove & init

# Introduction So far in this series, we’ve explored how the Wheels CLI in 3.x helps you manage your application key points and main aspects. Now we are discussing one of the strengths of Wheels, which has always been its extensibility. With Wheels 3.x, plugin management has evolved into a complete lifecycle experience within the CLI. In earlier versions of Wheels, we already had plugin-related commands such as: `wheels plugin list` This allowed developers to quickly see which plugins were installed inside an application and verify their presence. However, installation and management were still largely manual processes. Plugins allow you to: * Add reusable functionality * Share common solutions across project * Integrate third-party services * Extend framework behavior * Standardize patterns across teams The framework now provides structured commands to discover, install, remove, and even scaffold plugins — all without leaving your terminal. The CLI now supports: ``` wheels plugins search wheels plugins install wheels plugins remove wheels plugins init ``` This shift brings several advantages: * Centralized plugin discovery * Consistent installation across teams * Clean and safe removal * Faster onboarding for new developers * Ability to scaffold reusable internal plugins * Reduced manual file handling errors Instead of manually downloading, copying, and configuring plugin folders, everything can now be managed directly from the CLI. What used to be a manual setup task is now a structured, repeatable workflow — aligned with modern development practices. # Why Plugin CLI Commands Matter Traditionally, managing plugins meant: * Searching documentation or GitHub manually * Downloading zip files * Copying folders into /plugins * Managing dependencies manually * Removing plugins by deleting directories This process was: * Inconsistent * Error-prone * Hard to standardize across teams The new CLI plugin commands bring: * Discoverability * Automation * Clean installation * Safe removal * Scaffolding for new plugins It makes plugin management modern and developer-friendly. # wheels plugins search **Discover Available Plugins** `wheels plugins search authenticateThis` This command lets you search for available plugins by keyword. Instead of browsing repositories manually, you can: * Search by functionality * Explore plugin descriptions * See available versions * Identify compatible plugins **When to Use It** * Looking for caching solutions * Searching for authentication helpers * Exploring logging enhancements * Finding integrations (payment, email, etc.) It turns plugin discovery into a quick CLI action instead of a research task. # wheels plugins install **Install Plugins Cleanly** `wheels plugins install authenticateThis` This command: * Downloads the plugin * Places it in the correct directory * Handles necessary setup steps * Registers it properly within the app No manual folder copying. No guesswork. **Benefits** * Standardized installation * Reduced setup errors * Faster onboarding * Clear version control For teams, this is huge. Instead of sending plugin files manually, you simply say: `“Run wheels plugins install xyz.”` Consistent. Repeatable. Clean. # wheels plugins remove **Remove Plugins Safely** `wheels plugins remove authenticateThis` Instead of manually deleting plugin directories and hoping nothing breaks, this command: * Removes the plugin cleanly * Updates internal references * Keeps the application structure organized **Why This Matters** Manual removal can leave: * Unused config entries * Stray files * Broken dependencies The CLI ensures a structured uninstall process. Cleaner codebase. Less technical debt. # wheels plugins init **Scaffold Your Own Plugin** `wheels plugins init myCustomPlugin` This command creates the basic structure for a new plugin. It generates: * Required directories * Boilerplate files * Plugin configuration * Proper structure following Wheels conventions **Why This Is Powerful** If your team builds reusable features across multiple apps: * Custom validation logic * Shared integrations * Common business utilities * Internal framework extensions You can now package them as plugins easily. Instead of copying code between projects, you create a proper plugin once — and reuse it everywhere. # Real-World Workflow Example **Discover a Plugin** `wheels plugins search i18n` **Install It** `wheels plugins install wheels-i18n` **Confirm Installation** `wheels plugin list` **Remove If No Longer Needed** `wheels plugins remove wheels-i18n` **Build Your Own** `wheels plugins init companyAuth` Everything stays structured and reproducible. # Team & CI/CD Benefits These commands support: * Faster onboarding * Standardized project setup * Automated plugin installation in pipelines * Cleaner version control * Reduced manual steps For example, in CI: `wheels plugins install paymentGateway` The environment is ready instantly. # The Bigger Evolution of Wheels CLI In older versions, plugin management was mostly manual, with only listing support available. Wheels 3.x expands that capability into: * Plugin discovery * Automated installation * Structured removal * Plugin scaffolding This reflects a broader philosophy shift: The CLI is no longer just for generating controllers and models. It’s becoming: * A project manager * A dependency manager * An automation tool * A development assistant # What This Means for Wheels Developers With search, install, remove, init, and plugin list, you gain: * Faster project setup * Cleaner dependency management * Better reusability * Stronger team consistency * Simplified maintenance Plugins are no longer “extra files.” They are first-class components of your application architecture. And the CLI treats them that way. # Conclusion The Wheels CLI plugin commands in 3.x modernize how developers extend their applications. * `plugins search` → Discover functionality * `plugins install` → Add it cleanly * `plugins remove` → Remove it safely * `plugins init` → Build your own * `plugin list` → Track what’s installed If database commands help you manage data… If testing commands help you ensure quality… Plugin commands help you extend your app intelligently. And in modern development, intelligent extensibility is everything. Stay tuned — more Wheels CLI deep dives are coming.

March 13, 2026 by Zain Ul Abideen

Wheels CLI Testing Commands: run, all, unit, integration, watch & coverage

# Introduction In previous articles, we explored how the Wheels CLI helps you manage environments, configuration, and databases safely in Wheels 3.x. Now we’re stepping into one of the most critical parts of modern development: # Testing automation. Writing tests is important. Running them consistently, efficiently, and intelligently is even more important. Whether you're: * Fixing a bug * Refactoring a model * Building a new feature * Reviewing a pull request * Preparing for deployment * Running CI/CD pipelines You need fast, reliable test execution. That’s where the Wheels CLI testing commands come in: ``` wheels test run wheels test all wheels test unit wheels test integration wheels test watch wheels test coverage ``` These commands transform testing from a manual step into a structured development workflow. # Why CLI-Based Testing Matters Without proper CLI testing tools, developers often: * Run tests inconsistently * Forget to run certain test suites * Skip integration tests * Manually check coverage * Run full test suites unnecessarily * Waste time rerunning everything The Wheels CLI standardizes test execution. It makes testing: * Repeatable * Targeted * Automated * CI-friendly * Developer-friendly Testing becomes part of your daily workflow — not a separate task. # wheels test run Run Tests Quickly `wheels test run` This is your primary test execution command. It runs your default configured test suite. Use it when: * You’ve made changes * You’re about to commit * You’re verifying a bug fix * You’re checking regression impact It’s your go-to command for daily development. # wheels test all **Execute Everything** `wheels test all` This runs: * Unit tests * Integration tests * Full application tests Use it when: * Preparing for deployment * Running CI builds * Verifying a major refactor * Ensuring full system stability This gives you complete confidence before shipping. # wheels test unit **Fast, Focused Feedback** `wheels test unit` Unit tests are: * Fast * Isolated * Focused on small pieces of logic They test: * Models * Services * Helpers * Utility functions Run this when: * Refactoring business logic * Updating model behavior * Testing validation rules * Working on isolated components Unit tests provide rapid feedback. They should run in seconds. # wheels test integration **Test Real Interactions** `wheels test integration` Integration tests validate how components work together. They typically cover: * Controller → Model interactions * Database queries * API endpoints * Authentication flows * Request lifecycles These tests are slower than unit tests — but far more comprehensive. Use them when: * Updating controllers * Modifying routes * Changing database behavior * Adjusting authentication * Testing real request flows Integration tests protect against system-level regressions. # wheels test watch **Continuous Testing During Development** `wheels test watch` This command monitors your project files. When changes are detected, Tests automatically rerun. This creates a powerful development loop: 1. Edit code 2. Save 3. Tests rerun instantly 4. See failures immediately It encourages: * Test-driven development (TDD) * Faster debugging * Immediate feedback * Higher code quality No more manually re-running tests after every change. # wheels test coverage **Measure Code Coverage** `wheels test coverage` Running tests is good. Knowing what they actually cover is better. This command generates a coverage report showing: * Percentage of code covered * Untested files * Uncovered lines * Weak testing areas Coverage helps you: * Identify missing test cases * Improve test completeness * Strengthen critical components * Enforce quality standards It transforms testing from reactive to strategic. # How These Commands Work Together Here’s a modern development workflow: **Daily Development** `wheels test unit` Fast feedback while coding. **After Feature Completion** `wheels test integration` Validate system behavior. **Before Commit** `wheels test run` Quick verification. **Before Deployment** ``` wheels test all wheels test coverage ``` Full confidence check. **During Active Development** `wheels test watch` Continuous feedback loop. Each command serves a specific purpose. Together, they create a complete testing ecosystem. # CI/CD Integration These commands are designed to work seamlessly in pipelines: **wheels test all || exit 1** If tests fail, deployment stops. Add coverage thresholds for quality enforcement: * Require minimum coverage percentage * Block deployment if below standard * Track coverage trends over time This makes testing not just a developer tool — but a deployment safeguard. # The Bigger Picture Older CLI tools focused mainly on scaffolding and generation. Wheels 3.x CLI emphasizes: * Observability * Environment safety * Configuration validation * Database lifecycle management * Automated testing Testing commands elevate the CLI into a full development companion. Modern development requires: * Fast iteration * Automated validation * Confidence before release * Clear quality metrics These testing commands deliver exactly that. # What This Means for Wheels Developers With **run**, **all**, **unit**, **integration**, **watch**, and **coverage**, you gain: * Faster debugging cycles * Stronger code quality * Safer refactoring * CI-ready workflows * Continuous feedback * Measurable quality standards Testing stops being optional. It becomes integrated. And when testing becomes effortless, quality naturally improves. # Conclusion The Wheels CLI testing commands in 3.x bring structure and power to your development workflow: * `test run` → Quick verification * `test all` → Full system validation * `test unit` → Fast, focused checks * `test integration` → Real-world confidence * `test watch` → Continuous feedback * `test coverage` → Quality measurement If database commands help you manage data… If environment commands help you deploy safely… Testing commands help you build with confidence. And in modern development, confidence is everything. Stay tuned — more Wheels CLI deep dives are coming. https://youtu.be/L2Z5bxcgVwE

March 09, 2026 by Zain Ul Abideen

Wheels CLI Database Commands: db create & db drop

# Introduction So far in this series, we’ve explored how the Wheels CLI in 3.x helps you inspect your application, manage configuration, and control environments safely. Now we’re moving into something even more foundational: **database lifecycle management**. Your application might have clean code and perfectly aligned environments — but without a properly provisioned database, nothing works. In a Wheels application, the database is not just storage. It powers: * Migrations * Application data * Session handling * Background jobs * Automated tests * API responses It’s core infrastructure. And whether you're: * Setting up a new project * Onboarding a teammate * Preparing a staging server * Resetting a development database * Cleaning up after automated CI tests You’ll eventually need to create or drop a database. Traditionally, this meant: * Logging into the database server manually * Running raw SQL commands * Managing permissions * Double-checking you weren’t targeting production * Repeating the same setup steps across environments It was manual. It was inconsistent. And sometimes — risky. Wheels CLI simplifies this by using your existing environment and datasource configuration to manage database provisioning directly from your project root safely. That’s where these two powerful commands come in: ``` wheels db create wheels db drop ``` Simple in appearance. Powerful in impact. # Why Database CLI Commands Matter Traditionally, creating or dropping databases meant: * Logging into SQL Server / MySQL / PostgreSQL manually * Running SQL scripts * Managing permissions * Copying credentials * Risking mistakes In team environments, this creates friction: * “What’s the correct database name?” * “Which server do I connect to?” * “Is this staging or production?” * “Did I just drop the wrong database?” The Wheels CLI eliminates this confusion by using your existing environment configuration. It knows: * Your datasource * Your database name * Your environment * Your credentials And it acts accordingly. # wheels db create Create a Database Instantly `wheels db create` This command creates the configured database for your active environment. It reads: * Environment settings * Datasource configuration * Database name * Connection credentials Then it provisions the database automatically. **When to Use db create** New Project Setup: ``` wheels environment show wheels db create ``` Your local database is ready — no manual SQL required. Onboarding a Team Member: Instead of sending setup documentation with SQL instructions: *“Just run wheels db create.”* It standardizes project setup. Automated Test Environments: In CI pipelines: `wheels db create` The database is created dynamically for testing. After tests complete, it can be dropped cleanly. **What Happens Behind the Scenes:** The command: 1. Connects to your DB server 2. Checks whether the database exists 3. Creates it if missing 4. Validates permissions 5. Confirms success It respects your current environment. That means: If you are in development → It creates the development DB. If you are in staging → It creates the staging DB. No cross-environment confusion. # wheels db drop Drops the configured database. This command permanently deletes a database. This is a destructive operation that cannot be undone. `wheels db drop` This command drops the database for the active environment. Used carefully, it’s extremely powerful. Used recklessly, it’s dangerous. That’s why environment awareness is critical. **When to Use db drop** Resetting Development: Need a clean slate? ``` wheels db drop wheels db create ``` Now you have a fresh database. Perfect for schema resets or major refactors. Rebuilding After Migration Changes: If migrations changed significantly: ``` wheels db drop wheels db create wheels db migrate latest ``` You’re back to a fully rebuilt database. CI/CD Cleanup: In automated pipelines: `wheels db drop` Removes temporary test databases after completion. **Safety First: Environment Awareness** Before running db drop, always confirm your environment: `wheels environment show` Dropping a production database accidentally is catastrophic. That’s why best practice is: 1. Confirm environment 2. Validate settings 3. Then execute database commands # Example Safe Workflow Step 1 – Confirm Environment `wheels environment show` Step 2 – Validate Environment `wheels environment validate` Step 3 – Drop (if safe) `wheels db drop` Step 4 – Recreate `wheels db create` This structured process prevents irreversible mistakes. # Real-World Development Scenarios **Scenario 1: Local Development Reset** You’ve been experimenting with schema changes. Your database is messy. Instead of manually cleaning tables: ``` wheels db drop wheels db create ``` Clean slate. Fresh start. Zero manual SQL. **Scenario 2: Staging Server Preparation** Before pushing new features: ``` wheels environment switch staging wheels db create ``` Ensures staging DB exists and matches configuration. **Scenario 3: Automated Testing** Your CI workflow: ``` wheels environment set testing wheels db create wheels test run wheels db drop ``` Fully automated lifecycle. No manual intervention. # How These Commands Improve Team Workflows They: * Standardize database setup * Reduce onboarding friction * Eliminate manual SQL steps * Prevent configuration mismatches * Support automated pipelines * Encourage safe environment practices In modern development, repeatability matters. These commands make database setup repeatable. # The Bigger Philosophy Earlier CLI tools focused on scaffolding code. Wheels 3.x CLI is evolving into: * An environment manager * A configuration validator * A deployment assistant * A database lifecycle controller Applications aren’t just code. They are infrastructure + configuration + environments + data. Managing databases via CLI is a natural evolution. # Important Best Practices Before using database commands: * Always confirm environment * Never drop production unless intentional * Use validation commands * Automate in CI when possible * Keep credentials secure Treat database commands with respect. They’re powerful by design. # Conclusion The new database commands in Wheels CLI 3.x simplify one of the most critical parts of application management. `wheels db create` → Instantly provision databases `wheels db drop` → Cleanly remove databases Together, they: * Speed up development * Simplify onboarding * Enable automation * Support safe workflows * Reduce manual SQL tasks If scaffolding commands help you build faster… Environment commands help you deploy safer… These database commands help you reset, rebuild, and automate smarter. And in modern development, controlled data management is everything. Stay tuned — more Wheels CLI deep dives are coming. Learn more here: https://youtu.be/HYXg5CtxrYQ

March 05, 2026 by Zain Ul Abideen

wheels.dev Goes Public: A Production Wheels 3.0 Application You Can Actually Study

Most framework documentation tells you *how* to build something. The Wheels community site at wheels.dev is something different -- it's a production application built with Wheels 3.0 that you can actually look at, poke around, and learn from. We've made the source public, and this article walks through how the site is built, how it's deployed, and how it comes to life inside a Docker Swarm. ## Why Make the Site Public? Framework examples tend to be toy applications. They show you the syntax but not the patterns. They demonstrate a feature in isolation but never show you how thirty features work together in something real. wheels.dev is a real application with real users. It has a blog system with moderation workflows, user authentication with role-based access control, a documentation viewer, newsletter management, an admin dashboard, and a full API layer. It handles file uploads, session clustering across multiple replicas, transactional email, and error tracking. It's the kind of application that exposes the decisions frameworks force you to make -- and shows how Wheels 3.0 handles them. By making the source public, we're turning the community site into the most comprehensive Wheels 3.0 example that exists. ## The Architecture At its core, wheels.dev follows the MVC pattern that Wheels is built around, but scaled to production complexity. ### Models: 31 ActiveRecord Components The data layer uses Wheels' ActiveRecord ORM with 31 model components. The `Blog` model alone demonstrates associations (`belongsTo` User, `hasMany` Comments, Tags, Categories, and ReadingHistory), validations, callbacks, and soft deletes tracked through `deletedAt` and `deletedBy` columns. The `User` model handles password hashing via bcrypt, role associations, and relationships to everything a user can create or interact with. Other models handle the supporting infrastructure: `RememberToken` for persistent login sessions, `PasswordReset` for email-based recovery flows, `LoginAttempt` for security tracking, `Newsletter` and `NewsletterSubscriber` for email campaigns, `Testimonial` with an approval workflow, and `CachedRelease` for caching ForgeBox release data. The database runs on CockroachDB, accessed through a standard PostgreSQL JDBC driver -- CockroachDB speaks the PostgreSQL wire protocol, so Wheels connects to it like any other Postgres database. The schema is managed entirely through timestamped migration files -- over 20 of them covering 25+ tables with foreign key constraints, indexes, and referential integrity. And yes, we're dogfooding here. Wheels currently supports six databases: MySQL, PostgreSQL, SQL Server, H2, Oracle, and SQLite. Running the community site on CockroachDB is our way of putting a seventh database adapter through its paces in production. Anybody hear a seventh supported database coming? ### Controllers: Three Namespaces Controllers are organized into three distinct namespaces, each serving a different concern: - **`web.*`** handles public-facing pages -- the homepage, blog listing and detail views, guides, documentation, community pages, and authentication flows - **`admin.*`** powers the dashboard for content moderation, user management, settings, newsletter administration, and testimonial approval - **`api.*`** exposes RESTful endpoints for blog content, downloads, and authentication A base `Controller.cfc` provides shared infrastructure: CSRF protection via `protectsFromForgery()`, authentication helpers, role-based access checks, and reusable query methods for fetching blogs with their associated tags, categories, and attachments. ### Routing: RESTful by Convention The routing configuration in `config/routes.cfm` demonstrates Wheels' mapper DSL at scale. API routes live under `/api/v1/` with proper REST verb mapping. The blog supports filtering by category, author, and tag through clean URLs like `/blog/categories/[slug]`. Admin routes are grouped under `/admin/` with consistent CRUD patterns. The guides system supports versioned paths (`/3.0.0/guides/[path]`) for serving documentation across framework releases. ### Views: Server-Rendered with HTMX The view layer uses CFML templates with a main `layout.cfm` that handles page titles, meta tags, and content-specific rendering. Where dynamic interactivity is needed -- loading comments, filtering blog posts, toggling UI states -- the site uses HTMX rather than a JavaScript framework. This keeps the architecture simple: the server renders HTML fragments, and HTMX swaps them into the page without full reloads. ## Features Worth Studying Several features in the codebase demonstrate patterns that go beyond what you'd find in a tutorial. ### Authentication and Session Management User authentication supports registration with email verification, login with bcrypt password hashing, and a "Remember Me" system that stores hashed tokens with user-agent validation. If someone's token doesn't match their current browser fingerprint, the token is invalidated -- a practical defense against session theft. Sessions are configured with a 2-hour timeout and a 30-minute idle logout, with session storage backed by CockroachDB so that sessions persist across container restarts and are shared across all Swarm replicas. The `onRequestStart` event handler checks for idle timeouts and validates remember-me tokens on every request. ### Role-Based Access Control The permission system uses a `User -> Role -> Permission` hierarchy. Controllers check access through methods like `checkAdminAccess()` and `checkRoleAccess()`, gating entire controller actions based on the authenticated user's role. The admin namespace uses before-filters to enforce this consistently. ### Blog Content Workflow Blog posts follow a multi-status lifecycle: Draft, Pending Approval, Approved, and Rejected. Authors create and submit posts; administrators moderate them through the admin dashboard with bulk actions. Comments have their own moderation queue. Reading history and bookmarks are tracked per user. The system generates XML sitemaps and RSS-compatible comment feeds. ### Caching Strategy The site uses a 10-minute RAM cache for frequently accessed queries and a dedicated cache for contributor data that's expensive to fetch from external sources. This caching layer is configured in `config/app.cfm` and works transparently with the ORM. ## How the Site is Deployed The deployment pipeline is triggered by any push to the `main` branch of the wheels.dev repository. Here's what happens. ### Building the Container A GitHub Actions workflow runs on a standard Ubuntu runner. It generates an environment file from encrypted GitHub Secrets -- connection details for the CockroachDB cluster, SMTP credentials for Postmark (transactional email), a Sentry DSN for error tracking, an ID salt for obfuscating database identifiers in URLs, and admin passwords. The workflow installs CommandBox (a CFML build tool and dependency manager), runs `box install` to pull all dependencies including the Wheels core framework, and builds a Docker image. The Dockerfile starts from `ortussolutions/commandbox:lucee6`, adds a PostgreSQL JDBC driver, copies in the application code and a production-tuned `server.json`, and disables the browser auto-launch that CommandBox includes for local development. The image is tagged with both `:latest` and the Git commit SHA, then pushed to GitHub Container Registry. ### Deploying to the Swarm A self-hosted GitHub Actions runner inside the Docker Swarm cluster picks up the deployment job. It authenticates with the container registry and runs `docker stack deploy`, which reconciles the running state with the desired state defined in `docker-compose.yml`. The stack deploys **three replicas** of the application. Rolling updates proceed one container at a time with a 15-second delay, using a start-first strategy -- the new replica must be running and healthy before the old one is removed. Rollbacks follow the same one-at-a-time pattern with a 10-second delay. Each replica gets up to 2 CPUs and 4 GB of memory, with the JVM tuned to a 2 GB minimum and 3 GB maximum heap. A Traefik reverse proxy handles load balancing and routing based on the `Host` header. Because sessions are stored in CockroachDB with clustering enabled, any replica can serve any request -- there's no need for sticky sessions or session affinity cookies. ### Shared Storage One of the trickier aspects of running a stateful web application across multiple replicas is file storage. Uploaded images, file attachments, generated sitemaps, versioned documentation, and API JSON responses all need to be accessible from every replica. The solution is CephFS-backed volumes mounted into each container at specific paths: `/app/public/images`, `/app/public/files`, `/app/public/sitemap`, `/app/docs/3.0.0/guides`, and `/app/public/json`. When a user uploads an image through replica 1, replicas 2 and 3 can serve it immediately. A separate `/data` volume provides general application state storage that persists across deployments. ### The Warmup Sequence This is one of the most important parts of the deployment, and it's easy to overlook. CFML applications running on the JVM suffer from cold-start latency -- the first request to any template triggers compilation, class loading, and JIT warm-up. In a user-facing application, that first request could take several seconds. The `server.json` configuration includes a warmup directive that fires immediately after the server starts, before it begins accepting external traffic: ``` /index.cfm, /blog, /blog/list, /blog/Categories, /guides, /3.0.0/guides, /api, /api/3.0.0/, /docs, /community, /news, /downloads, /login ``` These 13 URLs are hit sequentially with a 5-minute timeout window using a queued request strategy. By the time the replica joins the Swarm's load balancer rotation, every major route has been compiled, the template cache is warm, database connection pools are established, and the JVM has had a chance to JIT-compile the hot paths. The result: users never hit a cold replica. ### The Network Edge External traffic reaches the application through a Cloudflare tunnel, which handles TLS termination, DDoS protection, and edge caching. Inside the Swarm, Traefik routes requests to the three replicas over an overlay network. A middleware rule redirects `www.wheels.dev` to the apex `wheels.dev` domain. ## What Makes It a "Model" Application The term "model application" means something specific here. It's not just that wheels.dev runs on Wheels -- it's that every architectural decision in the codebase represents a recommended pattern. The controller namespacing (`web`, `admin`, `api`) shows how to organize a growing application. The base controller demonstrates cross-cutting concerns like authentication and CSRF protection. The model layer shows associations, validations, and soft deletes working together in a real schema. The routing configuration demonstrates RESTful conventions, versioned API paths, and clean URL patterns. The migration files show incremental schema evolution. The deployment configuration shows how a Wheels application transitions from development to production: environment-specific config overrides, container-based deployment, session clustering, shared storage, and zero-downtime updates. It's the complete picture -- not a tutorial, not a toy, but a running application that developers can study, fork, and learn from. ## Get Involved The wheels.dev source is public. Browse the code, open issues, suggest improvements, or use it as a reference for your own Wheels 3.0 projects. The repository includes a `CLAUDE.md` with AI-assisted development guidance and a comprehensive README to help you get oriented. If the best documentation is working code, then wheels.dev is the best Wheels 3.0 documentation we could write.

March 05, 2026 by Peter Amiri

Behind the Scenes: How a Single Commit Becomes a Running Application Across 40+ Configurations

When a developer opens a pull request against the Wheels framework, it kicks off one of the most comprehensive CI/CD pipelines you'll find in any open-source project. Whether you're a first-time contributor fixing a typo or a core maintainer shipping a new feature, the moment your PR hits the `develop` branch, the same gauntlet runs: dozens of engine and database combinations are tested, four distinct packages are built and published to a package registry, documentation is synced, container images are built, and a production Docker Swarm deployment rolls out -- all without a single manual intervention. You don't need commit access to trigger this. You just need a pull request. This is the story of how that sausage gets made. ## The Scale of the Problem Wheels is a Rails-inspired MVC framework for CFML (ColdFusion Markup Language). Unlike most frameworks that target a single runtime, Wheels supports **eight different server engines** -- Lucee 5, 6, and 7, Adobe ColdFusion 2018, 2021, 2023, and 2025, and the new BoxLang runtime. It also supports **six different databases**: MySQL, PostgreSQL, SQL Server, H2, Oracle, and SQLite. That matrix creates over 40 unique test configurations. Every one of them runs on every commit to the development branch. There are no shortcuts. ## Stage 1: The Test Matrix When a commit lands on the `develop` branch, GitHub Actions fires the `snapshot.yml` workflow, which immediately calls a reusable `tests.yml` workflow. This is where things get interesting. The test matrix spins up parallel jobs for each valid engine-and-database combination. Some pairs are excluded -- Adobe 2018 doesn't support SQLite, for example -- but the remaining combinations all run simultaneously. Each job follows the same sequence: 1. **Start the CFML engine container** on a dedicated port (Lucee 5 gets port 60005, Adobe 2023 gets 62023, and so on) 2. **Start the database container** (except for embedded databases like H2 and SQLite) 3. **Wait for both services** with retry logic to handle cold-start delays 4. **Patch compatibility files** where needed -- Oracle on Adobe engines requires a serialization filter update 5. **Install engine-specific packages** via the CFML package manager 6. **Execute the full test suite** via HTTP, passing the database type as a parameter 7. **Capture and upload results** as JSON artifacts with detailed workflow logs Each engine gets its own purpose-built Docker image. The Lucee images include H2, Oracle JDBC extensions, and SQLite drivers. The Adobe images handle their own package management quirks. BoxLang runs on its own runtime entirely. The test infrastructure treats each engine as a first-class citizen, not an afterthought. If even one of those 40+ jobs fails, the pipeline stops. Nothing gets published until the entire matrix is green. ## Stage 2: Four Packages, One Pipeline Once the test matrix passes, the release pipeline takes over. Wheels isn't distributed as a single monolithic package -- it's split into four distinct artifacts, each with its own purpose: - **Wheels Core**: The framework engine itself -- routing, ORM, controllers, views, and the internal machinery - **Wheels Base Template**: The application scaffold that developers start new projects from - **Wheels CLI**: Command-line tooling for scaffolding, migrations, and development workflows - **Wheels Starter App**: A ready-to-run example application for learning Each package has its own preparation script that assembles the right files, replaces version placeholders (like `@build.version@` and `@build.number@`), and structures the output for publishing. The version string itself carries meaning: `3.0.0` is a stable release, `3.0.0-rc.1` is a release candidate, and `3.0.0-SNAPSHOT` marks bleeding-edge development builds. A build number suffix (e.g., `+1234`) tracks the exact CI run. After preparation, each package goes through validation -- checking that `box.json` manifests parse correctly, file counts match expectations, and version strings are consistent. Only then does the pipeline authenticate with ForgeBox (the CFML package registry) and publish all four packages. The pipeline also builds ZIP archives with MD5 and SHA512 checksums, uploading them as GitHub Actions artifacts and attaching them to GitHub Releases with auto-generated release notes pulled from the changelog. ## Stage 3: Documentation Sync In parallel with package publishing, the pipeline syncs framework documentation to the community website. A dedicated `docs-sync.yml` workflow checks out both the framework repository and the website repository, then uses `rsync` to synchronize: - **Guide content** (Markdown files) flows from the framework's `docs/src/` directory into the website's versioned guides path - **Image assets** are copied additively so that old screenshots aren't accidentally removed - **API documentation** (JSON) is synced to the website's public directory for the interactive API browser If any files changed during the sync, the workflow commits and pushes to the website repository automatically. This triggers the next stage. ## Stage 4: Container Build When the website repository receives a push to `main` -- whether from a documentation sync or a direct code change -- the `swarm-deploy.yml` workflow fires. This is where the application becomes a container. The build job runs on a standard GitHub-hosted Ubuntu runner. It generates an environment file from GitHub Secrets containing database credentials, SMTP configuration for transactional email, a Sentry DSN for error tracking, and various application secrets. It installs CommandBox (the CFML build tool), pulls all dependencies, and builds a Docker image. The base image is `ortussolutions/commandbox:lucee6`, which provides a Lucee 6 runtime managed by CommandBox. The Dockerfile layers on a PostgreSQL JDBC driver, copies the application code, and includes a production-tuned `server.json` that configures JVM heap sizes, connection pools, and the server warmup sequence. The resulting image gets tagged twice -- once with `:latest` and once with the Git commit SHA for traceability -- then pushed to GitHub Container Registry (GHCR). ## Stage 5: Swarm Deployment The final stage runs on a self-hosted GitHub Actions runner that lives inside the Docker Swarm cluster itself. This runner authenticates with GHCR, pulls the freshly-built image, and executes `docker stack deploy`. The Swarm configuration deploys **three replicas** of the application behind a Traefik reverse proxy. Rolling updates proceed one replica at a time with a 15-second delay between each, using a start-first strategy -- meaning the new container must be healthy before the old one is removed. This ensures zero-downtime deployments. Each replica is allocated up to 2 CPUs and 4 GB of memory, with reserved minimums of 0.25 CPUs and 1 GB to guarantee baseline performance. The JVM is tuned with a 2 GB minimum and 3 GB maximum heap, sized to fit comfortably within the container's memory limit. Sessions are stored in the database with clustering enabled, so any replica can serve any request -- no sticky sessions required. Traefik handles load balancing and TLS termination, while a Cloudflare tunnel provides the public-facing edge with DDoS protection and global CDN caching. Shared storage volumes backed by CephFS allow all three replicas to access the same uploaded images, file attachments, generated sitemaps, and documentation content. This is critical -- without shared storage, a file uploaded through one replica would be invisible to the others. ## The Full Picture Here's what happens in the roughly 15-20 minutes between a developer pushing to `develop` and the changes being live: ``` git push origin develop | v GitHub Actions: snapshot.yml | v 40+ parallel test jobs (8 engines x 6 databases) | v (all green) +---> Package 4 artifacts (core, base, cli, starter-app) +---> Validate and publish to ForgeBox +---> Upload to GitHub Releases with checksums +---> Sync documentation to wheels.dev repo | v wheels.dev repo receives push | v Build Docker image on ubuntu-latest | v Push to GitHub Container Registry | v Self-hosted runner deploys to Docker Swarm | v 3 replicas with rolling updates | v Live at wheels.dev ``` ## Why This Matters For a framework that promises to run anywhere -- on any supported engine, against any supported database -- the CI/CD pipeline is the proof. It's not enough to claim compatibility; every commit verifies it across every combination. The four-package distribution model means developers install only what they need. The automated documentation pipeline means the website is never stale. The container-based deployment with rolling updates means releases happen without anyone noticing downtime. Is this level of orchestration overkill for an open-source CFML framework? Maybe. But for the developers who depend on Wheels in production, knowing that every commit survives a gauntlet of 40+ test configurations before it ever reaches them -- that's not overkill. That's trust.

March 03, 2026 by Peter Amiri

Wheels CLI Environment Commands: set, show, merge, switch & validate

# Introduction In our previous deep dives, we explored how the Wheels CLI helps you inspect your application and validate configuration. Now we’re focusing on something even more critical: # Environment management. Modern applications don’t run in just one mode. They operate across: * development * testing * staging * production * maintenance Managing these environments safely and consistently is essential — especially in Wheels 3.x. This article explores five powerful environment-focused commands: * wheels environment set * wheels environment show * wheels environment merge * wheels environment switch * wheels environment validate These commands are about control, safety, and clarity. Because in real-world development, environment mistakes are expensive. # Why Environment Management Matters Environment confusion causes real problems: * Debug mode accidentally enabled in production * Production database credentials used locally * Caching disabled in staging * Environment variables not loaded correctly * CI/CD pipelines pointing to the wrong configuration These mistakes aren’t code issues. They’re environment issues. The new environment commands in Wheels CLI are designed to prevent exactly that. # wheels environment show **See Your Active Environment Instantly** `wheels environment show` This command tells you: * Which environment is currently active * How it was detected * Which configuration files are being loaded * Relevant environment variables No guessing. No assumptions. If something feels “off,” this is your first command. **Why environment show Is Important** You might think you're in staging. But are you really? Running: `wheels environment show` Confirms it immediately. This prevents: * Accidental deployments * Incorrect database connections * Misaligned debugging settings Clarity before action. # wheels environment set **Explicitly Define Your Environment** `wheels environment set staging` This command allows you to explicitly define the active environment. Instead of relying only on system variables or automatic detection, you can directly control it. **When to Use environment set** * Preparing for deployment * Testing production-like behavior locally * Simulating staging configuration * Overriding default detection temporarily It gives you precision. **Why It Matters** Sometimes environment detection depends on: * Server variables * Hostnames * System environment variables * CI/CD configuration If those aren’t set correctly, unexpected behavior occurs. **environment set** eliminates uncertainty. You choose the environment. # wheels environment switch **Seamlessly Move Between Environments** `wheels environment switch production` While **set** defines the environment, **switch** is optimized for fast transitions during development workflows. Think of it as: * Quick toggling between dev and staging * Testing configuration differences * Reproducing environment-specific bugs **Real-World Scenario** You discover a bug that only happens in production. Instead of deploying blindly: `wheels environment switch production` Now your local app mirrors production behavior. You debug confidently. Then switch back: `wheels environment switch development` Fast. Controlled. Safe. # wheels environment merge **Combine Environment Configurations** `wheels environment merge staging production` The `merge` command allows you to merge configuration values from one environment into another. This is powerful during: * Preparing staging to match production * Promoting tested configuration forward * Synchronizing environment improvements **Why environment merge Is Powerful** Instead of manually copying configuration changes: * It standardizes updates * Reduces human error * Ensures consistency * Speeds up promotion workflows This is especially useful in structured release processes. Example Workflow 1. Test new config in staging 2. Validate everything works 3. Run: `wheels environment merge staging production` Now production inherits the verified configuration. Clean promotion. Less risk. # wheels environment validate **Protect Against Environment Mistakes** `wheels environment validate` This command checks: * Required environment variables exist * Critical settings are properly defined * Production safeguards are enabled * No unsafe debug flags are active * Database connections match expectations Think of it as an environment safety audit. **When to Use environment validate** Before Deployment Always run: `wheels environment validate` Especially before production deployments. It can prevent: * Debug mode in production * Missing secret keys * Incorrect datasource names * Disabled caching **During CI/CD Pipelines** Add it to your automated workflow. If validation fails, deployment stops. That’s modern DevOps discipline. # How These Commands Work Together Here’s a safe environment workflow: Step 1 – Confirm Current Environment `wheels environment show` Step 2 – Switch if Necessary `wheels environment switch staging` Step 3 – Validate Configuration `wheels environment validate` Step 4 – Merge Approved Changes `wheels environment merge staging production` Step 5 – Explicitly Set for Deployment `wheels environment set production` This structured approach prevents environment chaos. # The Bigger Evolution of Wheels CLI Earlier CLI generations focused heavily on: * Generating models * Creating controllers * Scaffolding applications Wheels 3.x is evolving beyond scaffolding. It now emphasizes: * Observability * Configuration management * Environment safety * Deployment confidence Modern development isn’t just about writing code. It’s about managing complexity. And environments are a major source of that complexity. These commands bring order to it. # What This Means for Wheels Developers With **set**, **show**, **merge**, **switch**, and **validate**, you gain: * Explicit environment control * Faster debugging * Safer deployments * Cleaner promotion workflows * Reduced configuration drift * Stronger team collaboration Environment mistakes are subtle — but costly. These commands dramatically reduce that risk. # Conclusion The new environment commands in Wheels CLI 3.x transform how you manage application modes. * environment show gives clarity * environment set gives control * environment switch gives speed * environment merge gives consistency * environment validate gives safety If earlier CLI commands helped you build faster… And inspection commands helped you debug smarter… These environment tools help you deploy safer. And in modern software development, safe environments mean stable applications. Stay tuned — more deep dives into Wheels CLI are coming.

March 02, 2026 by Zain Ul Abideen

Wheels CLI Config Commands: check, diff & dump

# Introduction In our previous article, Wheels CLI Essentials: Inspect Your App with about & get Commands, we explored how Wheels 3.x helps you understand your application's runtime state. Those commands focused on visibility. Now we go one layer deeper. This article introduces three powerful configuration-focused commands: * wheels config check * wheels config diff * wheels config dump These commands are not about what is running. They’re about how your configuration is structured, validated, and compared. If **about** and **get** gave you awareness, these commands give you control. # Why Configuration Commands Matter In modern applications, configuration complexity grows quickly: * Multiple environments * Default framework settings * Custom overrides * Team-specific environment variables * CI/CD configuration differences * Production hotfixes Over time, small configuration mismatches can cause major issues: * “It works on my machine.” * Staging behaves differently from production. * A default value overrides a custom setting. * A config file was edited but not deployed. The new config commands are built to prevent exactly these problems. They give you validation, comparison, and export tools — directly from the CLI. # wheels config check **Validate Your Configuration with Confidence** `wheels config check` The **check** command validates your configuration setup and ensures: * Required settings exist * No invalid configuration keys are present * Environment files are structured correctly * Overrides are applied properly * No conflicting definitions exist Think of it as a configuration health check. **When to Use config check** Before Deployment: Run it before pushing to staging or production: `wheels config check` This ensures: * No missing environment settings * No accidental debug flags * No incomplete overrides It acts like a pre-flight checklist. After Updating Configuration: Changed a config file? Added a new environment variable? Run: `wheels config check` It confirms everything is wired correctly. Why config check Is Powerful: * Prevents runtime configuration errors * Catches typos in setting names * Validates environment consistency * Encourages safe deployment practices Instead of discovering configuration errors in production… You catch them instantly. # wheels config diff **Compare Configuration Across Environments** `wheels config diff development production` The diff command compares configuration values between environments. It shows: * What differs * What exists in one environment but not another * What values are overridden This is extremely valuable in multi-environment workflows. **Why config diff Matters** Environment mismatches are one of the most common causes of bugs. Examples: * Caching enabled in production but not staging * Different datasource names * Different mail server settings * Logging levels not aligned Instead of manually comparing config files, run: `wheels config diff staging production` You instantly see differences in a clean, structured output. **Real-World Scenario** You deploy to production. Something behaves differently from staging. Instead of guessing: `wheels config diff staging production` Now you know: * Exactly what changed * Whether a setting was missed * Whether a production override is affecting behavior This command alone can save hours of manual inspection. **Why config diff Is Essential** * Eliminates manual file comparisons * Prevents environment drift * Improves team collaboration * Simplifies debugging In larger teams, configuration drift is inevitable. This command keeps environments aligned. # wheels config dump Export Your Full Configuration Snapshot `wheels config dump` The **dump** command outputs your complete resolved configuration. It includes: * Default framework settings * Application-level overrides * Environment-specific settings * Fully merged configuration values Think of it as a raw configuration export. **When to Use config dump** Auditing: Need to see everything at once? `wheels config dump` You get a complete configuration snapshot. **Debugging Complex Overrides** Sometimes a setting comes from: * Framework defaults * settings.cfm * Environment-specific files * System environment variables Instead of tracing multiple layers manually, dump shows the final resolved result. **Sharing Configuration Safely** When collaborating with teammates, you can: * Dump configuration * Review it together * Identify unexpected overrides It creates transparency. **Why config dump Is Valuable** Full visibility into final configuration state * Simplifies advanced debugging * Helps audit production setups * Encourages configuration discipline It removes ambiguity. # How These Commands Work Together Here’s a practical workflow: **Step 1 – Validate** `wheels config check` Ensure configuration structure is correct. **Step 2 – Compare** `wheels config diff staging production` Identify environment differences. **Step 3 – Export Snapshot** `wheels config dump` Review the full resolved configuration. Together, they form a powerful configuration management toolkit. # The Bigger Shift in CLI Philosophy Earlier versions of CLI tools focused primarily on: * Generating controllers * Creating models * Scaffolding applications Wheels 3.x is expanding beyond scaffolding. It’s becoming: * A configuration validator * An environment consistency enforcer * A debugging assistant * A deployment safety layer This shift reflects modern development needs. Applications today are not just code. They are configuration-driven systems. And configuration must be inspectable, verifiable, and comparable. # What This Means for Wheels Developers With config check, config diff, and config dump, you gain: * Safer deployments * Fewer environmental surprises * Faster debugging cycles * Better team collaboration * Stronger production confidence These are not flashy commands. They don’t generate files. They don’t create scaffolds. But they solve real-world development problems — the kind that cost time, trust, and production stability. # Conclusion The new configuration commands in Wheels CLI 3.x are small additions — but major upgrades to your workflow. * **wheels config check** protects you from configuration mistakes * **wheels config diff** prevents environment drift * **wheels config dump** gives you full transparency If previous CLI commands helped you build faster… These help you deploy more safely. And in modern software development, safe deployments are everything. Stay tuned — the next deep dive into Wheels CLI is coming. Learn more here: https://youtu.be/6RJWe3RQp1Q

February 26, 2026 by Zain Ul Abideen

Wheels CLI Essentials: Inspect Your App with about & get Commands

# Introduction In our previous article, [Wheels CLI: Modern Commands for Faster, Smarter Wheels 3.0 Development](https://wheels.dev/blog/wheels-cli-modern-commands-for-faster-smarter-wheels-3-0-development), we introduced the new generation of CLI capabilities coming to Wheels 3.x. That article focused on the big picture — how the CLI is evolving beyond scaffolding into a complete development companion. Now it’s time to zoom in. This article explores three powerful inspection commands that help you understand your application’s current state instantly: * wheels about * wheels get environment * wheels get settings These commands are not about generating code. They’re about visibility, awareness, and confidence. When debugging, deploying, or supporting an application, knowing your environment and configuration matters just as much as writing good code. # Why App Inspection Commands Matter Modern development environments are rarely simple. You may have: * Multiple environments (development, staging, production) * Different configuration overrides * Environment-specific settings * Multiple framework versions across projects * Team members working on different machines Without proper visibility, confusion happens quickly. Questions like: * “Which environment am I in?” * “Is caching enabled here?” * “Why is this behaving differently in staging?” * “What version of Wheels is this app using?” The new CLI inspection commands answer these instantly. * No digging through files. * No guessing. * No assumptions. Just clarity. # wheels about **Your Application’s Full Snapshot** The about command provides a complete overview of your Wheels application. `wheels about` It displays: * Wheels framework version * CFML engine information * Application name * Current environment * Configuration status * Key runtime details * Application statistics Think of it as your application’s diagnostic summary. **When to Use about** Debugging Issues: If something behaves unexpectedly, start with: `wheels about` You’ll quickly see: * Whether you’re in the correct environment * Which framework version is running * Whether configuration values are being picked up properly Support & Collaboration: When helping a teammate, the first question often is: “What version are you running?” Instead of manually checking files, they can simply run: `wheels about` It standardizes the way teams share environment information. Deployment Validation: After deploying to staging or production, you can verify: * Correct environment detection * Correct configuration loading * Framework version consistency It’s a fast sanity check before declaring deployment success. Why about Is Powerful: * Reduces troubleshooting time * Prevents environment confusion * Makes support conversations easier * Encourages environmental awareness It’s your first command when something feels “off.” # wheels get environment **Know Exactly Where You Are** Modern apps typically run in multiple environments: * development * testing * staging * production * maintenance The get environment command tells you exactly which one your app is currently using. `wheels get environment` **What It Shows** * Active environment name * How it was detected * Where the configuration is coming from This eliminates guesswork. No more manually inspecting configuration files. **Why This Is Important** Environment mismatches are one of the most common causes of bugs. For example: * Caching enabled in staging but not locally * Different database connections * Different mail server settings * Debug mode accidentally enabled in production Instead of wondering, just run: `wheels get environment` Instant clarity. **Real-World Scenario** Imagine deploying to staging and noticing unexpected behavior. You assume it’s running in staging. But what if the environment variable wasn’t set correctly? Running: `wheels get environment` Immediately confirms whether your assumption is correct. This command alone can save hours of debugging. # wheels get settings **Inspect Your Active Configuration** The get settings command shows the current Wheels application settings for your active environment. `wheels get settings` It displays: * All active configuration values * Default settings * Custom overrides * Environment-specific configurations You can also filter for specific settings if needed. **Why This Command Is Critical** Configuration issues are subtle. Sometimes: * A setting exists in one environment but not another * A default value is overriding a custom one * A configuration file isn’t being loaded as expected Instead of manually opening multiple config files, this command aggregates everything into one clear output. **Practical Use Cases** Troubleshooting: If something related to caching, sessions, or routing behaves differently: `wheels get settings` You’ll immediately see: * What’s enabled * What’s disabled * What values are active Configuration Validation: Before going live: * Confirm debugging is disabled * Confirm production caching is enabled * Confirm mail settings are correct * Confirm custom overrides are loaded This command provides verification without manual inspection. The Bigger Picture: These commands represent an important shift in the CLI philosophy. Older CLI commands focused on generating files. These new commands focus on observability and awareness. They help you: * Understand your app * Validate your configuration * Debug faster * Avoid environment confusion * Collaborate more efficiently In modern development, visibility is productivity. # How These Commands Work Together Here’s a practical workflow: **Step 1 – Confirm Environment** `wheels get environment` Make sure you're in the expected environment. **Step 2 – Inspect Configuration** `wheels get settings` Verify important configuration values. **Step 3 – Full Diagnostic Overview** `wheels about` Review the full application snapshot. Together, they provide a complete picture of your application’s runtime state. # What This Means for Wheels Developers With these inspection tools, Wheels CLI is evolving into more than just a scaffolding tool. It’s becoming: * A diagnostic assistant * A configuration validator * An environment inspector * A debugging companion And this is just the beginning. In upcoming articles, we’ll continue exploring: * Environment management tools * Database utilities * Testing automation commands * Asset workflows * Documentation generation * Advanced plugin tooling Each module builds toward one goal: * More control. * More clarity. * More confidence. # Conclusion The new inspection commands in Wheels CLI 3.x are small in size — but huge in impact. * wheels about gives you a full application snapshot * wheels get environment removes environment guesswork. * wheels get settings exposes active configuration instantly. If earlier CLI commands helped you build faster… These help you debug smarter. And in modern development, smart debugging is just as important as fast coding. Stay tuned — the next deep dive is coming. Learn more here: https://www.youtube.com/watch?v=NHx3-wncyFw

February 23, 2026 by Zain Ul Abideen

Welcome to Our Community

Welcome to Our Community - a place where like-minded people connect, share ideas,
and grow together in a positive and supportive environment.

Explore community
Wheels.dev Community

Top Contributors

Per Djurner

Contributed as a Software Developer

Per Djurner is a long-time core contributor and leader of the Wheels framework, with a history of shaping its direction since the project’s early days. He made the very first commit and has continued to contribute regularly, fixing important bugs, refining SQL handling, and enhancing model methods with more flexible options. In addition to code, he has improved documentation, templates, and overall project stability, ensuring Wheels remains reliable and developer-friendly. His work reflects both technical expertise and long-term commitment to the growth of the framework.

Per Djurner profile picture

Peter Amiri

Contributed as a Software Developer and Project Manager

Peter Amiri is a senior developer and community leader who has taken on a core team / maintainer role in the Wheels framework. He has decades of experience with ColdFusion (since version 1.5), including work in user-groups, large scale sites, and infrastructure. Since returning to the project, he’s helped revitalize it — organizing roadmap discussions, guiding structure changes, supervising modernization (including CLI improvements, package modularization, and updating workflows), and helping re-energize community contributions.

Peter Amiri profile picture

Zain Ul Abideen

Contributed as a Software Developer

Zain Ul Abideen is an active contributor to the Wheels framework, playing a key role in improving its stability and usability. His work includes fixing issues like invalid columns not throwing exceptions, ensuring primary keys return correctly as numeric, and refining logic around calculated properties. He also enhanced view helpers to better handle active states and improved default routing behavior. Through these contributions, Zain has strengthened both the framework’s reliability and developer experience.

Zain Ul Abideen profile picture

Anthony Petruzzi

Contributed as a Software Developer

Anthony Petruzzi has made valuable contributions to the Wheels through code improvements, bug fixes, and collaborative reviews. They’ve helped refine core components, enhanced framework stability, and actively participated in issue discussions to steer design decisions. Their efforts in writing clear, maintainable code and offering constructive feedback in pull requests have strengthened the project’s code quality. Overall, Anthony Petruzzi involvement showcases dedication to open-source collaboration and meaningful impact on the Wheels ecosystem.

Anthony Petruzzi profile picture

Tom King

Contributed as a Software Developer and Maintainer

Tom King is one of the core maintainers of Wheels, with deep involvement in both development and leadership. He oversaw major releases, such as Wheels 2.0, which introduced features like RESTful routing, database migrations, improved CLI support, and a rewritten core in CFScript. He also helps steer the project’s long-term direction — writing blog posts reflecting on its history (e.g. noting its first commits, celebrating milestones) and working to modernize both tooling and community engagement.

Tom King profile picture

Adam Chapman

Contributed as a Software Developer

Adam Chapman has been a dedicated and influential contributor to the Wheels ecosystem. He joined the core team after years of community support, helping to steer architectural evolution and plugin integrations. Beyond code, he’s actively engaged in issue triage, proposing enhancements and shaping long-term design direction. His commitment to both community discussion and technical contributions has strengthened the project’s cohesion and future readiness.

Adam Chapman profile picture

James

Contributed as a Software Developer

James has brought forward meaningful contributions to the Wheels through consistent code enhancements, test case development, and active engagement in issue resolution. He frequently submits detailed pull requests, helping to bolster the framework’s robustness and maintainability. Beyond code, James participates in discussion threads and reviews, offering thoughtful feedback which helps keep the project aligned with community needs. His steady involvement has strengthened both core modules and auxiliary features, making Wheels more reliable and polished for all users.

James profile picture

Andrew Bellenie

Contributed as a Software Developer and Maintainer

Andrew Bellenie has played a pivotal role in the Wheels ecosystem, as a long-standing core team member and active community contributor. He brings deep experience in CFML development and framework architecture. Andy has contributed code, design feedback, documentation, and mentorship to newcomers. He also helps triage issues, guide feature direction, and maintain the project’s stability. His dedication helps keep the framework evolving and its community engaged.

Andrew Bellenie profile picture

scahyono

Contributed as a Software Developer

scahyono has contributed thoughtful enhancements to the Wheels codebase, particularly in ensuring compatibility with Oracle setups. Notably, they worked on a module (or plugin) to allow ColdFusion on Wheels to correctly read table metadata across Oracle remote database links, which broadens database support and resilience. Their willingness to tackle specialized integration challenges strengthens the framework’s versatility and helps more users adopt Wheels in diverse environments.

scahyono profile picture

MvdO79

Contributed as a Software Developer

MvdO79 has shown his support for the Wheels not only through code but also as a financial backer. He contributes monthly via Open Collective, helping sustain the framework’s ongoing development. Beyond funding, his presence in issue discussions demonstrates engagement with bug tracking and community feedback. His dual role-as supporter and participant-reinforces the open-source spirit behind Wheels.

MvdO79 profile picture

Raul Riera

Contributed as a Software Developer

Raúl Riera has been an enthusiastic supporter and contributor to the Wheels community-beyond writing code, he’s helped through design, advocacy, and community engagement. He has designed swag such as T-shirts for Wheels events and promoted the framework through his dev shop, Hipervínculo. As a software entrepreneur (founder of Odonto.me) and developer, Raúl bridges technical and community roles, helping raise awareness of Wheels and adding a touch of creativity and outreach to the project’s ecosystem.

Raul Riera profile picture

Michael Diederich

Contributed as a Software Developer

Michael Diederich has contributed key fixes and enhancements to the Wheels, particularly around framework usability and interface issues. Notably, he addressed documentation and UI elements-changes such as showing the current Git branch in the debug layout in version 2.5.0 reflect his involvement. In earlier releases, he also fixed bugs (for example with form and URL handling in the startFormTag() and array routing) that improved reliability across use cases. His contributions help refine both developer-facing tools and core correctness.

Michael Diederich profile picture

Rob Cameron

Contributed as a Software Developer

Rob Cameron had the original idea for CFWheels (and by extension, the foundation for Wheels), having built the framework with inspiration from Ruby on Rails in 2005. Though he eventually moved on from active core development to focus on other projects (such as Rails work), his early design and architectural direction still underpin much of the project's structure and philosophy.

Rob Cameron profile picture

Chris Peters

Contributed as a Software Developer

Chris Peters has been foundational in the development, documentation, and promotion of the Wheels framework since its early days. He authored many of the earliest releases, oversaw version 1.3.0 that introduced HTML5 enhancements, table less models, and thread-safe startup, and managed releases like 1.0.5 with dozens of bug fixes and stability updates. He also wrote technical blog posts about core features (flash messages, asset query strings, error handling) and established guidelines for contributing and documentation, helping to build a strong community around the framework.

Chris Peters profile picture

David Paul Belanger

Contributed as a Software Developer

David Paul Belanger has been a core force behind the Wheels, contributing both technically and strategically across many versions. He has co-authored features and bug fixes (such as updates to sendFile() and usesLayout()) in the 2.x releases. Beyond code, David has helped lead the transition of the framework’s governance and been active in community outreach-having participated in CF-Alive podcasts and collaborated with Tom King and others on guiding the project’s future direction.

David Paul Belanger profile picture

John Bampton

Contributed as a Software Developer and Documentation Writer

John Bampton made his mark as a contributor to the Wheels project beginning with version 2.4.0, where he helped fix broken links in documentation and correct spelling errors in the README and core templates. His attention to detail improved the documentation clarity and usability for future developers. Though he is noted as a “new contributor,” his work helped plug small but important gaps in the project’s written material, aiding the framework’s polish and accessibility.

John Bampton profile picture

Simon

Contributed as a Software Developer

Simon contributed to the Wheels framework by refining code and improving framework functionality. His work helped address issues and enhance stability, making the project more reliable and easier for developers to use. These contributions support the continued growth and effectiveness of the Wheels ecosystem.

Simon profile picture

Brian Ramsey

Contributed as a Software Developer and Quality Assurance Engineer

Brian Ramsey has been a long-time contributor and advocate within the Wheels community. His work spans both code contributions and knowledge sharing, with a focus on improving framework usability for everyday developers. Brian has participated in bug resolution, tested new releases, and provided feedback that shaped core improvements. Beyond code, he’s been active in community discussions, answering questions, and guiding newer users. His steady involvement has helped ensure Wheels remains both developer-friendly and reliable, reflecting his commitment to open-source collaboration and practical problem solving.

Brian Ramsey profile picture

Danny Beard

Contributed as a Software Developer

Danny Beard has contributed to the Wheels framework through targeted code enhancements and thoughtful participation in issue discussions. His work has included fixing bugs, refining logic in core functions, and improving overall framework consistency. Danny’s involvement reflects an eye for detail and a practical approach to problem-solving, ensuring the framework remains dependable in real-world applications. Beyond code, his willingness to collaborate with other contributors has reinforced the community-driven nature of Wheels, helping maintain a strong and sustainable open-source project.

Danny Beard profile picture

Reuben Brown

Contributed as a Software Developer

Reuben Brown has been a valuable contributor to the Wheels framework, offering code improvements and community input that strengthen the project’s overall quality. His work includes bug fixes and refinements that enhance stability and usability, ensuring developers can rely on Wheels in production environments. Reuben’s involvement extends beyond code, as he has taken part in discussions, reviewed issues, and provided practical feedback to guide development. His contributions reflect a thoughtful balance of technical skill and collaborative spirit, reinforcing the open-source ethos of the Wheels project.

Reuben Brown profile picture

Seb

Contributed as a Software Developer

Seb has provided important contributions to the Wheels that help improve framework robustness and usability. Through resolving issues, submitting pull requests, and polishing code, Seb has helped close gaps and make the system smoother for both new and experienced users. They’ve also participated in reviews, giving constructive feedback, which strengthens code quality and consistency across releases. Seb’s steady involvement supports the project’s open-source mission, making Wheels more reliable, maintainable, and welcoming for all contributors.

Seb profile picture

timbadolato

Contributed as a Software Developer

Timbadolato has contributed to the Wheels with a focus on improving functionality, fixing issues, and enhancing developer experience. His pull requests demonstrate a clear attention to detail, addressing edge cases and refining framework behavior to make it more predictable and reliable. By engaging in code reviews and community discussions, timbadolato has helped shape technical decisions and ensured smoother adoption for users. His contributions highlight a practical, solution-oriented approach that supports both the long-term stability and growth of the Wheels ecosystem.

timbadolato profile picture

Alex

Contributed as a Software Developer

Alex has played a supportive and constructive role in the Wheels, contributing code improvements and feedback that strengthen the framework’s overall reliability. His efforts include bug fixes, refinements to core features, and helpful participation in discussions that guide project direction. By addressing issues and proposing practical solutions, Alex has contributed to making Wheels easier to use and more stable for developers. His involvement reflects a collaborative spirit and reinforces the open-source values that keep the project moving forward.

Alex profile picture

Chris Geirman

Contributed as a Software Developer

Chris Geirman made contributions to the Wheels that helped refine parts of the codebase and improve developer experience. While his involvement was smaller in scope, his participation still added value to the framework and reflects the spirit of open-source collaboration.

Chris Geirman profile picture

Zac Spitzer

Contributed as a Software Developer

Zac Spitzer provided contributions to the Wheels that helped address specific issues and improve framework stability. Though his involvement was brief, his work added value to the codebase and demonstrated the importance of community participation in strengthening and maintaining open-source projects.

Zac Spitzer profile picture

Nikolaj Frey

Contributed as a Software Developer

Nikolaj Frey has made contributions to the Wheels framework that supported improvements in the project’s codebase and functionality. While his involvement was limited in scope, his participation still added meaningful value, reinforcing the collaborative nature of the open-source community that drives Wheels forward.

Nikolaj Frey profile picture

Gralen

Contributed as a Software Developer

Gralen contributed improvements to the Wheels framework that enhanced code quality and supported overall stability. Their work helped refine the project and contributed to making the framework more reliable for developers using it in real-world applications.

Gralen profile picture

Doug McCaughan

Contributed as a Software Developer

Doug McCaughan contributed to the Wheels framework by helping refine functionality and addressing issues that improved developer experience. His efforts supported the stability of the project and ensured smoother use of core features. Through his work, Doug added value to the framework’s ongoing development and its open-source community.

Doug McCaughan profile picture

Coleman Sperando

Contributed as a Software Developer

Coleman Sperando contributed to the Wheels framework by making improvements that strengthened its functionality and reliability. His work addressed specific areas of the codebase, helping to refine features and ensure a smoother experience for developers. These contributions supported the project’s ongoing growth and the collaborative effort behind Wheels.

Coleman Sperando profile picture

Charlie Arehart

Contributed as a Software Developer

Charlie Arehart has supported the Wheels framework through his deep expertise in ColdFusion and the broader CFML ecosystem. He has provided valuable feedback, shared knowledge with the community, and highlighted best practices that strengthen adoption and reliability. His involvement helps connect Wheels development with the wider ColdFusion community, ensuring the framework remains relevant and accessible to developers.

Charlie Arehart profile picture

Charley Contreras

Contributed as a Software Developer

Charley Contreras contributed to the Wheels framework by helping refine parts of the codebase and supporting improvements that enhance usability. His work added value to the project’s overall stability and reflects the collaborative effort of developers working together to keep the framework evolving and reliable.

Charley Contreras profile picture

Brant Nielsen

Contributed as a Software Developer

Brant Nielsen contributed to the Wheels framework by improving functionality and addressing issues that supported better performance and reliability. His work helped refine the codebase and enhance the developer experience, reinforcing the project’s commitment to building a stable and effective open-source framework.

Brant Nielsen profile picture

Ben Nadel

Contributed as a Software Developer

Ben Nadel is a veteran ColdFusion developer known for deep technical thought leadership and contributions to the community, including work around Wheels and related topics. He writes regularly about extending and customizing parts of Wheels (for example, customizing the router/proxy component behavior to suit specific workflow preferences). He also shares experiments and educational posts (e.g. integrating HTMX in ColdFusion apps) that help other developers understand modern patterns in CFML. While he may not always be contributing direct core framework commits, his influence shows up in how people use and adapt Wheels in real-world apps, and in sharing best practices, tutorials, and ideas that help shape how the framework is viewed and utilized.

Ben Nadel profile picture

Andrei B.

Contributed as a Software Developer

Andrei B. contributed to the Wheels framework by helping refine code and improve functionality in targeted areas of the project. His efforts supported greater stability and usability, making the framework more dependable for developers. These contributions reflect the collaborative spirit that drives the ongoing success of Wheels.

Andrei B. profile picture

Adam Larsen

Contributed as a Software Developer

Adam Larsen contributed to the Wheels framework by improving functionality and addressing issues that enhanced the stability and reliability of the codebase. His work helped refine features and ensure a smoother experience for developers, supporting the ongoing growth and maintenance of the project.

Adam Larsen profile picture

Claude

Contributed as a Software Developer

Claude profile picture

github-actions[bot]

Contributed as a Software Developer

github-actions[bot] profile picture

mlibbe

Contributed as a Software Developer

mlibbe profile picture

Zain Ul Abideen

Contributed as a Software Developer

Zain Ul Abideen profile picture

Zain Ul Abideen

Contributed as a Software Developer

Zain Ul Abideen profile picture