Chronos is a scroll-driven, single-page experience that animates the entire
history of the cosmos β from the Big Bang to the present day and beyond β across
nine hand-painted eras, ending in a developer portfolio reveal. Every scene
is drawn with Flutter CustomPainters and animated from a single ticker, so the
whole journey is pure Dart with no image-based animation.
It's a showcase of what Flutter can do for rich, interactive, fully responsive storytelling on the web (and mobile, and desktop).
π Experience it live
π» Best viewed on a desktop browser β the cursor-driven parallax and hover-to-reveal moments need a mouse, and the wide scenes have room to breathe. It stays fully responsive on tablet and phone, just without the pointer effects.
Everything in the timeline is drawn and moved in pure Dart. No GIFs, videos,
Lottie files, or pre-rendered sprites, just Canvas calls running every frame.
- More than 30
CustomPainters render every star, galaxy, planet, creature, and particle by hand. - One
Tickerdrives all of it. It feeds a singletimevalue through aProvider, and only the on-screen era listens, so dozens of scenes hold 60fps without dozens ofAnimationControllers. - Scroll is the timeline. Page position maps to progress through each era, so you scrub 13.8 billion years by scrolling.
- Procedural, not keyframed. Flames flicker, galaxies wind, comets follow real conic-section orbits, and dinosaurs walk, all from math.
It is built to show how far Flutter's rendering and animation can go on the web.
- Nine custom-painted eras β Big Bang β Cosmic Dark Ages β First Stars β Galaxies β Solar System β Life Begins β Age of Giants β Rise of Humanity β The Future, then a portfolio reveal.
- Scroll is the timeline β your scroll position drives every animation and era transition; a tap-to-jump progress bar lets you skip around.
- Hand-built scenes β supernovae, colliding galaxies, orbiting planets and rogue comets, single-celled life, fighting dinosaurs, an ice-age mammoth hunt, a forest sabertooth ambush, a campfire that grows into a city skyline.
- Interactive moments β drag to spin galaxies, tap to ignite stars, tap (or hover) to reveal the dinosaur titans.
- Fully responsive β purpose-built mobile, tablet, and desktop behavior with touch-first interactions and width-aware layouts.
- Performant by design β one
Tickerfeeds aProvider; only the on-screen era subscribes to per-frame updates (visibility-gated viaEraScope), and each era is wrapped in aRepaintBoundary.
| Area | Choice |
|---|---|
| Framework | Flutter (Web, Android, iOS, desktop) |
| Language | Dart |
| State | provider β no setState, all state flows through ChangeNotifiers |
| Rendering | CustomPainter / Canvas for every scene |
| Fonts | google_fonts |
| Links | url_launcher |
| CI / Deploy | GitHub Actions β GitHub Pages |
The whole experience is one long SingleChildScrollView. Each era is a
SizedBox that is twice the viewport tall, so scrolling reveals a tall scene a
viewport at a time.
Ticker (JourneyPage)
ββ AnimationProvider.time // global clock, ticks every frame
ScrollController
ββ ScrollProvider // overall + per-era progress, current era
MouseRegion
ββ CursorProvider // pointer-driven parallax (desktop)
Each era:
EraScope // subscribes to time/cursor ONLY when its era is on-screen
ββ EraWrapper // headline + description + background gradient + parallax
ββ CustomPaint layers (StarField, Nebula, scene painters, InfoLabelsβ¦)
Key ideas worth reading the code for:
EraScope(lib/components/journey/era_scope.dart) β visibility gating. Only the active era (and its neighbors) rebuilds per frame, so 9 animated scenes don't all run at once.EraWrapper(lib/components/journey/era_wrapper.dart) β shared title / description / entrance animation, with responsive scale factors.InfoLabelPainter(lib/components/painters/info_label_painter.dart) β shared floating epoch annotations that flip inward on narrow screens.
Every CustomPainter lives in its own file under a painters/ folder; widget
files never contain a painter.
lib/
βββ main.dart # App entry β providers + JourneyPage
βββ core/
β βββ hooks/hooks.dart # Barrel export used across the app
β βββ provider/ # ScrollProvider, AnimationProvider, CursorProvider
β βββ utils/ # AppSettings, AppColors, AppText, Responsive
βββ pages/
β βββ journey/
β β βββ journey_page.dart # The scrolling journey scaffold
β β βββ painters/ # CursorTrailPainter
β βββ eras/ # One widget per era (the nine scenes)
β β βββ painters/ # One painter per file, per era scene (22 of them)
β βββ portfolio/ # Final developer reveal screen
βββ layouts/ # Per-breakpoint layouts (mobile/tablet/desktop)
βββ components/
βββ journey/ # ProgressBar, EraWrapper, EraScope
βββ interactive/
β βββ *.dart # StarIgniter, GalaxyRotator, CreatureRevealer
β βββ painters/ # Their painters (galaxy spiral, titan dust, β¦)
βββ painters/ # Shared, reusable painters (StarField, Nebula, β¦)
- Flutter SDK
3.27+(Dart3.12+) - A browser (Chrome recommended) for the web target
# 1. Clone
git clone https://github.com/OttomanDeveloper/andro_meda.git
cd andro_meda
# 2. Install dependencies
flutter pub get
# 3. Run on the web
flutter run -d chromeOn Flutter web, if CanvasKit fails to load from the CDN, run with
flutter run -d chrome --no-web-resources-cdnto serve CanvasKit locally.
flutter run # any connected device / emulator
flutter build web --release
flutter build apk --releaseflutter analyze # static analysis (must be clean)
dart format . # formatting (CI checks this)
flutter test # smoke testsPlease read CONTRIBUTING.md before opening a PR β it
covers the project conventions (notably: state goes through Provider, never
setState) and how scenes are built.
Contributions are welcome! New eras, richer scenes, performance work, and accessibility improvements are all great places to start. See CONTRIBUTING.md to get started. Found a security issue? Please follow the Security Policy.
Released under the Creative Commons Attribution 4.0 International License (CC BY 4.0). You're free to use, share, and adapt this work β even commercially β as long as you give appropriate credit to Muhammad Usman, link to the license, and indicate any changes.
Muhammad Usman β Senior Flutter Developer
- GitHub: @OttomanDeveloper
- LinkedIn: ottomancoder
- YouTube: @OttomanCoder
If this project helped or inspired you, please consider giving it a β.