Skip to content

Project Structure

Technomantus Corvi edited this page Sep 5, 2026 · 1 revision

Project Structure

tanuki_base/
│
├── public/ ← ONLY folder exposed to the web
│ ├── index.php ← Entry point (only calls App::run())
│ ├── .htaccess ← Apache rewrite rules
│ └── assets/
│ ├── css/app.css
│ └── js/app.js
│
├── routes.php ← All route definitions
├── utils.php ← Global helpers: e(), view(), env(), redirect()…
├── auth.php ← Session auth helpers (tanuki_login, inert until wired in)
│
├── .env ← Local environment variables (NOT in git)
├── .env-example ← Documented template
├── nginx.config ← Nginx server block reference
│
├── config/
│ ├── database.php ← Database class (PDO Singleton, mysql/pgsql/sqlite)
│ ├── redis.php ← Redis class (optional, native phpredis)
│ ├── mongo.php ← Mongo class (optional, mongodb/mongodb)
│ ├── mail.php ← Mail class (SMTP, used by tanuki_login)
│ └── nav.php ← Navigation menu entries
│
├── core/
│ ├── App.php ← Bootstrap: env loader, autoloader, router
│ ├── Controller.php ← Base controller class
│ ├── Model.php ← Lightweight Active Record base
│ └── Request.php ← HTTP request wrapper
│
├── controllers/ ← Your controllers (extend Controller)
├── models/ ← Your models (extend Model)
├── views/ ← Pure PHP templates
│ └── errors/ ← 404 / 500 / 503 error views
├── includes/
│ ├── head.php ← HTML head + nav + user menu + language switcher + opens <main>
│ └── footer.php ← Closes </main> + footer + app.js
├── lang/ ← Translation dictionaries (en.json, es.json, ...)
│
├── admin/ ← tanuki_admin extension — fully self-contained
│ ├── admin.php ← Resource registry
│ ├── AdminController.php ← Generic CRUD controller
│ ├── create-superuser.php ← CLI script
│ └── templates/ ← Independent admin templates
│
└── tests/ ← PHPUnit tests (see Testing)

Why public/ is the only exposed folder

Everything except public/ sits outside the web server's document root. This means core/, controllers/, models/, and config/ can never be requested directly by URL, no matter how the server is configured — the framework's PHP classes simply aren't reachable from outside. This is the same pattern used by Laravel, Symfony, and most modern PHP frameworks.

What's core vs. optional

Always present, always active Present, inert until you wire it in
core/, controllers/, models/, views/, includes/, config/database.php auth.php, config/mail.php, admin/ (whole folder)

Optional pieces cost nothing at runtime until you register their routes in routes.php — see Authentication and Admin Panel.

Clone this wiki locally