diff --git a/README.md b/README.md
index baf551d..b0e1986 100644
--- a/README.md
+++ b/README.md
@@ -486,6 +486,62 @@ The CLI detects BoxLang projects using three methods (in order of precedence):
}
```
+### 🗂️ App Layout Detection
+
+The CLI automatically detects whether your project uses a **modern** or **flat** layout and generates files in the correct location.
+
+| Layout | Detection | App Code Location | Tests Location |
+| ------ | --------- | ----------------- | -------------- |
+| **Modern** | Both `app/` and `public/` directories exist | `/app/models`, `/app/handlers`, etc. | `/tests/` |
+| **Flat** | Default (no `app/` + `public/`) | `/models`, `/handlers`, etc. | `/tests/` |
+
+#### Modern Layout (e.g. `boxlang`, `modern` templates)
+
+```text
+/app - Application source code
+ /config - Configuration
+ /handlers - Event handlers
+ /models - Models & services
+ /views - View templates
+ /layouts - Layout wrappers
+ /interceptors - Interceptors
+/public - Web root
+/modules - ColdBox modules
+/tests - Test suites
+/resources - Migrations, seeders, etc.
+```
+
+#### Flat Layout (e.g. `flat`, legacy templates)
+
+```text
+/config - Configuration
+/handlers - Event handlers
+/models - Models & services
+/views - View templates
+/layouts - Layout wrappers
+/interceptors - Interceptors
+/modules - ColdBox modules
+/tests - Test suites
+```
+
+When you run a generation command in a modern-layout project, the CLI automatically targets the correct directory:
+
+```bash
+# In a flat layout project → creates /handlers/users.cfc
+# In a modern layout project → creates /app/handlers/users.cfc
+coldbox create handler users
+
+# In a flat layout project → creates /models/User.cfc
+# In a modern layout project → creates /app/models/User.cfc
+coldbox create model User
+```
+
+You can always override the target directory explicitly:
+
+```bash
+coldbox create model User directory=app/models
+```
+
#### 🚀 Usage Examples
```bash
diff --git a/changelog.md b/changelog.md
index 3ea0753..70771ba 100644
--- a/changelog.md
+++ b/changelog.md
@@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+### Added
+
+- Automatic app layout detection for code generation commands. The CLI now detects whether the project uses a modern layout (with `app/` and `public/` directories) or a flat layout, and automatically places generated files in the correct location (e.g., `app/models` vs `models`, `app/handlers` vs `handlers`, etc.).
+
## [8.9.0] - 2026-04-07
### Updates
diff --git a/commands/coldbox/create/handler.cfc b/commands/coldbox/create/handler.cfc
index cc02347..299dd02 100644
--- a/commands/coldbox/create/handler.cfc
+++ b/commands/coldbox/create/handler.cfc
@@ -42,11 +42,11 @@ component aliases="coldbox create controller" extends="coldbox-cli.models.BaseCo
required name,
actions = "",
boolean views = true,
- viewsDirectory = "views",
+ viewsDirectory = getAppPrefix( getCWD() ) & "views",
boolean integrationTests = true,
appMapping = "/",
testsDirectory = "tests/specs/integration",
- directory = "handlers",
+ directory = getAppPrefix( getCWD() ) & "handlers",
description = "I am a new handler",
boolean open = false,
boolean rest = false,
diff --git a/commands/coldbox/create/interceptor.cfc b/commands/coldbox/create/interceptor.cfc
index 5b187d5..e86119a 100644
--- a/commands/coldbox/create/interceptor.cfc
+++ b/commands/coldbox/create/interceptor.cfc
@@ -29,7 +29,7 @@ component extends="coldbox-cli.models.BaseCommand" {
description = "I am a new interceptor",
boolean tests = true,
testsDirectory = "tests/specs/interceptors",
- directory = "interceptors",
+ directory = getAppPrefix( getCWD() ) & "interceptors",
boolean open = false,
boolean force = false,
boolean boxlang = isBoxLangProject( getCWD() )
diff --git a/commands/coldbox/create/layout.cfc b/commands/coldbox/create/layout.cfc
index 904713c..1000bcb 100644
--- a/commands/coldbox/create/layout.cfc
+++ b/commands/coldbox/create/layout.cfc
@@ -21,7 +21,7 @@ component extends="coldbox-cli.models.BaseCommand" {
function run(
required name,
boolean helper = false,
- directory = "layouts",
+ directory = getAppPrefix( getCWD() ) & "layouts",
boolean open = false,
boolean force = false,
content = "
#arguments.name# Layout
#variables.utility.BREAK#",
diff --git a/commands/coldbox/create/model.cfc b/commands/coldbox/create/model.cfc
index 5796487..554cca3 100644
--- a/commands/coldbox/create/model.cfc
+++ b/commands/coldbox/create/model.cfc
@@ -60,7 +60,7 @@ component extends="coldbox-cli.models.BaseCommand" {
persistence = "transient",
boolean tests = true,
testsDirectory = "tests/specs/unit",
- directory = "models",
+ directory = getAppPrefix( getCWD() ) & "models",
description = "I am a new Model Object",
boolean open = false,
boolean accessors = true,
diff --git a/commands/coldbox/create/orm-crud.cfc b/commands/coldbox/create/orm-crud.cfc
index e8d43b9..1bbd0fe 100644
--- a/commands/coldbox/create/orm-crud.cfc
+++ b/commands/coldbox/create/orm-crud.cfc
@@ -22,8 +22,8 @@ component extends="coldbox-cli.models.BaseCommand" {
function run(
required entity,
pluralName = "",
- handlersDirectory = "handlers",
- viewsDirectory = "views",
+ handlersDirectory = getAppPrefix( getCWD() ) & "handlers",
+ viewsDirectory = getAppPrefix( getCWD() ) & "views",
boolean tests = true,
testsDirectory = "tests/specs/integration",
boolean boxlang = isBoxLangProject( getCWD() )
diff --git a/commands/coldbox/create/orm-entity.cfc b/commands/coldbox/create/orm-entity.cfc
index f668d84..2c0f19d 100644
--- a/commands/coldbox/create/orm-entity.cfc
+++ b/commands/coldbox/create/orm-entity.cfc
@@ -56,7 +56,7 @@ component extends="coldbox-cli.models.BaseCommand" {
function run(
required entityName,
table = "",
- directory = "models",
+ directory = getAppPrefix( getCWD() ) & "models",
boolean activeEntity = false,
primaryKey = "id",
primaryKeyColumn = "",
diff --git a/commands/coldbox/create/orm-service.cfc b/commands/coldbox/create/orm-service.cfc
index c4fa851..284b68f 100644
--- a/commands/coldbox/create/orm-service.cfc
+++ b/commands/coldbox/create/orm-service.cfc
@@ -23,7 +23,7 @@ component extends="coldbox-cli.models.BaseCommand" {
**/
function run(
required serviceName,
- directory = "models",
+ directory = getAppPrefix( getCWD() ) & "models",
boolean queryCaching = false,
boolean eventHandling = true,
cacheRegion = "",
diff --git a/commands/coldbox/create/orm-virtual-service.cfc b/commands/coldbox/create/orm-virtual-service.cfc
index 53788d7..349f9be 100644
--- a/commands/coldbox/create/orm-virtual-service.cfc
+++ b/commands/coldbox/create/orm-virtual-service.cfc
@@ -23,7 +23,7 @@ component extends="coldbox-cli.models.BaseCommand" {
**/
function run(
required entityName,
- directory = "models",
+ directory = getAppPrefix( getCWD() ) & "models",
boolean queryCaching = false,
boolean eventHandling = true,
cacheRegion = "",
diff --git a/commands/coldbox/create/resource.cfc b/commands/coldbox/create/resource.cfc
index cd3c472..0088832 100644
--- a/commands/coldbox/create/resource.cfc
+++ b/commands/coldbox/create/resource.cfc
@@ -91,9 +91,9 @@ component extends="coldbox-cli.models.BaseCommand" {
generator = "native",
properties = "",
modulesDirectory = "modules_app",
- handlersDirectory = "handlers",
- viewsDirectory = "views",
- modelsDirectory = "models",
+ handlersDirectory = getAppPrefix( getCWD() ) & "handlers",
+ viewsDirectory = getAppPrefix( getCWD() ) & "views",
+ modelsDirectory = getAppPrefix( getCWD() ) & "models",
boolean tests = true,
specsDirectory = "tests/specs",
boolean api = false,
diff --git a/commands/coldbox/create/service.cfc b/commands/coldbox/create/service.cfc
index 8e77ef2..336ada9 100644
--- a/commands/coldbox/create/service.cfc
+++ b/commands/coldbox/create/service.cfc
@@ -33,7 +33,7 @@ component extends="coldbox-cli.models.BaseCommand" {
methods = "",
boolean tests = true,
testsDirectory = "tests/specs/unit",
- directory = "models",
+ directory = getAppPrefix( getCWD() ) & "models",
description = "I am a new service",
boolean open = false,
boolean force = false,
diff --git a/commands/coldbox/create/view.cfc b/commands/coldbox/create/view.cfc
index 55210c9..dffebfc 100644
--- a/commands/coldbox/create/view.cfc
+++ b/commands/coldbox/create/view.cfc
@@ -22,7 +22,7 @@ component extends="coldbox-cli.models.BaseCommand" {
function run(
required name,
boolean helper = false,
- directory = "views",
+ directory = getAppPrefix( getCWD() ) & "views",
boolean open = false,
content = "#arguments.name# view
",
boolean force = false,
diff --git a/models/BaseCommand.cfc b/models/BaseCommand.cfc
index 7d48e46..1a6adcb 100644
--- a/models/BaseCommand.cfc
+++ b/models/BaseCommand.cfc
@@ -17,6 +17,19 @@ component accessors="true" {
return this;
}
+ /**
+ * Detects the application layout and returns the appropriate path prefix.
+ * In a modern layout (app/ and public/ directories exist), returns "app/".
+ * In a flat layout, returns "".
+ *
+ * @cwd The current working directory
+ *
+ * @return string "app/" for modern layout, "" for flat layout
+ */
+ function getAppPrefix( required cwd ){
+ return variables.utility.detectTemplateType( cwd ) == "modern" ? "app/" : "";
+ }
+
/**
* Determines if we are running on a BoxLang server
* or using the BoxLang runner.