dudi/docs/structure.md
Simon Kühn fd473f00af Initial commit: Dudi habit tracker
Symfony 8 SPA with Doctrine ORM, Symfony Security, vanilla JS frontend.
Migrated from plain PHP (delight-im/auth + raw SQL) to full Symfony stack.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 15:40:57 +02:00

3 KiB

Project Structure

dudi/
├── bin/
│   └── console                     # Symfony CLI
├── config/
│   ├── packages/
│   │   ├── doctrine.yaml           # ORM + DBAL config
│   │   ├── security.yaml           # Firewall, providers, access control
│   │   ├── mailer.yaml
│   │   └── ...
│   └── routes.yaml                 # Auto-discovers #[Route] attributes
├── migrations/                     # Legacy SQL migrations (pre-Symfony)
├── public/                         # Apache DocumentRoot
│   ├── index.php                   # Symfony kernel entry point
│   ├── .htaccess                   # RewriteRule → index.php
│   ├── app.js                      # Frontend SPA (vanilla JS)
│   ├── style.css
│   └── logo.png
├── src/
│   ├── Controller/
│   │   ├── AppController.php       # Catch-all → renders app.html.twig
│   │   ├── AuthController.php      # /api/me, /api/register, /api/reset-*, /api/change-password
│   │   ├── GoalController.php      # /api/goals CRUD
│   │   └── InviteController.php    # /api/invite, /api/invites
│   ├── Entity/
│   │   ├── User.php                # Maps to users table (delight-im/auth compatible schema)
│   │   ├── Goal.php
│   │   └── Invite.php
│   ├── Repository/
│   │   ├── UserRepository.php      # implements PasswordUpgraderInterface
│   │   ├── GoalRepository.php
│   │   └── InviteRepository.php
│   ├── Security/
│   │   └── JsonLoginAuthenticator.php  # Handles POST /api/login with JSON body
│   └── Kernel.php
├── templates/
│   └── app.html.twig               # Full SPA shell + all <template> elements
├── .env                            # Generic defaults (committed)
├── .env.local                      # Local credentials (gitignored)
├── deploy.sh                       # rsync + remote composer install + cache:clear
└── symfony.lock

Frontend Architecture

The frontend is a single-page app with no build step:

  • public/app.js — all logic, ~700 lines vanilla JS
  • templates/app.html.twig — rendered once server-side; contains all <template id="tpl-*"> elements
  • JS clones templates with tpl(id) helper and fills in dynamic values via querySelector
  • No framework, no bundler, no npm

Database Tables

Table Managed by Purpose
goals Doctrine ORM User goals with JSON sets column
invites Doctrine ORM Invite tokens
users Doctrine ORM User accounts (bcrypt passwords)
rememberme_token Symfony Security 24h remember-me tokens
users_resets Raw SQL in AuthController Password reset tokens
users_throttling Legacy (delight-im/auth) Can be removed
users_confirmations Legacy (delight-im/auth) Can be removed
schema_migrations Legacy Can be removed