En 1995, vous créiez index.html, écriviez <h1>Bonjour</h1>, le téléchargiez sur un serveur, et ça marchait. La boucle de retour se mesurait en secondes. Un enfant de douze ans pouvait construire un site web en un après-midi. Tout le web était construit par des gens qui n'étaient pas des programmeurs professionnels -- c'étaient des enseignants, des étudiants, des hobbyistes, des propriétaires de petites entreprises qui avaient besoin d'une présence sur ce nouveau truc appelé internet.
En 2024, créer l'équivalent de ce hello world nécessite d'installer Node.js, d'initialiser un projet, d'installer React, ReactDOM, Vite, TypeScript, les définitions de types, Tailwind, PostCSS, Autoprefixer, ESLint, Prettier, puis de créer une douzaine de fichiers de configuration avant d'écrire une seule ligne de code applicatif. Le nombre de dépendances approche les 2 000 paquets. L'empreinte disque dépasse 1,5 giga-octet. Le temps jusqu'au premier rendu se mesure en heures.
FLIN existe parce que nous croyons que cette trajectoire n'est pas inévitable. C'est un choix que l'industrie a fait, et c'est un choix que nous pouvons défaire. Pas en revenant aux limitations de 1995, mais en allant de l'avant -- en construisant un langage qui offre la simplicité de cette époque avec toute la puissance de 2026 : un compilateur, une machine virtuelle, une base de données embarquée, une interface réactive et un serveur HTTP. Le tout derrière un seul fichier.
Cet article raconte l'histoire de cette vision : d'où elle vient, à quoi elle ressemble en pratique, et pourquoi la complexité du développement web moderne n'est pas une loi naturelle.
L'explosion de la complexité : une chronologie
Pour comprendre la raison d'être de FLIN, il faut voir comment nous en sommes arrivés là. Les chiffres ne sont pas exagérés -- ils sont conservateurs.
Année Fichiers pour "Hello World" Dépendances Fichiers config Espace disque
----- --------------------------- ----------- --------------- -------------
1995 1 (index.html) 0 0 3 Ko
2005 3 (HTML/CSS/JS) 0 0 15 Ko
2010 10 + jQuery 5 1 500 Ko
2015 50 + Gulp 200 5 80 Mo
2020 500 + Webpack 1 000 10 500 Mo
2024 50 000+ 2 000 15+ 1,5 GoChaque étape de cette progression était rationnelle isolément. jQuery a résolu la compatibilité entre navigateurs. Gulp a résolu l'automatisation de build. Webpack a résolu le bundling de modules. React a résolu la gestion d'état de l'interface. TypeScript a résolu la sûreté des types. Tailwind a résolu les classes utilitaires CSS. Chaque outil a résolu un vrai problème.
Mais l'effet agrégé est que les outils censés nous aider sont devenus le problème. Un développeur moderne passe plus de temps à configurer des outils qu'à écrire du code applicatif. La courbe d'apprentissage, autrefois mesurée en jours, prend maintenant des mois. Et dans les marchés émergents -- où l'internet est lent, les données sont chères et l'électricité n'est pas fiable -- télécharger 1,5 Go de node_modules n'est pas un inconvénient. C'est une barrière à l'entrée.
L'observation qui a lancé FLIN
FLIN est né d'une observation simple : la plupart des applications web font les mêmes cinq choses.
- Afficher des données à l'utilisateur.
- Réagir aux entrées de l'utilisateur.
- Sauvegarder des données dans une base de données.
- Interroger des données depuis une base de données.
- Gérer des requêtes HTTP.
Cinq choses. Et pourtant, pour faire ces cinq choses en 2024, vous avez besoin de React pour la première, d'une bibliothèque de gestion d'état pour la deuxième, de Prisma ou TypeORM pour la troisième et la quatrième, d'Express ou Fastify pour la cinquième, plus TypeScript, Vite, ESLint, Prettier, Tailwind, et une douzaine de fichiers de configuration pour tout relier.
La question qui a lancé FLIN était : et si un seul outil faisait nativement ces cinq choses ?
Pas un framework. Pas une bibliothèque. Pas un toolkit "batteries incluses" qui nécessite toujours npm et Node.js sous le capot. Un langage de programmation. Un dans lequel la réactivité, la persistance, les requêtes et la gestion HTTP sont intégrées à la syntaxe elle-même, de la même façon que l'arithmétique et les opérations sur les chaînes sont intégrées à chaque langage.
À quoi ressemble FLIN : l'application la plus simple
Voici une application FLIN complète et fonctionnelle. Pas un jouet. Pas un "hello world" qui omet les parties difficiles. Un compteur fonctionnel avec un bouton qui incrémente un nombre et l'affiche :
flincount = 0
<button click={count++}>{count}</button>Deux lignes de logique. Une ligne de vue. Sauvegardez-la sous app.flin. Lancez flin dev. Le navigateur s'ouvre. Vous cliquez sur le bouton. Le nombre augmente. Il n'y a pas d'instruction import, pas de fichier de configuration, pas d'étape de build, pas de gestionnaire de paquets, pas d'initialisation de framework.
Comparez avec l'équivalent React :
jsximport { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
{count}
</button>
);
}La version React nécessite de comprendre les imports, le hook useState, les fonctions fléchées, la syntaxe JSX et le concept d'export par défaut. La version FLIN nécessite de comprendre les variables et le HTML. Un enfant de douze ans qui sait ce que <button> signifie peut lire le code FLIN et comprendre ce qu'il fait en trente secondes.
Ce n'est pas une différence superficielle. C'est la différence entre un langage conçu pour des développeurs qui comprennent déjà la programmation, et un langage conçu pour des humains qui veulent construire des choses.
À quoi ressemble FLIN : une vraie application
Le compteur est simple exprès. Voici quelque chose de réel : une application todo complète avec stockage persistant, filtrage et opérations CRUD.
flintodos = []
filter = "all"
newTodo = ""
entity Todo {
title: text
done: bool = false
created: time = now
}
filtered = match filter {
"all" -> Todo.all
"active" -> Todo.where(done == false)
"completed" -> Todo.where(done == true)
}
<main>
<h1>Mes Todos</h1>
<input value={newTodo} placeholder="Que faut-il faire ?"
enter={save Todo { title: newTodo }; newTodo = ""}>
<nav>
<button click={filter = "all"}>Tous</button>
<button click={filter = "active"}>Actifs</button>
<button click={filter = "completed"}>Faits</button>
</nav>
{for todo in filtered}
<div class="todo-item">
<input type="checkbox" checked={todo.done}
change={todo.done = !todo.done; save todo}>
<span class={if todo.done then "done" else ""}>{todo.title}</span>
<button click={delete todo}>x</button>
</div>
{/for}
<footer>{Todo.where(done == false).count} éléments restants</footer>
</main>Quarante-trois lignes. Une application complète avec une entité soutenue par une base de données, une interface réactive, du filtrage, de la création, de la bascule, de la suppression et un compteur en direct des éléments restants. Pas de configuration. Pas d'imports. Pas d'outils de build. Le mot-clé entity indique au compilateur FLIN que Todo est un type de données persistant stocké dans FlinDB. Les mots-clés save et delete effectuent des opérations de base de données. Le bloc {for ... in ...} itère sur les résultats de requête. L'expression match sélectionne la bonne requête en fonction du filtre courant.
Pour construire la même application en React, vous auriez besoin de : React, une solution de gestion d'état, un framework backend (Express ou routes API Next.js), une base de données (PostgreSQL ou SQLite), un ORM (Prisma ou Drizzle), une solution CSS et un outil de build. La base de code résultante s'étendrait sur plusieurs fichiers à travers des répertoires frontend et backend, avec des fichiers de configuration pour chaque outil.
La puissance derrière la simplicité
La simplicité de la syntaxe de FLIN n'est pas obtenue en limitant ses capacités. Elle est obtenue en déplaçant la complexité dans le compilateur et le runtime, là où elle appartient. Derrière chaque fichier FLIN se trouve un pipeline de compilation en quatre phases et un runtime multi-composants.
Quand vous écrivez count = 0 dans FLIN, le compilateur ne stocke pas simplement un nombre. Il crée un binding réactif -- une variable qui, quand elle change, déclenche automatiquement des mises à jour de l'interface dans chaque vue qui la référence. C'est le même modèle de réactivité que React, Vue et Svelte implémentent avec les hooks, les refs et les runes, respectivement. La différence est que dans FLIN, c'est le comportement par défaut. Vous n'optez pas pour la réactivité. Chaque variable est réactive.
Quand vous écrivez entity Todo { title: text }, le compilateur génère un schéma de base de données, crée une table dans FlinDB, enregistre les méthodes de requête (Todo.all, Todo.where(...), Todo.find(...)), et met en place le suivi temporel pour que chaque enregistrement maintienne son historique complet. Une ligne de FLIN remplace la définition de schéma Prisma, le fichier de migration, la classe de modèle et le pattern repository.
Quand vous écrivez save todo, le runtime sérialise l'entité, l'écrit dans le WAL (Write-Ahead Log) de FlinDB, met à jour le cache en mémoire, invalide tous les caches de requête qui référencent le type Todo, et déclenche des mises à jour réactives dans toutes les vues qui affichent des données todo. Un mot-clé remplace un appel d'API, une transaction de base de données, une invalidation de cache et une mise à jour d'état.
Source FLIN Ce que le compilateur/runtime fait réellement
----------- ------------------------------------------
count = 0 Allouer une variable réactive, enregistrer dans le graphe de dépendances
entity Todo {...} Générer le schéma, créer la table, enregistrer les méthodes de requête,
activer le suivi temporel
save todo Sérialiser, écriture WAL, mise à jour du cache, invalidation du cache,
mise à jour réactive de l'interface
Todo.where(...) Génération de requête SQL, binding de paramètres, désérialisation des
résultats, mise en cache optionnelle
{for todo in ...} Diff du DOM virtuel, rendu incrémentiel de liste,
réconciliation par cléLe développeur écrit cinq choses. Le compilateur et le runtime en font cinquante. C'est le marché que FLIN propose : vous pensez à votre application, et l'outillage pense à tout le reste.
La liste des éliminations
Quand vous adoptez FLIN, vous arrêtez d'utiliser tout un écosystème d'outils. Ce n'est pas une affirmation abstraite -- c'est une liste concrète.
Côté frontend, les vues réactives de FLIN remplacent React, Vue, Svelte et Angular. Le routage basé sur les fichiers de FLIN remplace Next.js, Nuxt et SvelteKit. Les variables réactives de FLIN remplacent Redux, Zustand et Pinia. La récupération de données intégrée de FLIN remplace React Query et SWR.
Côté backend, les gestionnaires de routes de FLIN remplacent Express, Fastify et NestJS. Le système d'entités de FLIN remplace Prisma, TypeORM et Drizzle. FlinDB remplace PostgreSQL, MySQL, Redis, Elasticsearch et Pinecone.
En outillage, FLIN remplace npm, Webpack, Vite, TypeScript, ESLint, Prettier, Jest et Docker.
En configuration, FLIN remplace package.json, tsconfig.json, vite.config.js, tailwind.config.js, .eslintrc, .prettierrc, postcss.config.js, docker-compose.yml et les fichiers .env.
Les chiffres racontent l'histoire :
Métrique Pile Node.js FLIN Réduction
------ ----------- ---- ---------
Fichiers (Hello World) 50 000+ 1 99,998 %
Dépendances 1 847 0 100 %
Fichiers de config 15+ 0 100 %
Espace disque 1,5 Go ~50 Ko 99,997 %
Temps pour démarrer 2 heures 2 minutes 98,3 %Pourquoi cela compte pour l'Afrique
FLIN a été créé à Abidjan, en Côte d'Ivoire, et sa conception reflète les contraintes de la construction logicielle en Afrique de l'Ouest.
Quand votre connexion internet tourne en moyenne à 5 Mbps les bons jours, télécharger 1,5 Go de node_modules n'est pas une attente de cinq minutes -- c'est une épreuve de plusieurs heures qui consomme des données mobiles chères. Quand les coupures de courant interrompent votre travail, un long build Webpack qui échoue en plein milieu signifie recommencer. Quand votre ordinateur portable a 4 Go de RAM, faire tourner un serveur de développement à côté de VS Code et d'un navigateur nécessite une gestion mémoire soignée que les chaînes d'outils JavaScript modernes ignorent allègrement.
Le modèle zéro-dépendance de FLIN élimine tous ces points de friction. Il n'y a rien à télécharger. Il n'y a pas d'étape de build en mode développement -- le compilateur et le runtime gèrent tout à la volée. L'empreinte mémoire se mesure en méga-octets, pas en giga-octets.
Mais l'argument est plus large que les contraintes d'infrastructure. La complexité du développement web moderne est une barrière à la participation. Un adolescent à Dakar qui veut construire un site web rencontre un écosystème qui exige des mois d'étude avant de produire quoi que ce soit de significatif. L'écart entre "je connais le HTML" et "je peux construire une application web" s'est élargi de jours à des mois.
FLIN comble cet écart. Si vous savez ce que <button> signifie et que vous comprenez que count = 0 crée une variable, vous pouvez construire une application FLIN. La progression de débutant à développeur productif se mesure en heures, pas en mois. Et parce que le langage gère nativement la persistance, la réactivité, le routage et le HTTP, vous ne heurtez jamais le mur de "maintenant je dois apprendre une technologie complètement différente pour le backend".
Ce qui est bon pour Lagos est bon pour Londres. Les contraintes qui rendent FLIN nécessaire en Afrique le rendent meilleur partout : des cycles de développement plus rapides, des déploiements plus petits, des coûts d'hébergement réduits et un modèle mental plus simple.
La dimension IA
Il y a un deuxième public pour la simplicité de FLIN qui n'existait pas en 1995 : les générateurs de code par IA.
Quand un modèle de langage génère du code FLIN, les chances de produire un programme correct sont dramatiquement plus élevées qu'avec une pile React/TypeScript/Prisma. Les raisons sont structurelles :
- Pas d'imports à halluciner. Les modèles d'IA génèrent fréquemment des instructions import pour des paquets qui n'existent pas ou ont été renommés. FLIN n'a pas d'imports.
- Pas de configuration à mal configurer. Un pourcentage significatif des erreurs de code généré par IA vient de fichiers de configuration incorrects. FLIN n'a pas de fichiers de configuration.
- Un fichier par composant. L'IA n'a pas besoin de coordonner des changements à travers des répertoires frontend et backend. Tout est au même endroit.
- Surface syntaxique minimale. Moins de mots-clés, moins de patterns, moins de façons d'exprimer la même chose. Cela réduit la probabilité de générer du code syntaxiquement valide mais sémantiquement incorrect.
FLIN est conçu pour un avenir où l'IA écrit la plupart du code. Plus le langage est simple, plus fiablement l'IA peut l'utiliser, plus les humains deviennent productifs en dirigeant des agents IA pour construire des applications.
Les compromis honnêtes
La simplicité de FLIN s'accompagne de vraies contraintes qu'il vaut la peine d'énoncer clairement.
Vous ne pouvez pas utiliser de paquets npm. FLIN n'a pas de gestionnaire de paquets et pas d'interopérabilité avec l'écosystème JavaScript. Si votre application nécessite une bibliothèque npm spécifique -- disons, une bibliothèque de graphiques ou un kit de génération de PDF -- FLIN ne peut pas l'utiliser directement. Le langage fournit 409 fonctions intégrées couvrant les besoins les plus courants (cryptographie, traitement d'images, email, paiements, génération de PDF), mais des cas limites existent.
Vous apprenez un nouveau langage. La syntaxe de FLIN est conçue pour être intuitive, mais ce n'est pas JavaScript, Python ou un langage que vous connaissez déjà. Il y a un investissement d'apprentissage, même s'il est plus petit que celui d'un nouveau framework.
L'écosystème est jeune. FLIN a 180 composants d'interface embarqués et 1 675 icônes embarquées, mais il n'a pas les milliers de paquets tiers que React ou Vue offrent. Si vous avez besoin d'un composant hautement spécialisé, vous devrez peut-être le construire vous-même.
FlinDB n'est pas PostgreSQL. Pour les applications qui nécessitent des requêtes SQL complexes, des jointures multi-tables ou une compatibilité avec des outils existants basés sur PostgreSQL, FlinDB peut ne pas être suffisant. FLIN est conçu pour des applications qui possèdent leurs données, pas des applications qui s'intègrent avec une infrastructure de base de données existante.
Ces compromis sont intentionnels. FLIN n'essaie pas d'être tout. Il essaie d'être le meilleur outil pour construire des applications web autonomes -- et pour ce cas d'usage, le ratio simplicité/puissance est inégalé.
Le pari philosophique
En 1995, le web était une plateforme ouverte et accessible où n'importe qui pouvait participer. Un gamin à Lagos pouvait concurrencer une équipe à Londres parce que les outils étaient simples et la barrière à l'entrée basse. La croissance explosive du web n'a pas été portée par des développeurs professionnels, mais par des millions de personnes qui ont appris le HTML en un après-midi et ont construit quelque chose.
Quelque part en chemin, l'industrie a décidé que la complexité était le prix de la puissance. Qu'il fallait un diplôme en informatique et des années d'expérience framework pour construire un site web. Que 1 847 dépendances étaient normales. Que 15 fichiers de configuration étaient acceptables. Qu'un environnement de développement de 1,5 Go était bien.
FLIN est un pari que ce compromis est faux. Que vous pouvez avoir la simplicité de 1995 et la puissance de 2026. Qu'un seul langage peut remplacer toute une chaîne d'outils. Qu'un enfant de douze ans qui connaît le HTML devrait pouvoir construire une vraie application web.
C'est un pari que nous faisons depuis Abidjan, avec un compilateur Rust, une IA CTO et la conviction que le prochain million de développeurs web ne viendra pas de San Francisco. Ils viendront de Lagos, Nairobi, Dakar, Abidjan et Kinshasa. Et ils méritent des outils qui respectent leur temps, leur bande passante et leur intelligence.
Prochain dans la série : FLIN en pratique : premiers exemples -- La théorie, c'est gratuit. Voici du vrai code FLIN : une application todo, un blog, une API, un tableau de bord en temps réel et un moteur de recherche sémantique.