← Retour aux projets

Mon site perso : SvelteKit, blog et terminal

sveltekittypescriptblogfrontendself-hosting
· Voir le projet

Pourquoi ce site ?

J’avais besoin d’un endroit pour expliquer mes projets et raconter ce que je fais, ainsi que mes expériences. Tout ce que je n’avais pas la place de mettre sur LinkedIn ou qui n’y aurait pas forcément sa place, c’est un site pour moi avant tout : des articles, des projets et un petit terminal interactif, parce que sinon ça fait un peu trop simple, même si j’aime bien le style minimaliste.

Avant ça, j’avais déjà fait des sites plus simples, au début avec HTML + JS vanilla et Flask, puis avec Svelte. J’essaie de faire quelque chose de propre, que je puisse faire évoluer facilement et qui tourne sur mon cluster comme le reste.

Repo : github.com/BaptTF/bapttf-front

Vue d’ensemble

Le site, c’est un frontend SvelteKit en TypeScript, servi en statique. Le contenu vit dans des fichiers Markdown. Sur la home, il y a un terminal qui parle à un backend Go via WebSocket.

BriqueChoixRôle
FrontendSvelteKit + TypeScriptApp, routing, pages
ContenuMarkdown + mdsvexArticles et pages projet
StyleTailwind CSS 4UI
Buildadapter-staticExport HTML/CSS/JS
Serveurstatic-web-serverServir le build en prod
Backend terminalGo (API + WebSocket)Easter egg / Hall of Root
DeployDocker → GHCR → ArgoCDGitOps sur mon K3S

Le frontend est volontairement simple. Pas de CMS, pas de base de données pour le blog. Un dossier src/posts/, des fichiers .md, et c’est tout.

Stack frontend

SvelteKit

J’ai choisi SvelteKit parce que j’en avais déjà fait et que j’aime bien. C’est léger, c’est super intuitif. Le modèle avec les +page.svelte / +page.ts, le routage par fichiers et le fait de pouvoir générer du statique, c’est vraiment bien.

Le site tourne avec Svelte 5 ($props(), $state(), $effect()). Au début il faut comprendre, mais une fois pris en main c’est agréable.

Contenu en Markdown

Les articles sont des fichiers Markdown avec du frontmatter. mdsvex les transforme en composants Svelte. Un article “classique”, c’est juste un titre, une date et des tags. Un article de projet a en plus un bloc project :

project:
  slug: bapttf-front
  link: "https://github.com/BaptTF/bapttf-front"
  description: "Mon site perso, portfolio, blog et terminal interactif."
  featured: true

C’est ce qui permet d’avoir à la fois un blog et une page projets sans dupliquer le contenu. Un projet = un article. Si je veux parler d’un repo, j’écris l’article, je mets le frontmatter project, et il apparaît automatiquement.

Design

L’UI est volontairement sobre : navbar, footer, dark mode via prefers-color-scheme, pas de framework de composants trop lourd. L’idée, c’était que le contenu passe avant le design. Le terminal est le seul élément un peu lourd de la home.

Le terminal et le Hall of Root

En cours : le terminal interactif n’est pas encore sur la page d’accueil (backend Go à finir).

Sur la page d’accueil, il y a un faux terminal. Il se connecte en WebSocket à mon API Go ; tu peux taper des commandes et, si tu trouves le mot de passe root… tu rentres dans le Hall of Root.

C’est un easter egg. Tu obtiens les privilèges, tu entres un pseudo et tu apparais sur /root avec les autres qui ont réussi. Rien d’utile, c’est juste un petit challenge de cybersécurité parce que j’aime bien les CTF.

Côté frontend, c’est un composant Svelte qui gère :

  • la connexion WebSocket
  • l’affichage des lignes
  • le prompt $ / #
  • la popup du pseudo une fois root obtenu

Les URLs API/WS passent par des variables d’environnement (PUBLIC_API_URL, PUBLIC_WS_URL) injectées au build Docker.

Build et déploiement

Le site est généré en statique. Pas de Node en prod côté frontend : SvelteKit génère les pages, et static-web-server les sert dans le conteneur.

Le Dockerfile est en multi-stage :

  1. node:22-alpinenpm ci + npm run build
  2. image finale légère avec le dossier build/

La CI GitHub Actions fonctionne ainsi :

  1. check + lint + build
  2. sur main, build de l’image Docker
  3. push sur GHCR (latest + tag sha)
  4. ArgoCD côté cluster récupère la nouvelle image

Autrement dit : un push sur main, et le site se met à jour tout seul. Même logique que le reste de mon infra, décrite dans l’article vps-infra.

Choix techniques

Pourquoi du statique ?

Un site perso n’a pas besoin d’un runtime Node. De l’HTML pré-généré, c’est plus simple à héberger, plus rapide, et ça consomme quasi rien sur le cluster. Les seules parties dynamiques (terminal, Hall of Root) passent par l’API Go à côté.

Pourquoi Markdown plutôt qu’un CMS ?

Parce que je veux écrire dans mon éditeur, versionner le contenu avec le code, et ouvrir une PR si j’ai envie. Pas de panneau d’admin, pas de plugin qui casse, pas de base à sauvegarder pour trois articles.

Pourquoi un backend séparé pour le terminal ?

Le frontend ne doit pas connaître le mot de passe root ni gérer la liste des rooters. Ça vit côté backend. Le site reste statique, les secrets doivent rester dynamiques. Et ça me donne une raison d’avoir un petit backend dans la stack.

Ce que j’aimerais améliorer

C’est un premier jet qui marche, mais il y a clairement de la marge :

  • Plus de contenu — le site existe, maintenant il faut écrire
  • Le backend Go — mieux documenter l’API du terminal / Hall of Root, peut-être la lier plus clairement depuis cet article
  • SEO / métadonnées — Open Graph, descriptions propres par page
  • Quelques améliorations UX — navigation au clavier dans le terminal, meilleurs états de chargement sur /root
  • Tests — aujourd’hui la CI fait check/lint/build, pas encore de vrais tests

En résumé

Mes choix

  • SvelteKit + adapter-static : simple, rapide, parfait pour un site perso self-hosté
  • Articles = source de vérité pour le blog et les projets
  • GitOps jusqu’au bout : même pipeline que le reste de mon infra
  • Le terminal : un petit aspect fun du site, et ça permet d’avoir un frontend + backend

Choix discutables

  • Deux repos / deux services (front + API Go) pour un site perso, c’est peut-être overkill, mais j’aime que ce soit propre.

Ce que je changerais

  • Clarifier le lien entre ce repo et le backend terminal dans la doc

En résumé : c’est mon petit site sur internet. C’est pas révolutionnaire, mais c’est à moi, c’est propre, ça tourne sur mon cluster et ça me permet d’écrire sur ce que je veux.

© 2026 Baptiste