First commit

This commit is contained in:
julien
2026-03-27 14:43:08 +01:00
commit ced7dbfbf7
54 changed files with 3680 additions and 0 deletions

170
README.md Normal file
View File

@@ -0,0 +1,170 @@
# F3 Simple Blog
Blog simple avec Fat-Free Framework.
## Structure
```text
project/
├── config.local.ini # Surcharges locales (gitignored)
├── app/
│ ├── config.ini # Routes et variables F3
│ ├── bootstrap.php # Initialisation (DB, session, cache, erreurs)
│ ├── Controllers/
│ ├── Helpers/ # Fonctions utilitaires (App.php, Error.php)
│ ├── Models/ # DB\SQL\Mapper (Post, Media, User)
│ ├── Services/ # MarkdownService
│ └── Views/
├── db/
│ └── app.sqlite
├── logs/
│ ├── app.log
│ └── php-error.log
├── public/
│ ├── assets/ # Sources CSS/JS (servis minifiés via /min/@file)
│ └── uploads/
│ └── media/ # Images converties en PNG (sans perte)
└── tmp/
├── cache/ # Cache F3 (pages publiques + assets minifiés)
└── uploads/ # Transit Web::receive() — vidé après chaque upload
```
## Philosophie des dossiers runtime
Le projet garde la même logique en local et dans Docker :
- `tmp/` = runtime temporaire, recréable
- `db/` = base SQLite persistante
- `logs/` = logs persistants
- `public/uploads/media/` = médias publiés et persistants
Autrement dit, `tmp/` peut être vidé sans perte métier. Les données à sauvegarder restent hors de `tmp/`.
## Fonctionnalités F3 utilisées
- **Routage nommé** — `config.ini [routes]`, `$f3->alias()`
- **Cache HTTP + serveur** — `$f3->expire()` sur les routes publiques, `Cache::reset('.url')` à la mutation
- **Assets minifiés** — `Web::minify()` via `AssetController` (`GET /min/@file`)
- **Upload** — `Web::receive()` avec callback de validation taille
- **Images** — `Image` (chargement, conversion PNG, dimensions), `Base::write()` pour l'écriture
- **Markdown** — `Markdown::instance()->convert()`
- **Slugs** — `Web::instance()->slug()`
- **Session** — `$f3->set('JAR', …)`, token CSRF dans `SESSION.csrf_token`
- **Logging** — `Log` de F3 avec fallback `file_put_contents`
- **ORM** — `DB\SQL\Mapper` : `paginate()`, `copyfrom()`, `cast()`, `find()`
## Prérequis
### Développement local
- PHP 8.3+
- Composer
- Extensions PHP : `pdo_sqlite`, `dom`, `gd`, `mbstring`
### Déploiement Docker
- Docker
- Docker Compose
## Configuration
Les paramètres par défaut sont dans `app/config.ini`.
Pour surcharger localement ou en production :
```bash
cp config.local.ini.example config.local.ini
```
Réglages minimums conseillés en production :
```ini
[globals]
app.env=prod
app.timezone=Europe/Paris
```
Le fichier `config.local.ini` sert uniquement aux surcharges d'environnement. Les chemins runtime restent les mêmes partout :
- `tmp/cache/` pour le cache F3 et les assets minifiés
- `tmp/uploads/` pour les fichiers temporaires d'upload
## Développement local
```bash
composer install
cp config.local.ini.example config.local.ini
php scripts/install.php
php -S 127.0.0.1:8080 -t public
```
Ouvre ensuite `http://127.0.0.1:8080`.
Créer un compte admin :
```bash
php scripts/create-admin.php admin
# mot de passe : 10 caractères minimum
```
## Déploiement avec Docker
```bash
cp config.local.ini.example config.local.ini
# édite config.local.ini (app.env=prod, app.timezone, etc.)
docker compose up -d --build
```
Docker monte les mêmes dossiers runtime que le développement local. Seuls les répertoires persistants restent séparés de `tmp/`.
Si `config.local.ini` n'existe pas, le conteneur démarre avec les valeurs par défaut de `app/config.ini`.
Le service écoute sur `http://127.0.0.1:8888`.
Créer un compte admin :
```bash
docker compose exec app php scripts/create-admin.php admin
# mot de passe : 10 caractères minimum
```
## Reverse proxy Caddy
### Caddy sur le même hôte
```caddy
blog.example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:8888
}
```
### Caddy dans Docker
Si Caddy tourne aussi dans Docker, place-le sur le même réseau que `app` et cible directement le service :
```caddy
blog.example.com {
encode zstd gzip
reverse_proxy app:80
}
```
## Données à sauvegarder
- `db/` — base SQLite
- `public/uploads/media/` — images
- `logs/` — optionnel
- `tmp/` — non persistant, recréable
## Mise à jour
```bash
docker compose up -d --build
```
## Logs
- Applicatifs : `logs/app.log`
- PHP : `logs/php-error.log`
- Apache (conteneur) : `docker compose logs -f app`