Project Structure
Keel keeps framework internals separate from app code while keeping views plain PHP.
public_html/
index.php
css/keel.css yours
js/keel.js yours
deck/ Deck's, published by Composer, git-ignored
deck.css
deck.min.css
deck.js
deck-extras.js
deck-icons.svg
uploads/
src/
Core/
App/
Controllers/
Middleware/
Models/
Services/
routes/
web.php
views/
partials/
auth/
dashboard/
resources/
images/
database/
migrations/
migrate.php
queue-work.php
tests/
storage/
logs/
app/
What belongs where
src/Core/: framework internals likeRouter,Request,Response,Database,View,ErrorHandler.src/App/Controllers/: HTTP endpoints and request orchestration.src/App/Services/: business logic, external APIs, and workflows.src/App/Middleware/: route guards and request checks.routes/web.php: route registration.views/: plain PHP templates (no template engine dependency).public_html/deck/: Deck's published files. Not yours — see below.public_html/css/keel.cssandpublic_html/js/keel.js: Keel's own styles and glue, served exactly as written. There is no build step.resources/images/: brand source images.database/migrations/: SQL migrations applied byphp database/migrate.php.database/queue-work.php: queue worker CLI entrypoint.
Deck's files versus yours
Two directories under public_html/ hold CSS. The difference matters, because one of them is overwritten without warning.
public_html/deck/ |
public_html/css/keel.css |
|
|---|---|---|
| Whose | Deck's | Yours |
| How it gets there | composer install |
You write it |
| In git | No, git-ignored | Yes |
| Safe to edit | Never | Always |
Never edit anything in public_html/deck/. It is build output: Composer republishes the whole directory on every install and update, so an edit there survives until the next install and then vanishes — including on a teammate's machine, and in CI, where it never existed at all. The directory is git-ignored for that reason, and a fresh clone has no public_html/deck/ until Composer runs.
Everything you want to change goes in public_html/css/keel.css instead. Deck reserves four cascade layers for it — app.base, app.components, app.pages and app.overrides — which are declared after all of Deck's, so a rule there beats a Deck rule without !important and without extra specificity. That is the supported way to override Deck, and it survives upgrades. See Building the Interface.