{"tracks":[{"id":"go","title":"Golang Backend","tagline":"From hello world to a deployed JSON API.","modules":[{"id":"G0","title":"Hello, Go","milestone":"Hello, name! prints a personalised greeting","lessons":[{"id":"go-hello","title":"Hello, Go","minutes":5,"xp":20,"steps":3}]},{"id":"G1","title":"Variables and Types","milestone":"Tip calculator with numbers and strings","lessons":[{"id":"go-variables","title":"Variables and Types","minutes":5,"xp":20,"steps":3}]},{"id":"G2","title":"Control Flow","milestone":"FizzBuzz and a number guessing game","lessons":[{"id":"go-control-flow","title":"Control Flow","minutes":5,"xp":20,"steps":3}]},{"id":"G3","title":"Functions","milestone":"Calculator library with four operations","lessons":[{"id":"go-functions","title":"Functions That Do Work","minutes":5,"xp":20,"steps":6}]},{"id":"G4","title":"Collections: Slices and Maps","milestone":"Shopping list built on a slice and a map","lessons":[{"id":"go-collections","title":"Slices and Maps","minutes":5,"xp":20,"steps":3}]},{"id":"G5","title":"Structs and Methods","milestone":"CLI task tracker v1, in memory","lessons":[{"id":"go-structs","title":"Structs and Methods","minutes":5,"xp":20,"steps":3}]},{"id":"G6","title":"Errors and Packages","milestone":"Task tracker saves to a JSON file with real error handling","lessons":[{"id":"go-errors","title":"Errors Are Values","minutes":5,"xp":20,"steps":3}]},{"id":"G7","title":"Interfaces","milestone":"Memory and file storage behind one interface","lessons":[{"id":"go-interfaces","title":"Interfaces","minutes":5,"xp":20,"steps":3}]},{"id":"G8","title":"Pointers and Generics","milestone":"Generic helper functions checkpoint","lessons":[{"id":"go-pointers-generics","title":"Pointers and Generics","minutes":5,"xp":20,"steps":3}]},{"id":"G9","title":"Concurrency: Goroutines and Channels","milestone":"Concurrent link checker fetching five URLs at once","lessons":[{"id":"go-concurrency","title":"Goroutines and Channels","minutes":5,"xp":20,"steps":3}]},{"id":"G10","title":"HTTP Servers","milestone":"Hello server plus an echo endpoint","lessons":[{"id":"go-http","title":"HTTP Servers","minutes":5,"xp":20,"steps":3}]},{"id":"G11","title":"JSON APIs","milestone":"Full CRUD JSON API with an in-memory store","lessons":[{"id":"go-json-api","title":"JSON APIs","minutes":5,"xp":20,"steps":3}]},{"id":"G12","title":"Databases with Postgres","milestone":"The G11 API persisted in Postgres","lessons":[{"id":"go-databases","title":"Databases","minutes":5,"xp":20,"steps":3}]},{"id":"G13","title":"Testing and Quality","milestone":"Table driven tests for every API handler","lessons":[{"id":"go-testing","title":"Testing and Quality","minutes":5,"xp":20,"steps":3}]},{"id":"G14","title":"Config, Deploy and Ship","milestone":"Deployed API with a public URL and health check","lessons":[{"id":"go-ship","title":"Config, Deploy and Ship","minutes":5,"xp":20,"steps":3}]}]},{"id":"flutter","title":"Flutter Frontend","tagline":"From Dart basics to a deployed Flutter Web app.","modules":[{"id":"F0","title":"Dart Warm-Up","milestone":"Dart quiz-bot logic in a mini runner","lessons":[{"id":"dart-warmup","title":"Dart Warm-Up","minutes":5,"xp":20,"steps":3}]},{"id":"F1","title":"Dart OOP and Async Basics","milestone":"Model classes for a todo app","lessons":[{"id":"dart-async","title":"Dart OOP and Async","minutes":5,"xp":20,"steps":3}]},{"id":"F2","title":"Everything Is a Widget","milestone":"Profile card screen","lessons":[{"id":"flutter-widgets","title":"Everything Is a Widget","minutes":5,"xp":20,"steps":3}]},{"id":"F3","title":"Layout","milestone":"Product list and login screen clones","lessons":[{"id":"flutter-layout","title":"Layout","minutes":5,"xp":20,"steps":3}]},{"id":"F4","title":"Styling and Assets","milestone":"Themed settings screen with dark and light modes","lessons":[{"id":"flutter-styling","title":"Styling and Themes","minutes":5,"xp":20,"steps":3}]},{"id":"F5","title":"Interaction and State I","milestone":"Counter, BMI calculator, then Todo v1","lessons":[{"id":"flutter-state","title":"State and setState","minutes":5,"xp":20,"steps":3}]},{"id":"F6","title":"Navigation","milestone":"Multi-screen app with list to detail navigation","lessons":[{"id":"flutter-navigation","title":"Navigation","minutes":5,"xp":20,"steps":3}]},{"id":"F7","title":"Forms and Validation","milestone":"Sign-up form with real validation","lessons":[{"id":"flutter-forms","title":"Forms and Validation","minutes":5,"xp":20,"steps":3}]},{"id":"F8","title":"HTTP and JSON","milestone":"Weather app against a public API","lessons":[{"id":"flutter-http","title":"HTTP and JSON","minutes":5,"xp":20,"steps":3}]},{"id":"F9","title":"State Management","milestone":"Todo v2 rebuilt with Riverpod","lessons":[{"id":"flutter-state-mgmt","title":"State Management","minutes":5,"xp":20,"steps":3}]},{"id":"F10","title":"Local Storage and Offline","milestone":"Notes app that works offline","lessons":[{"id":"flutter-storage","title":"Local Storage and Offline","minutes":5,"xp":20,"steps":3}]},{"id":"F11","title":"Testing and Polish","milestone":"Portfolio polish pass with a real widget test","lessons":[{"id":"flutter-testing","title":"Widget Tests","minutes":5,"xp":20,"steps":3}]},{"id":"F12","title":"Build and Deploy","milestone":"Deployed Flutter Web app with a public URL","lessons":[{"id":"flutter-deploy","title":"Build and Deploy","minutes":5,"xp":20,"steps":3}]}]},{"id":"capstone","title":"Full-Stack Capstone","tagline":"Your Flutter app talking to your own Go API, shipped live.","modules":[{"id":"C1","title":"Contract First","milestone":"API spec sheet passes the contract quiz","lessons":[{"id":"capstone-contract","title":"Contract First","minutes":5,"xp":20,"steps":3}]},{"id":"C2","title":"Go API v1","milestone":"CRUD API with Postgres and contract tests green","lessons":[{"id":"capstone-api","title":"Go API v1","minutes":5,"xp":20,"steps":3}]},{"id":"C3","title":"Auth","milestone":"Unauthenticated requests get a 401, tokens refresh cleanly","lessons":[{"id":"capstone-auth","title":"Auth","minutes":5,"xp":20,"steps":3}]},{"id":"C4","title":"Flutter Client","milestone":"Flutter Web app running against the live API","lessons":[{"id":"capstone-client","title":"Flutter Client","minutes":5,"xp":20,"steps":3}]},{"id":"C5","title":"Social Layer","milestone":"Weekly league and friends list with privacy safe names","lessons":[{"id":"capstone-social","title":"Social Layer","minutes":5,"xp":20,"steps":3}]},{"id":"C6","title":"Ship It","milestone":"Public URL plus the Capstone Shipped badge","lessons":[{"id":"capstone-ship","title":"Ship It","minutes":5,"xp":20,"steps":3}]}]}]}
