Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ All historical references to "CFWheels" in this changelog have been preserved fo

### Added

**Documentation**
- Add Debug Panel guide covering each tab, configuration settings, and when the bar appears

**ORM & data layer**
- Chainable query builder with `where()`, `orWhere()`, `whereNull()`, `whereBetween()`, `whereIn()`, `whereNotIn()`, `orderBy()`, `limit()`, and more for injection-safe fluent queries (#1922)
- Enum support with `enum()` for named property values, auto-generated `is*()` checkers, auto-scopes, and inclusion validation (#1921)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: CORS
description: Cross-origin request handling — configuring the Cors middleware, preflight, credentials mode, and per-route scoping.
type: howto
sidebar:
order: 12
order: 13
---

import { Aside, CardGrid, LinkCard } from '@astrojs/starlight/components';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
---
title: Debug Panel
description: The built-in development debug bar — what each tab shows, how to configure it, and when it appears.
type: howto
sidebar:
order: 11
---

import { Aside, CardGrid, LinkCard } from '@astrojs/starlight/components';

The Debug Panel is a fixed bar that Wheels appends to every HTML response in development mode. It surfaces request details, execution timing, parameters, environment configuration, installed packages, and links to built-in tools — without leaving the page you are working on. The panel is rendered by `vendor/wheels/events/onrequestend/debug.cfm` and runs at the very end of the request lifecycle, after your controller and views have finished.

**You'll learn:**

- When the debug bar appears and how to control it
- What each tab shows and which configuration drives it
- How to read the timing breakdown to find bottlenecks
- Where to find package and plugin status
- How to access developer tools from the bar

## When the debug bar appears

The bar only renders for standard full-page HTML requests. It is automatically suppressed for any of the following:

- AJAX requests (`X-Requested-With: XMLHttpRequest`)
- HTMX requests (`HX-Request`)
- Turbo Frame requests (`Turbo-Frame`)
- Fetch requests (`X-Fetch: true`)
- Requests that produce structured output (`?format=json`, `xml`, `csv`, or `pdf`)

This means AJAX-driven partial updates, Turbo Streams, API endpoints, and CSV exports all receive clean responses with no injected HTML.

## Enabling and disabling

The bar respects the `showDebugInformation` application setting. By default, Wheels sets this to `true` only in the `development` environment and `false` in every other environment (`testing`, `maintenance`, and `production`). You can override it explicitly in `config/environment.cfm`:

```cfm title="config/environment.cfm"
<cfset set(showDebugInformation=true)>
```

Setting `showDebugInformation=false` removes the bar entirely — no HTML is injected into responses.

<Aside type="caution">
Never enable the debug bar in production. It renders internal state — your data source name, environment, CFML engine version, and parameter values — that you do not want visible to end users.
</Aside>

## The debug bar

When active, the bar appears as a slim strip pinned to the bottom of the browser window. Tabs are arranged from left to right: a Wheels logo (doubles as the Request tab toggle), then Request, Timing, Params, Environment, and optionally Tools. The right side shows the current git branch (when Wheels detects a `.git` directory), the framework version, and a one-click reload link when no reload password is configured.

![The collapsed Wheels debug bar pinned to the bottom of a browser window: Wheels logo, Posts.index controller.action, timing badge, Params, Development environment, and Tools tabs, with Wheels 4.0.0-SNAPSHOT version on the right](/v4-0-0-snapshot/digging-deeper/debug-panel-screenshots/01-collapsed-bar.png)

Clicking any tab opens a panel above the bar. Clicking the same tab again closes it. The minimize button (×) collapses the bar to a small "Debug" button in the corner, persisted via `sessionStorage` so it stays collapsed as you navigate.

## Request tab

The Request tab label shows `controller.action` for the current request. Clicking it opens a key-value panel with:

| Field | Description |
|---|---|
| Route | Named route that matched this request (omitted when no named route matched) |
| Controller | Controller name |
| Action | Action name |
| Key | URL key segment, if present |
| HTTP Method | `GET`, `POST`, `PUT`, `DELETE`, etc. |
| URL | Full URL for this request |
| Application | Value of `applicationName` from `Application.cfc` |
| Data Source | The configured `dataSourceName` |
| DB Adapter | The active database adapter (MySQL, PostgreSQL, SQL Server, etc.) — omitted when the adapter name is not detected |
| URL Rewriting | Current URL rewriting mode |

![Request panel open showing the key-value table: Route (root), Controller (Posts), Action (index), HTTP Method (GET), URL, Application (blog), Data Source (blog), DB Adapter (SQLiteModel), URL Rewriting (On)](/v4-0-0-snapshot/digging-deeper/debug-panel-screenshots/02-request-panel.png)

Use this panel to confirm that routing resolved the way you intended, that the correct data source is in use, and that URL rewriting is configured as expected.

## Timing tab

The Timing tab label shows the total request duration in milliseconds, color-coded by threshold:

- **Green** — under 100 ms
- **Yellow** — 100–499 ms
- **Red** — 500 ms or more

Opening the panel shows a horizontal bar chart breaking down where time was spent. Each phase (model, queries, template rendering, etc.) is sorted by duration descending and rendered as a proportional colored bar showing both the raw milliseconds and the percentage of total time.

![Timing panel showing "Execution Timing — 9ms total" in the header with horizontal bar chart for action and view phases, color-coded and sorted by duration](/v4-0-0-snapshot/digging-deeper/debug-panel-screenshots/03-timing-panel.png)

The chart is most useful for spotting query-heavy actions: if `queries` or `model` accounts for 80%+ of total time, look at the SQL being generated (the Routes admin page lists query counts per action if you need more detail).

## Params tab

The Params tab shows the count of extra request parameters as a badge. Opening the panel displays a table of every parameter that was available to the action, excluding the routing parameters (`controller`, `action`, `key`, `route`) and `fieldnames`.

| Column | Description |
|---|---|
| Name | Parameter key, lowercased |
| Value | The value; complex values (structs, arrays) are JSON-encoded |
| Type | `string` or `json` |

![Params panel showing the Request Parameters table with Name, Value, Type columns — four rows for status=published, category=tech, author=peter, page=2 — all string type](/v4-0-0-snapshot/digging-deeper/debug-panel-screenshots/04-params-panel.png)

This is the fastest way to confirm that form fields, query string values, and nested structs arrived the way you expected before you reach for a `writeDump` call.

## Environment tab

The Environment tab label shows the current environment name (Development, Testing, etc.) with a color-coded dot matching the timing badge palette. The panel is divided into subsections based on what is enabled.

### Application

Always shown. Lists the environment, the git branch (when the app root contains a `.git` directory), the Wheels version, the CFML engine and version, and the host name (when available).

When no reload password is set, the environment name is followed by quick-switch links that reload the app in a different environment mode. This is useful during development to test environment-specific code paths without editing config files.

![Environment & Configuration panel showing Application section with Environment (Development with green dot), Wheels Version, CFML Engine (Lucee 7.0.0.395), Host Name; Packages section listing wheels-basecoat; and Plugins (Legacy) "No plugins installed."](/v4-0-0-snapshot/digging-deeper/debug-panel-screenshots/05-environment-panel.png)

### Packages

Shown when `enablePackagesComponent` is `true` (the default in Wheels 4.0+). Displays two tables.

**Installed packages** lists every package found in `vendor/` and loaded by `PackageLoader.cfc`:

| Column | Description |
|---|---|
| Package | Package name from `package.json` |
| Version | Semver version string |
| Description | One-line description |

If any package failed to load (manifest error, missing dependency, CFC exception), a red error list appears below the installed table with the package name and the exception message.

**Available from registry** pulls the same 24-hour cached registry index used by the `wheels packages` CLI and shows what is available to install:

| Column | Description |
|---|---|
| Package | Name, linked to the package homepage when available |
| Latest | Latest compatible version |
| Description | Registry description |

![Packages section of the Environment panel — Installed table showing wheels-basecoat 3.0.0-rc.1 with version and description columns](/v4-0-0-snapshot/digging-deeper/debug-panel-screenshots/05-environment-panel.png)

This lets you discover first-party packages such as `wheels-hotwire`, `wheels-sentry`, or `wheels-i18n` without leaving the app. The table reflects the same 24-hour cache as `wheels packages list`; run `wheels packages registry refresh` from the CLI if you need up-to-the-minute data.

### Plugins (legacy)

Shown when `enablePluginsComponent` is `true`. Lists plugins installed in the legacy `plugins/` directory with their names and versions. Legacy plugins are the Wheels 3.x predecessor to packages — if you are on a fresh 4.x app, this section is likely empty.

If any plugin warnings exist, a red **Warnings** subsection appears beneath the plugin table:

- **Incompatible plugins** — plugins flagged as incompatible with the current Wheels version (controlled by `showIncompatiblePlugins`)
- **Dependent plugins** — plugins whose dependencies are not satisfied
- **Version mismatches** — plugins that require a different version of another plugin than what is loaded
- **Mixin collisions** — cases where two plugins defined the same method name on the same mixin target; the later-loaded plugin wins

## Tools tab

Shown when `enablePublicComponent` is `true` (the default in development). Opens a grid of link cards, each opening in a new tab:

| Card | Links to |
|---|---|
| System Info | `/wheels/info` — Wheels internals, environment variables, loaded settings |
| Routes | `/wheels/routes` — all registered routes with HTTP method, path, and handler |
| API Docs | `/wheels/api` — generated API documentation |
| Guides | `/wheels/guides` — the documentation site |
| Tests | `/wheels/app/tests` — the test runner |
| Migrator | `/wheels/migrator` — the database migration UI (shown when `enableMigratorComponent` is `true`) |
| Packages | `/wheels/packages` — the package browser (shown when `enablePackagesComponent` is `true`) |
| Plugins | `/wheels/plugins` — the legacy plugin list (shown when `enablePluginsComponent` is `true`) |

![Tools panel showing the Developer Tools link-card grid: System Info, Routes, API Docs, Guides, Tests, Migrator, Packages, and Plugins](/v4-0-0-snapshot/digging-deeper/debug-panel-screenshots/06-tools-panel.png)

## Configuration reference

All settings are applied in `config/settings.cfm` or an environment-specific file under `config/`:

```cfm title="config/environment.cfm"
<cfset set(showDebugInformation=true)>
<cfset set(enablePackagesComponent=true)>
<cfset set(enablePluginsComponent=true)>
<cfset set(showIncompatiblePlugins=true)>
<cfset set(enablePublicComponent=true)>
<cfset set(enableMigratorComponent=true)>
```

| Setting | Default | Effect |
|---|---|---|
| `showDebugInformation` | `true` in `development`, `false` elsewhere | Show or hide the debug bar entirely |
| `enablePackagesComponent` | `true` | Show the Packages subsection in the Environment panel and the Packages link in Tools |
| `enablePluginsComponent` | `true` | Show the Plugins (Legacy) subsection and the Plugins link in Tools |
| `showIncompatiblePlugins` | `true` | Include incompatible-plugin warnings in the Warnings subsection |
| `enablePublicComponent` | `true` in `development`, `false` elsewhere | Show the Tools tab and its link grid |
| `enableMigratorComponent` | `true` | Show the Migrator link in the Tools panel |

## Related guides

<CardGrid>
<LinkCard
title="Packages"
description="Install first-party packages, write your own, and understand the vendor/ activation model — the same packages that appear in the debug bar's Packages tab."
href="/v4-0-0-snapshot/digging-deeper/packages/"
/>
<LinkCard
title="Configuration"
description="Full reference for all Wheels application settings, including the debug-related flags covered here."
href="/v4-0-0-snapshot/configuration/"
/>
</CardGrid>
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Dependency Injection Usage
description: Practical DI patterns — strategy swapping in tests, per-request resolvers, factories, and the service-locator pitfall.
type: howto
sidebar:
order: 14
order: 15
---

import { Aside, CardGrid, LinkCard } from '@astrojs/starlight/components';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ The Digging Deeper section covers Wheels' advanced features — the ones you rea
href="/v4-0-0-snapshot/digging-deeper/packages/"
description="Activating first-party packages, writing your own, and the package.json manifest."
/>
<LinkCard
title="Debug Panel"
href="/v4-0-0-snapshot/digging-deeper/debug-panel/"
description="The built-in dev debug bar — request details, timing, params, packages, and developer tool links."
/>
<LinkCard
title="Route Model Binding"
href="/v4-0-0-snapshot/digging-deeper/route-model-binding/"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Rate Limiting
description: Throttle requests per client — three strategies, memory vs database storage, custom keying, and response headers.
type: howto
sidebar:
order: 13
order: 14
---

import { Aside, CardGrid, LinkCard } from '@astrojs/starlight/components';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Route Model Binding
description: Load records from the URL automatically — per-resource opt-in, global default, custom model name, scope-level binding, and the dev-mode warning when it's off.
type: howto
sidebar:
order: 11
order: 12
---

import { Aside, CardGrid, LinkCard } from '@astrojs/starlight/components';
Expand Down
Loading