presque.cool
Back to projects
adulthood simulator icon

adulthood simulator

Sep 2025 Game
Visit project

A satirical infinite to-do list simulating adult life. One task done, ten more to go.


Le pitch

Adulthood Simulator est une to-do list satirique qui simule l’expérience de la vie adulte. On coche une tâche, une nouvelle apparaît. Toujours. Le compteur monte, les tâches ne finissent jamais — comme dans la vraie vie.

310 tâches réparties en 7 catégories (domestique, administratif, santé, social, finances, carrière, existentiel), écrites à la main en français et en anglais, avec un système de distribution intelligent qui empêche les répétitions et crée des enchaînements narratifs.

Essayer : presque.cool/adulthood-simulator/

Durée v2 : ~1 jour
Période Sep 2025 → Fév 2026
Stack
Preact TypeScript Tailwind CSS PWA
Statut ✓ En production

Pourquoi ce projet

Coder une app de prise de notes ou une to-do list, c’est un peu le rite de passage chez les développeurs. Tout le monde le fait, alors qu’il en existe des milliers. C’est un exercice technique inoffensif, un “hello world” à peine déguisé.

J’ai voulu me moquer gentiment de ce cliché — en construisant la to-do list la plus inutile possible.

L’idée part d’un constat universel : la vie adulte est une to-do list infinie. On fait les courses, on range, on paye les factures, on prend rendez-vous, on rappelle quelqu’un, on oublie quelque chose — et ça recommence. Il n’y a pas de fin. Il n’y a jamais de fin. Adulthood Simulator transforme cette absurdité en expérience interactive. Pas un outil de productivité — l’exact inverse. Un simulateur qui capture le sentiment que peu importe combien de tâches on accomplit, il y en aura toujours d’autres.

Les tâches vont du quotidien banal (“Trouver le couvercle qui correspond exactement à ce tupperware précis”) à l’existentiel (“Se demander si les gens au travail savent qu’on improvise depuis le premier jour”).


Deux versions, deux approches

Prototype Alpine.js (septembre 2025) : Première version fonctionnelle avec Alpine.js. Les bases étaient là — tâches, catégories, score — mais le code avait ses limites. Puis le projet a été mis en pause pendant 5 mois.

Version Preact (février 2026) : Réécriture complète. Pas une migration — un nouveau projet. Le choix de Preact plutôt que React était délibéré : pour un projet satirique avec une mécanique simple, 3 KB de runtime suffisent. Pas de Zustand, pas de Redux — un store custom minimaliste qui fait exactement ce qu’il faut. L’objectif technique : zéro dépendance inutile.


Le cœur du projet : le moteur de tâches

La partie la plus intéressante n’est pas l’UI — c’est le système de distribution des tâches. La classe TaskPool gère trois mécaniques qui transforment une simple base de données en quelque chose de plus vivant :

Cooldown anti-répétition : Chaque tâche peut définir un cooldown — un nombre de tirages pendant lesquels elle ne peut pas réapparaître. Cela évite que “Acheter du lait” apparaisse trois fois de suite, même dans un pool mélangé aléatoirement.

Triggers (chaînes narratives) : Certaines tâches en déclenchent d’autres. Compléter “Acheter du lait avant que celui au frigo ne devienne du fromage” force l’apparition immédiate de “Oublier le lait dans le coffre de la voiture pendant 3 jours”. Ces enchaînements créent des micro-récits — l’humour vient de la reconnaissance de ces situations.

Les tâches déclenchées n’apparaissent jamais dans le pool normal. Elles n’existent que comme conséquences.

Tâches rares (~1.5%) : À chaque tirage, il y a 1.5% de chance de piocher une tâche rare plutôt que la suivante du pool. Ce sont les tâches les plus absurdes ou les plus spécifiques — des petites surprises qui cassent la routine.

Le cycle : pool mélangé → tirage avec vérification de cooldown → quand le pool est épuisé, re-mélange → boucle infinie. Si l’utilisateur a tout complété, le pool entier redevient disponible. Les tâches ne s’arrêtent jamais.


Architecture minimaliste

L’architecture reflète la philosophie du projet : faire le maximum avec le minimum.

Store custom : Un mécanisme de store réactif en ~30 lignes — getState, setState, subscribe. Pas de middleware, pas de devtools, pas de boilerplate. Deux stores : un pour le score (IDs des tâches complétées, persisté en localStorage, plafonné à 2000 entrées), un pour les settings (thème, langue).

Preact au lieu de React : Même API, ~3 KB au lieu de ~40 KB. Pour une app de cette taille, la différence est significative. Le Virtual DOM de Preact gère le même pattern de memoization et de lazy loading.

