Et si vous pouviez supprimer React, Next.js, Redux, Prisma, Express, Tailwind et 41 autres outils -- et les remplacer tous par un seul langage de programmation ?
Ce n'est pas une expérience de pensée. C'est l'objectif de conception de FLIN, et cet article cartographie chaque technologie qu'il remplace, explique pourquoi chaque remplacement est possible, et montre le code qui le prouve.
Nous avons compté. Le nombre est 47. Non pas parce que nous visions un grand nombre, mais parce que c'est le nombre d'outils distincts que l'écosystème JavaScript moderne nécessite pour construire, styliser, servir, persister, rechercher, tester, linter, formater, bundler et déployer une application web de production.
Voici la liste complète des éliminations.
Catégorie 1 : frameworks frontend
Éliminés : React, Vue, Svelte, Angular, Solid, Preact
Six frameworks. Six modèles de composants différents. Six systèmes de réactivité différents. Six syntaxes de templates différentes. Six courbes d'apprentissage différentes. Six communautés qui ne partagent ni code, ni conventions, ni modèles mentaux.
FLIN les remplace tous les six par des vues réactives intégrées au langage lui-même :
flincount = 0
name = ""
<div>
<h1>Bonjour, {if name then name else "Monde"} !</h1>
<input placeholder="Votre nom" value={name}>
<button click={count++}>Cliqué {count} fois</button>
</div>Il n'y a pas de import React from 'react'. Il n'y a pas de balise <script> enveloppant la logique. Il n'y a pas de useState, pas de ref(), pas de $state, pas de signal(). Les variables sont réactives parce que le compilateur de FLIN suit quelles variables sont utilisées dans quelles expressions de vue et génère automatiquement du code de mise à jour à grain fin.
L'intuition clé : dans React, vous devez explicitement opter pour la réactivité (useState). Dans Vue, vous devez explicitement déclarer des références réactives (ref). Dans FLIN, la réactivité est le comportement par défaut. Vous écrivez count = 0, et chaque vue qui référence count se met à jour quand il change. Le compilateur gère le reste.
Comparez le même compteur en React :
jsx// React : 12 lignes, 3 imports, 1 hook
import React, { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>
Incrémenter
</button>
</div>
);
}Et en FLIN :
flin// FLIN : 4 lignes, 0 import, 0 hook
count = 0
<button click={count++}>{count}</button>Quatre lignes. Zéro cérémonie. Le même résultat.
Catégorie 2 : méta-frameworks
Éliminés : Next.js, Nuxt, SvelteKit, Remix, Astro
Les méta-frameworks existent parce que les frameworks frontend ne résolvent que la moitié du problème. React rend l'interface, mais ne gère pas le routage, le rendu côté serveur, les points d'API ou la génération statique. Next.js comble cette lacune pour React. Nuxt pour Vue. SvelteKit pour Svelte.
FLIN n'a pas besoin de méta-framework parce que c'est un langage complet, pas une bibliothèque d'interface. Le routage est basé sur les fichiers :
my-app/
index.flin --> /
about.flin --> /about
products/
index.flin --> /products
[id].flin --> /products/:id
api/
users.flin --> /api/users
users/[id].flin --> /api/users/:idLes routes dynamiques utilisent la syntaxe entre crochets. Les paramètres sont disponibles via l'objet params :
flin// products/[id].flin
product = Product.find(params.id)
{if product}
<h1>{product.name}</h1>
<p>{product.description}</p>
<span class="price">{product.price}</span>
{else}
<h1>Produit non trouvé</h1>
{/if}Les routes d'API utilisent le mot-clé route avec des déclarations de méthode HTTP :
flin// api/users.flin
route GET {
User.where(active == true)
}
route POST {
user = User {
name: body.name,
email: body.email,
role: body.role || "user"
}
save user
user
}Pas d'Express. Pas de Fastify. Pas de chaîne de middleware. Pas d'objets requête/réponse à déstructurer. La variable body est le corps de la requête parsé. La valeur de retour est la réponse JSON. FLIN gère la sérialisation, les en-têtes content-type et les codes de statut HTTP automatiquement.
Catégorie 3 : gestion d'état
Éliminés : Redux, Zustand, Pinia, MobX, Recoil, Jotai
Les bibliothèques de gestion d'état existent parce que le modèle de composants de React rend difficile le partage d'état entre des composants distants. Redux à lui seul a engendré un sous-écosystème entier : Redux Toolkit, Redux Saga, Redux Thunk, Redux Persist, React Redux.
FLIN élimine toute la catégorie avec une seule règle : toutes les variables sont réactives par défaut.
flin// Voici l'intégralité de la solution de gestion d'état de FLIN
count = 0
userName = "Guest"
items = []
filter = "all"
// Les valeurs calculées se réévaluent automatiquement
filtered = match filter {
"all" -> items
"active" -> items.where(x => x.done == false)
"completed" -> items.where(x => x.done == true)
}Il n'y a pas de store. Pas de reducer. Pas de créateur d'actions. Pas de sélecteur. Pas de useDispatch. Pas de useSelector. Pas de wrapper Provider. Les variables existent au niveau du fichier, et toute expression de vue qui les référence se met à jour quand elles changent.
Redux seul nécessite de comprendre les actions, les reducers, le store, le middleware, les sélecteurs et l'API connect/hooks -- six concepts distincts pour résoudre un problème qui, dans FLIN, ne nécessite aucun concept parce qu'il est intégré au modèle d'exécution du langage.
Catégorie 4 : récupération de données
Éliminés : React Query, SWR, TanStack Query, Apollo Client
Les bibliothèques de récupération de données existent parce que React n'a aucun moyen intégré de récupérer des données, de les mettre en cache, d'invalider les caches, de gérer les états de chargement ou de réessayer les requêtes échouées. React Query encapsule tout cela dans des hooks comme useQuery et useMutation.
Dans FLIN, les données viennent des entités. Les entités sont soutenues par FlinDB, la base de données embarquée de FLIN. Il n'y a pas de fetch, pas d'état de chargement à gérer, pas de cache à configurer :
flin// Les données sont simplement là
users = User.all
recentPosts = Post.order(created, "desc").limit(10)
activeProducts = Product.where(active == true)
// Le filtrage est réactif
searchQuery = ""
results = if searchQuery.len > 3 then
search searchQuery in Product by description limit 20
else
Product.allLa "bibliothèque" de récupération de données, c'est le langage lui-même.
Catégorie 5 : frameworks CSS
Éliminés : Tailwind CSS, Styled Components, CSS Modules, Emotion, Sass
FLIN adopte une approche pragmatique du stylisme. Vous pouvez utiliser du CSS pur -- le langage ne force pas de solution de style spécifique. Mais la bibliothèque de composants prévue de FLIN, Elephant UI, fournira plus de 70 composants préconçus pour le langage.
Plus important encore, FLIN élimine la chaîne d'outils que les frameworks CSS nécessitent. Tailwind a besoin de PostCSS, d'un fichier de configuration et d'une étape de build pour purger les classes inutilisées. Styled Components nécessite un plugin Babel. Sass nécessite un compilateur. Dans FLIN, les styles sont simplement du CSS -- pas de préprocesseur, pas de plugin, pas de configuration :
flin<div class="container">
<h1 class="title">Produits</h1>
{for product in products}
<div class="card" style="border-color: {product.color}">
<h3>{product.name}</h3>
<span class="price">{product.price}</span>
</div>
{/for}
</div>La couche de stylisme est intentionnellement simple. La philosophie de FLIN est que le budget de complexité doit être consacré à la logique applicative, pas au choix entre sept façons différentes d'appliquer une couleur de fond.
Catégorie 6 : frameworks backend
Éliminés : Express, Fastify, Koa, Hono, NestJS
Cinq frameworks backend, chacun avec des systèmes de middleware différents, des API de routage différentes, des écosystèmes de plugins différents. FLIN les remplace tous par des déclarations de routes :
flin// api/users/[id].flin
route GET {
User.find(params.id)
}
route PUT {
user = User.find(params.id)
user.name = body.name || user.name
user.email = body.email || user.email
user.role = body.role || user.role
save user
user
}
route DELETE {
user = User.find(params.id)
delete user
{ success: true }
}Chaque gestionnaire de route est un bloc qui reçoit params (paramètres d'URL) et body (corps de la requête) comme variables implicites. La valeur de retour devient la réponse JSON. La gestion des erreurs, la sérialisation et la sémantique HTTP sont gérées par le runtime FLIN.
Comparez avec l'équivalent Express :
javascript// Express : 35+ lignes, setup du routeur, middleware, gestion des erreurs
const express = require('express');
const router = express.Router();
router.get('/:id', async (req, res) => {
try {
const user = await prisma.user.findUnique({
where: { id: req.params.id }
});
if (!user) return res.status(404).json({ error: 'Not found' });
res.json(user);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// ... répéter pour PUT, DELETELa version FLIN est plus courte, plus lisible et gère les mêmes cas. La différence n'est pas du sucre syntaxique -- c'est l'élimination d'une couche entière d'abstraction.
Catégorie 7 : base de données et ORM
Éliminés : configuration PostgreSQL, configuration MySQL, Prisma, TypeORM, Drizzle, Mongoose
C'est là que le principe de conception "memory-native" de FLIN brille. Dans la pile traditionnelle, vous avez besoin de : un serveur de base de données (PostgreSQL ou MySQL), une bibliothèque de connexion, un ORM ou constructeur de requêtes, un outil de migration et un langage de définition de schéma.
FLIN remplace tout cela par le mot-clé entity et FlinDB, sa base de données embarquée :
flinentity User {
name: text
email: text
role: text = "user"
active: bool = true
created: time = now
}
// Créer
save User { name: "Juste", email: "[email protected]" }
// Lire
users = User.all
admins = User.where(role == "admin")
firstUser = User.where(email == "[email protected]").first
// Mettre à jour
user = User.find(id)
user.name = "Juste A. GNIMAVO"
save user
// Supprimer
delete userPas de prisma migrate dev. Pas d'instructions CREATE TABLE. Pas de chaîne de connexion dans un fichier .env. La déclaration entity est simultanément : une définition de type, une table de base de données, un ensemble d'opérations CRUD et un traqueur d'historique. Quand vous écrivez entity User, le runtime de FLIN crée la table, génère les requêtes et gère la connexion -- le tout de manière invisible.
L'équivalent Prisma nécessite un fichier schema.prisma, une migration, une étape prisma generate, puis du code comme prisma.user.findMany({ where: { role: 'admin' } }). Le User.where(role == "admin") de FLIN fait la même chose sans aucune configuration.
Catégorie 8 : recherche
Éliminés : Elasticsearch, Algolia, Meilisearch, Pinecone, Weaviate
La recherche est l'une des fonctionnalités les plus coûteuses opérationnellement dans une pile traditionnelle. La recherche plein texte nécessite Elasticsearch (une application Java qui a besoin de son propre cluster). La recherche sémantique nécessite une base de données vectorielle comme Pinecone ou Weaviate, plus un pipeline d'embeddings.
FLIN intègre les deux dans FlinDB :
flinentity Product {
name: text
description: semantic text // Auto-embedded pour la recherche vectorielle
price: money
category: text
}
// Filtre traditionnel
cheap = Product.where(price < 1000)
// Recherche sémantique (similarité vectorielle)
results = search "chaise de bureau ergonomique confortable"
in Product
by description
limit 10
// Basée sur l'intention (langage naturel vers requête)
trending = ask "produits ajoutés cette semaine avec un prix inférieur à 5000"Le modificateur semantic sur un champ texte indique à FlinDB de calculer automatiquement les embeddings vectoriels. Le mot-clé search effectue une recherche de similarité sur ces embeddings. Le mot-clé ask traduit le langage naturel en requêtes de base de données en utilisant l'IA.
Pas de cluster Elasticsearch. Pas de clé API Pinecone. Pas de pipeline d'embeddings. Pas de gestion d'index. Un mot-clé dans une définition d'entité.
Catégorie 9 : outils de build
Éliminés : Webpack, Vite, Parcel, Rollup, esbuild, Turbopack
Six bundlers. Chacun avec son propre format de configuration, son propre système de plugins, ses propres opinions sur le code splitting, le tree shaking et la résolution de modules.
FLIN élimine entièrement la catégorie :
bashflin dev # Démarrer le serveur de développement
flin build # Build de productionDeux commandes. Zéro configuration. Le compilateur FLIN gère la tokenisation, le parsing, la vérification de types et la génération de code en une seule passe. Il n'y a pas d'étape de "build" séparée parce que le compilateur est l'outil de build.
Le fichier de configuration Vite pour un projet React typique fait 30 à 50 lignes. Une configuration Webpack peut dépasser 200. L'équivalent de configuration de FLIN est : rien. Il n'y a pas de fichier de configuration parce qu'il n'y a rien à configurer.
Catégorie 10 : gestionnaires de paquets
Éliminés : npm, yarn, pnpm, bun (en tant que gestionnaire de paquets)
Quatre gestionnaires de paquets, chacun résolvant le même problème -- télécharger et gérer les dépendances -- avec des formats de lockfile différents, des algorithmes de résolution différents et des caractéristiques de performance différentes.
FLIN n'a pas besoin de gestionnaire de paquets parce que FLIN a zéro dépendance. Tout est intégré. Il n'y a pas de node_modules. Il n'y a pas de package.json. Il n'y a pas de lockfile. Il n'y a pas d'avertissement npm audit concernant 47 vulnérabilités de haute sévérité dans des paquets dont vous n'avez jamais entendu parler.
Les implications pour l'espace disque seul sont stupéfiantes :
Outil Taille node_modules Équivalent FLIN
----------- ------------------- ---------------
create-react-app ~300 Mo 0 octet
Next.js starter ~400 Mo 0 octet
Nuxt starter ~350 Mo 0 octet
Angular starter ~500 Mo 0 octetPour un développeur à Abidjan qui paie au méga-octet de données, l'élimination de node_modules n'est pas un confort. C'est la différence entre pouvoir travailler et ne pas pouvoir travailler.
Catégorie 11 : système de types
Éliminé : TypeScript (en tant qu'outil séparé)
TypeScript est sans doute l'ajout le plus réussi à l'écosystème JavaScript. Il détecte les bugs au moment de la compilation, permet de meilleurs outils et rend les grandes bases de code gérables.
Mais TypeScript est un compilateur séparé avec son propre fichier de configuration (tsconfig.json), ses propres règles de résolution de modules, ses propres conflits de versions et sa propre courbe d'apprentissage. FLIN intègre la vérification de types dans le langage :
flin// Les types sont inférés
name = "Juste" // text
age = 25 // int
price = 99.99 // number
active = true // bool
items = [1, 2, 3] // [int]
// Ou déclarés explicitement
score: number = 0
nickname: text? = none // Texte optionnelLe système de types de FLIN est plus simple que celui de TypeScript -- délibérément. Il n'y a pas de génériques, pas de types conditionnels, pas de types mappés, pas de types de templates littéraux. Le système de types de FLIN couvre les 95 % de cas dont 95 % des applications ont besoin. Les 5 % restants sont de la complexité que la philosophie de FLIN rejette.
Catégorie 12 : outils de qualité du code
Éliminés : ESLint, Prettier, Biome
Trois outils (ou leur successeur, Biome) pour le linting, le formatage et l'application du style de code. Chacun avec son propre fichier de configuration, ses propres règles, son propre système de plugins.
Le compilateur de FLIN inclut un formateur intégré sans configuration. Il y a une seule façon de formater le code FLIN, tout comme il y a une seule façon de formater le code Go (gofmt) ou le code Rust (rustfmt). Les débats sur les tabulations contre les espaces, les points-virgules contre pas de points-virgules, et les guillemets simples contre les guillemets doubles n'existent pas dans FLIN parce que le langage prend ces décisions pour vous.
Catégorie 13 : tests
Éliminés : Jest, Vitest, Mocha, Cypress, Playwright
FLIN inclut un lanceur de tests intégré. Les tests font partie du langage, pas un outil externe avec son propre fichier de configuration, sa propre bibliothèque d'assertions et sa propre résolution de modules.
La conception suit le même principe de zéro configuration : écrivez les tests, lancez flin test, voyez les résultats. Pas de jest.config.js. Pas de vitest.config.ts. Pas de décision sur quel lanceur de tests utiliser.
Catégorie 14 : fichiers de configuration éliminés
Cette catégorie mérite sa propre section car elle représente le symptôme le plus visible du problème des 47 outils :
Fichier de config éliminé Objectif
------------------------------ -----------------------------------
package.json Métadonnées et scripts du paquet
package-lock.json Lockfile des dépendances
tsconfig.json Configuration TypeScript
vite.config.ts Configuration du bundler
webpack.config.js Configuration du bundler
tailwind.config.js Configuration du framework CSS
postcss.config.js Configuration du traitement CSS
babel.config.js Transpilation JavaScript
.eslintrc.js Configuration du linter
.prettierrc Configuration du formateur
jest.config.js Configuration du lanceur de tests
next.config.js Configuration du méta-framework
nuxt.config.js Configuration du méta-framework
svelte.config.js Configuration du méta-framework
docker-compose.yml Orchestration de conteneurs
.env / .env.local / .env.prod Variables d'environnementSeize fichiers de configuration, éliminés. Pas cachés derrière les défauts d'un framework. Éliminés entièrement, parce que l'outil qu'ils configuraient n'existe plus.
Le tableau de bord final
| Métrique | Avant (écosystème Node.js) | Après (FLIN) | Réduction |
|---|---|---|---|
| Fichiers pour 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 commencer à coder | 2+ heures | 2 minutes | 98,3 % |
| Courbe d'apprentissage | Mois | Jours | ~90 % |
| Outils à apprendre | 47 | 1 | 97,9 % |
Ce ne sont pas des projections. Ce sont les objectifs de conception vers lesquels chaque décision de l'architecture de FLIN est optimisée.
Ce que FLIN ne remplace pas
L'honnêteté intellectuelle exige de lister ce que FLIN conserve :
- CSS -- Vous pouvez utiliser n'importe quel framework CSS à côté de FLIN, ou écrire du CSS pur. Le stylisme n'est pas une préoccupation du langage.
- Git -- Le contrôle de version est orthogonal au langage de programmation.
- Votre éditeur -- VS Code, Vim, Emacs -- FLIN fonctionne avec n'importe quel éditeur de texte.
- Les plateformes de déploiement -- Vous avez toujours besoin d'un endroit où exécuter le binaire, bien que la sortie en binaire unique de FLIN rende le déploiement trivialement simple.
FLIN remplace les outils qui se dressent entre votre idée et une application fonctionnelle. Il ne remplace pas les outils qui existent en dehors de cette frontière.
L'argument philosophique
Quarante-sept technologies n'est pas un nombre que quelqu'un a choisi. C'est le résultat émergent d'un écosystème où chaque problème est résolu en ajoutant un nouvel outil, et personne n'est responsable du total. npm a 2,5 millions de paquets non pas parce que 2,5 millions de paquets sont nécessaires, mais parce que le coût de créer un nouveau paquet est inférieur au coût d'améliorer un existant.
FLIN parie sur la philosophie opposée : un outil, possédé par une seule équipe, responsable de l'intégralité de la pile. Quand le système d'entités a un bug, nous le corrigeons. Nous ne déposons pas une issue sur le GitHub de Prisma en attendant qu'un mainteneur bénévole intervienne. Quand le routeur a besoin d'une fonctionnalité, nous l'ajoutons. Nous n'évaluons pas cinq paquets middleware Express concurrents.
C'est un compromis. FLIN n'aura jamais l'étendue de l'écosystème npm. Mais il aura quelque chose que npm ne peut pas fournir : la cohérence. Chaque fonctionnalité de FLIN a été conçue pour fonctionner avec toutes les autres, testée ensemble, versionnée ensemble, documentée ensemble.
Quarante-sept outils, chacun excellent isolément, créent une expérience fragmentée. Un seul langage, conçu comme un tout, crée une expérience unifiée.
C'est le pari.
Prochain dans la série : Nommer un langage d'après un éléphant : l'origine fongbé de FLIN -- En fongbé, une langue parlée au Bénin, il y a une expression : "E flin nu" -- "Il se souvient des choses."