Studio d’applications — Web · PWA · SaaS · Outils
X 0000·Y 0000·— fps0 cellules
Des applications qui tiennent en production.
Kouma Studio conçoit, développe et opère des applications web. Produit, design et ingénierie dans une seule équipe — du premier croquis au déploiement.
01 · Savoir-faire
Ce que nous savons construire.
Six terrains, de la conception à la mise en production.
Applications web & SaaS
Comptes, rôles, paiements, tableaux de bord : des produits complets, pas des prototypes.
Offline-first & PWA
Des applications qui s’installent comme des apps natives et continuent de fonctionner sans réseau.
Calcul dans le navigateur
Traitement local de fichiers lourds — PDF, image, vidéo, audio — sans serveur ni envoi.
Outils développeur & CLI
Protocoles, interfaces en ligne de commande et automatisations pour les équipes techniques.
Design produit & design system
Parcours, interfaces et systèmes de design livrés en tokens et en composants, pas seulement en maquettes.
Sites éditoriaux & SEO
Contenu structuré, données enrichies, performances mesurées : des pages qui se trouvent et se chargent vite.
02 · Sous le capot
Cette page, mesurée en direct.
Pas de chiffres marketing : ces valeurs sont relevées à l’instant, dans votre navigateur. Cliquez, tapez, faites défiler — l’INP se met à jour.
Core Web Vitals — cette visite
Ressources & rendu
L’afficheur du haut de page tient en un seul fragment shader.
WebGL2 · un triangle plein écran · un draw call par image · zéro dépendance.
1#version 300 es2precision highp float;34uniform vec2 uResolution; // canevas, en pixels physiques5uniform vec2 uGrid; // colonnes, rangées6uniform float uCell; // côté d'une cellule, en pixels physiques7uniform vec2 uOrigin; // coin haut-gauche de la grille8uniform float uDpr;9uniform float uTime; // secondes10uniform float uMix; // transition scène A -> B, de 0 à 111uniform float uIntro; // apparition, de 0 à 112uniform float uMotion; // 0 sous prefers-reduced-motion13uniform vec2 uPointer; // pointeur (très loin s'il est absent)14uniform vec3 uRipple; // clic : x, y, instant15uniform vec3 uInk; // couleur des points16uniform sampler2D uSceneA; // une texel par cellule : allumée ou non17uniform sampler2D uSceneB;1819out vec4 fragColor;2021// Hash stable par cellule : chacune bascule à son propre instant.22float hash(vec2 p) {23 p = fract(p * vec2(123.34, 456.21));24 p += dot(p, p + 45.32);25 return fract(p.x * p.y);26}2728// Carré arrondi en distance signée — rx = 0,32 x côté, comme le K pixel.29float roundedSquare(vec2 p, float side) {30 float r = 0.32 * side;31 vec2 q = abs(p) - 0.5 * side + r;32 return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - r;33}3435void main() {36 vec2 px = vec2(gl_FragCoord.x, uResolution.y - gl_FragCoord.y) - uOrigin;37 vec2 cell = floor(px / uCell);38 if (cell.x < 0.0 || cell.y < 0.0 || cell.x >= uGrid.x || cell.y >= uGrid.y) discard;3940 vec2 local = px / uCell - cell - 0.5;41 vec2 uv = (cell + 0.5) / uGrid;42 vec2 center = (cell + 0.5) * uCell + uOrigin;4344 // Scène : A et B se relaient, cellule par cellule.45 float flip = smoothstep(hash(cell) * 0.7, hash(cell) * 0.7 + 0.3, uMix);46 float lit = mix(texture(uSceneA, uv).r, texture(uSceneB, uv).r, flip);4748 // Onde diagonale du loader Kouma, du coin haut-gauche au coin bas-droit.49 float diag = (cell.x + cell.y) / (uGrid.x + uGrid.y);50 float wave = 0.5 + 0.5 * sin(6.2832 * (diag * 4.0 - uTime * 0.4));5152 // Apparition en balayage diagonal.53 float intro = smoothstep(diag, diag + 0.2, uIntro * 1.2);5455 // Loupe sous le pointeur, rayon d'environ 110 px CSS.56 float d = length(center - uPointer) / (110.0 * uDpr);57 float lens = exp(-d * d * 2.0) * uMotion;5859 // Onde de choc au clic : un anneau qui s'étend et s'éteint.60 float age = uTime - uRipple.z;61 float rd = length(center - uRipple.xy) / uDpr;62 float ring = age < 0.0 ? 0.063 : exp(-pow((rd - age * 700.0) / 40.0, 2.0)) * exp(-age * 1.8) * uMotion;6465 float side = mix(0.28, 0.72, lit)66 + 0.06 * wave * lit * uMotion67 + (0.34 * lens + 0.5 * ring) * (1.0 - 0.7 * lit);68 float alpha = mix(0.08 + 0.06 * wave * uMotion, 1.0, lit)69 + (0.45 * lens + 0.6 * ring) * (1.0 - lit);7071 float dist = roundedSquare(local, min(side, 0.9) * intro) * uCell;72 float a = clamp(alpha, 0.0, 1.0) * (1.0 - smoothstep(-0.5, 0.5, dist)) * intro;73 fragColor = vec4(uInk * a, a);74}03 · Contact
Un projet d’application ? Parlons-en.
Décrivez-le en quelques lignes — contexte, objectif, échéance. Nous revenons vers vous pour en discuter.