Pas de routeur : Une seule page. Le seul état qui change est la liste de tâches et le score. Pas besoin de plus.

DOM plafonné à 20 items : Les tâches complétées les plus anciennes sont retirées du DOM quand la liste dépasse 20 éléments, avec un ajustement du scroll pour éviter les sauts visuels.


L’esthétique Apple Notes

Le design s’inspire de l’application Apple Notes — des tons crème et or en mode clair, un fond sombre chaleureux en mode dark. La palette utilise des couleurs OKLCh pour une uniformité perceptuelle. L’idée : une to-do list qui ressemble à une to-do list, pas à une app tech.

Les polices sont volontairement système (Segoe UI, Roboto) avec du monospace (Cascadia Code, Source Code Pro) pour certains éléments. Sobre, lisible, familier.


310 tâches, deux langues

Toutes les tâches ont été écrites manuellement, en français et en anglais. 310 entrées réparties en 7 catégories :

  • Domestique — IKEA, courses, ménage, lessive, Tupperware
  • Administratif — Impôts, factures, mots de passe, paperasse
  • Santé — Rendez-vous reportés, médicaments, hydratation
  • Social — Messages non lus, anniversaires oubliés, small talk
  • Finances — Abonnements inutiles, budget, épargne
  • Carrière — Réunions inutiles, emails, imposter syndrome
  • Existentiel — Questionnements sur le temps qui passe, sens de la vie

Le ton est constant : satirique, observationnel, jamais méchant. L’humour vient de la reconnaissance — “ah oui, je fais ça aussi”.


Stack technique

  • Preact + TypeScript — 3 KB de runtime, même API que React
  • Vite comme bundler (avec SWC)
  • Tailwind CSS — Couleurs OKLCh, dark mode natif
  • Store custom — State management minimaliste sans dépendance
  • PWA — installable, offline, Workbox
  • i18n maison — français/anglais, clés type-safe via TypeScript
  • Accessibilité — WCAG 2.1, focus trap, navigation clavier, ARIA
  • Compression — Brotli + Gzip sur les assets
  • CSP — Content-Security-Policy avec hashes auto-générés

Évolutions

DateVersionDescription
Sep 20251.0Prototype Alpine.js — Tâches, catégories, score de base
Fév 20262.0Réécriture Preact — TaskPool engine, store custom, PWA, accessibilité, 310 tâches

Bilan

Ce que j’ai appris :

  • Concevoir un moteur de distribution de contenu avec cooldown, triggers et raretés — un système simple en apparence, mais qui demande de la réflexion pour garder l’expérience fraîche
  • Qu’un store custom en 30 lignes peut remplacer Zustand/Redux quand les besoins sont simples
  • L’importance d’écrire du contenu soi-même — les 310 tâches donnent une voix au projet que du contenu généré n’aurait pas

Ce que je referais pareil :

  • Preact plutôt que React pour un projet de cette envergure — le gain en taille de bundle est réel
  • Zéro dépendance de state management — le store custom est plus simple à maintenir qu’un outil externe

Ce que je changerais :

  • Ajouter des catégories ou des tâches thématiques ou saisonnières (ex: jeunes parents) — le pool de 310 finit par se répéter après un usage prolongé
  • Explorer des mécaniques de “progression” — des achievements ironiques, des statistiques absurdes…

The pitch

Adulthood Simulator is a satirical to-do list that simulates the adult life experience. You check off a task, a new one appears. Always. The counter goes up, the tasks never end — just like real life.

310 tasks across 7 categories (domestic, admin, health, social, finance, career, existential), hand-written in French and English, with a smart distribution system that prevents repetition and creates narrative chains.

Try it: presque.cool/adulthood-simulator/

Duration v2: ~1 day
Period Sep 2025 → Feb 2026
Stack
Preact TypeScript Tailwind CSS PWA
Status ✓ In production

Why this project

Building a notes app or a to-do list is something of a rite of passage for developers. Everyone does it, even though thousands already exist. It’s a harmless technical exercise, a barely disguised “hello world.”

I wanted to gently mock that cliché — by building the most useless to-do list possible.

The idea starts from a universal observation: adult life is an infinite to-do list. You buy groceries, clean up, pay bills, schedule appointments, call someone back, forget something — and it starts over. There’s no end. There’s never an end. Adulthood Simulator turns that absurdity into an interactive experience. Not a productivity tool — the exact opposite. A simulator that captures the feeling that no matter how many tasks you complete, there will always be more.

Tasks range from the mundanely domestic (“Find the lid that matches this exact Tupperware container”) to the existential (“Wonder if people at work know you’ve been improvising since day one”).


Two versions, two approaches

