2026-03-30 00:00:03 +02:00
2026-03-30 00:00:03 +02:00
2026-03-27 14:43:08 +01:00
2026-03-29 21:01:07 +02:00
2026-03-27 14:43:08 +01:00
2026-03-30 00:00:03 +02:00
2026-03-30 00:00:03 +02:00
2026-03-27 22:30:10 +01:00
2026-03-27 22:50:42 +01:00
2026-03-29 01:49:25 +01:00
2026-03-29 01:49:25 +01:00
2026-03-30 00:00:03 +02:00
2026-03-27 22:56:24 +01:00
2026-03-30 00:00:03 +02:00
2026-03-30 00:00:03 +02:00

F3 Simple Blog

Blog simple construit autour de deux objectifs :

  • simplicité conceptuelle ;
  • fidélité à Fat-Free Framework.

Le rendu visuel est volontairement soigné, mais le backend reste petit et lisible :

  • 3 contrôleurs : SiteController, AuthController, AdminController
  • 1 contrôleur de base : Controller
  • 3 modèles : Post, Media, User
  • 1 service dédié : MarkdownService
  • 1 bootstrap F3
  • 2 scripts CLI : installation et création d'admin

Structure

project/
├── app/
│   ├── bootstrap.php
│   ├── config.ini
│   ├── helpers.php
│   ├── Controllers/
│   ├── Models/
│   ├── Services/
│   └── Views/
├── db/
├── logs/
├── public/
│   ├── assets/
│   └── uploads/media/
├── docker/
├── scripts/
│   ├── bootstrap.php
│   ├── install.php
│   └── create-admin.php
└── tmp/uploads/

Ce qui est utilisé côté F3

  • routes dans config.ini
  • DB\SQL\Mapper pour les trois tables
  • Auth pour la connexion
  • Session pour la session et le jeton CSRF de base
  • Template pour le rendu et le filtre date_fr
  • Web::receive() pour lupload
  • Markdown pour le rendu des articles
  • Web::slug() pour les slugs

Choix de simplicité

  • pas de namespaces ;
  • pas de couche repository ;
  • pas de système de migrations ;
  • pas de container DI ;
  • pas de logique de proxy avancée ;
  • un seul contrôleur admin pour les articles et la médiathèque ;
  • pas dimage de couverture dédiée : la première image du corps sert de vignette de carte.

Choix éditorial simplifié

Les articles n'ont plus de champ “image de couverture”. Les images vivent uniquement dans le Markdown, et la première image rendue dans body_html est réutilisée comme vignette dans les cartes darticle. Cela réduit le nombre de champs, supprime un cas métier entier, et garde un rendu visuel cohérent.

Simplifications supplémentaires

  • zéro HTML brut : le HTML saisi dans le Markdown est neutralisé avant le passage dans le parseur Markdown ; seuls les éléments générés par Markdown puis validés par le sanitizer sont rendus ;
  • images stockées brutes : lupload accepte uniquement JPG et PNG, vérifie que le fichier est bien une image, puis le stocke tel quel sans réencodage ni transformation ; la dépendance à GD est supprimée.

Pré-requis

Développement local

  • PHP 8.3+
  • Composer
  • extensions : pdo_sqlite, mbstring, intl, dom

Déploiement Docker

  • Docker
  • Docker Compose

Démarrage local

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 :

php scripts/create-admin.php admin

Configuration

Le fichier app/config.ini contient les valeurs par défaut. Tu peux les surcharger dans config.local.ini.

Exemple minimal en production :

[globals]
app.env=prod
app.timezone=Europe/Paris

Important sur le mode prod

Par défaut, app/config.ini laisse app.env=dev. Pour un vrai déploiement, il faut donc fournir un config.local.ini avec app.env=prod, sinon lapplication gardera un comportement de développement.

Déploiement Docker derrière Caddy

Le projet est cohérent pour un déploiement simple :

  • Apache sert public/ dans le conteneur ;
  • compose.yaml expose lapplication sur 127.0.0.1:8888 par défaut ;
  • Caddy termine TLS et reverse-proxy vers cette cible ;
  • SQLite, les logs et les uploads sont montés sur des volumes hôtes.

Exemple :

cp config.local.ini.example config.local.ini
# édite config.local.ini : app.env=prod
docker compose up -d --build

Le Caddyfile.example donne une base de reverse proxy. Le point important est de nexposer publiquement que Caddy. Lapplication Apache/PHP ne doit pas être accessible directement depuis Internet.

Volumes persistants à sauvegarder

Pour sauvegarder le blog, il faut au minimum conserver :

  • db/app.sqlite
  • public/uploads/media/

Les logs peuvent aussi être conservés si tu veux garder lhistorique derreurs.

Contrat Markdown

Le projet assume un Markdown simple :

  • titres, listes, citations, code, liens et images Markdown ;
  • pas de HTML brut auteur ;
  • les images du contenu utilisent la syntaxe media:nom-de-fichier.ext ;
  • les images externes ne sont pas rendues ;
  • avec le parseur Markdown de F3, laisse une ligne vide entre deux blocs pour un rendu fiable.

Limite volontaire : pas de migrations

scripts/install.php crée les tables si elles nexistent pas. En revanche, il ne gère pas les évolutions de schéma. Si le modèle de données change dans le futur, il faudra soit repartir dune base propre, soit appliquer une migration manuelle.

Nettoyage de confort appliqué

  • suppression d'une méthode utilitaire inutilisée dans Media ;
  • suppression d'un paramètre mort dans Post::usesMedia() ;
  • simplification de l'upload temporaire côté admin ;
  • détection secure des cookies un peu plus tolérante (HTTPS, REQUEST_SCHEME, X-Forwarded-Proto) sans réintroduire une grosse logique proxy.
Description
No description provided
Readme 301 KiB
Languages
PHP 48.4%
HTML 20.6%
CSS 19.7%
JavaScript 7.1%
Dockerfile 2.6%
Other 1.6%