Alpine.js prototype (September 2025): First working version with Alpine.js. The basics were in place — tasks, categories, score — but the code had its limits. Then the project was shelved for 5 months.

Preact version (February 2026): Complete rewrite. Not a migration — a new project. Choosing Preact over React was deliberate: for a satirical project with simple mechanics, 3 KB of runtime is enough. No Zustand, no Redux — a minimal custom store that does exactly what’s needed. The technical goal: zero unnecessary dependencies.


The heart of the project: the task engine

The most interesting part isn’t the UI — it’s the task distribution system. The TaskPool class manages three mechanics that turn a simple database into something that feels alive:

Anti-repetition cooldown: Each task can define a cooldown — a number of draws during which it can’t reappear. This prevents “Buy milk” from showing up three times in a row, even in a randomly shuffled pool.

Triggers (narrative chains): Some tasks trigger others. Completing “Buy milk before the one in the fridge turns into cheese” immediately forces “Forget the milk in the car trunk for 3 days” to appear next. These chains create micro-narratives — the humor comes from recognizing these situations.

Triggered tasks never appear in the regular pool. They only exist as consequences.

Rare tasks (~1.5%): On each draw, there’s a 1.5% chance of pulling a rare task instead of the next one from the pool. These are the most absurd or specific tasks — little surprises that break the routine.

The cycle: shuffled pool → draw with cooldown check → when pool is exhausted, reshuffle → infinite loop. If the user has completed everything, the entire pool becomes available again. The tasks never stop.


Minimalist architecture

The architecture reflects the project’s philosophy: do the most with the least.

Custom store: A reactive store mechanism in ~30 lines — getState, setState, subscribe. No middleware, no devtools, no boilerplate. Two stores: one for score (completed task IDs, persisted in localStorage, capped at 2,000 entries), one for settings (theme, language).

Preact instead of React: Same API, ~3 KB instead of ~40 KB. For an app this size, the difference matters. Preact’s Virtual DOM handles the same memoization and lazy loading patterns.

No router: A single page. The only state that changes is the task list and the score. Nothing more is needed.

DOM capped at 20 items: The oldest completed tasks are removed from the DOM when the list exceeds 20 elements, with scroll offset adjustment to prevent visual jumps.


The Apple Notes aesthetic

The design is inspired by the Apple Notes app — cream and gold tones in light mode, a warm dark background in dark mode. The palette uses OKLCh colors for perceptual uniformity. The idea: a to-do list that looks like a to-do list, not a tech app.

Fonts are deliberately system (Segoe UI, Roboto) with monospace (Cascadia Code, Source Code Pro) for certain elements. Clean, readable, familiar.


310 tasks, two languages

All tasks were written manually, in French and English. 310 entries across 7 categories:

  • Domestic — IKEA, groceries, cleaning, laundry, Tupperware
  • Admin — Taxes, bills, passwords, paperwork
  • Health — Postponed appointments, medication, hydration
  • Social — Unread messages, forgotten birthdays, small talk
  • Finance — Useless subscriptions, budget, savings
  • Career — Pointless meetings, emails, impostor syndrome
  • Existential — Questioning the passage of time, meaning of life

The tone is consistent: satirical, observational, never mean. The humor comes from recognition — “oh yeah, I do that too.”


Tech stack

  • Preact + TypeScript — 3 KB runtime, same API as React
  • Vite as bundler (with SWC)
  • Tailwind CSS — OKLCh colors, native dark mode
  • Custom store — Minimal state management with no dependencies
  • PWA — installable, offline, Workbox
  • i18n custom — French/English, type-safe keys via TypeScript
  • Accessibility — WCAG 2.1, focus trap, keyboard nav, ARIA
  • Compression — Brotli + Gzip on assets
  • CSP — Content-Security-Policy with auto-generated hashes

Timeline

DateVersionDescription
Sep 20251.0Alpine.js prototype — Tasks, categories, basic scoring
Feb 20262.0Preact rewrite — TaskPool engine, custom store, PWA, accessibility, 310 tasks

Takeaways

What I learned:

  • Designing a content distribution engine with cooldowns, triggers, and rarities — simple in concept, but requires thought to keep the experience fresh
  • That a custom store in 30 lines can replace Zustand/Redux when needs are simple
  • The importance of writing content yourself — the 310 tasks give the project a voice that generated content wouldn’t have

What I’d do the same:

  • Preact over React for a project this size — the bundle size savings are real
  • Zero state management dependencies — the custom store is easier to maintain than an external tool

What I’d change:

  • Add thematic or seasonal task categories (e.g., new parents) — the pool of 310 eventually repeats with prolonged use
  • Explore “progression” mechanics — ironic achievements, absurd statistics…

Settings

Language
Theme
Privacy Policy