How freecodecamp/mobile works
1. This repository is a two-part mobile system: a Flutter client app in mobile-app/ and a small Node/TypeScript backend in mobile-api/. The app is the primary product; the backend mainly supports podcast data ingestion and API serving.
2. The Flutter app is the main presentation and orchestration layer. Its structure is organized by feature area under lib/ui/views/ with a shared app bootstrap in lib/main.dart and lib/app/. Navigation, dependency wiring, and logging are centralized there rather than spread through features.
3. The app’s major user-facing subsystems are:
- Learn/curriculum delivery
- News/tutorial reading and bookmarking
- Podcasts and audio playback
- Profile/settings/auth-related flows
- Code radio and miscellaneous utility screens
Each subsystem has its own view and viewmodel pairings, suggesting an MVVM-style Flutter architecture.
4. The Learn subsystem is the most complex and is built for offline curriculum use. It combines packaged curriculum assets, local databases, file-based content, and a dedicated “test runner” asset bundle for executing curriculum challenge tests inside the app. The learn area has many specialized templates for different challenge types, block content, chapters, daily challenges, and scene assets.
5. Local data is a major boundary in the app. The repository includes bundled SQLite databases under assets/database/, SQL migration/reset scripts under assets/sql/, JSON learning content, and a generic file store service. This indicates the app can operate with local/offline data and migrates legacy content rather than relying entirely on live backend calls.
6. News is a separate content subsystem backed by an API service and bookmark persistence. The app includes views for feeds, search, tutorials, image viewing, author pages, and bookmark management. There is explicit legacy SQLite bookmark migration logic, so the app has evolved from local persistence to a newer storage path while preserving old user data.
7. Podcasts are handled as another distinct feature boundary. On the client side there are podcast list, episode list, episode detail, download, audio, and notification services. The presence of podcast database assets and legacy migration code shows a similar evolution from older local storage to current services. Podcast playback and download management are part of the app, not the backend.
8. The mobile-api/ backend is a lightweight data service, not a general-purpose application server. It contains database connectivity, Podcast and Episode models, route definitions, and a scheduled job to update podcasts from feed URLs. The podcast-feed-urls.json file and the update job make clear that the backend periodically ingests external podcast feeds and serves normalized data to the mobile app.
9. External services and platform integrations are important in the app architecture. Firebase is used for analytics, remote config, and platform-specific app configuration. Android and iOS native projects are included, along with push/notification-related services, quick actions, and audio integrations. These are app-side concerns rather than centralized server-side infrastructure.
10. The app’s state and service layer is separated from UI. Services under lib/service/ encapsulate authentication, Dio-based networking, Firebase access, locale management, navigation shortcuts, learn content loading, news APIs/bookmarks, podcast downloads/notifications, and JSON file storage. UI components generally depend on these services through injected viewmodels.
11. Testing is layered by scope. The backend has Jest tests for podcast behavior, while the Flutter app has unit tests, service tests, widget tests, and integration tests under test/ and integration_test/. There is also a dedicated integration runner for the curriculum/test-runner experience, reflecting the importance of validating in-app coding challenges.
12. CI/CD is split by platform and concern. GitHub Actions cover API build/test/deploy, Flutter unit tests, Flutter CI/deploy, curriculum e2e tests, and Crowdin translation sync. Mobile release tooling is also present via Codemagic and Fastlane, which indicates the app is built and shipped as native Android/iOS binaries.
13. The main architectural data flows are:
- Curriculum and learn content flow from bundled assets/local DBs into the Learn UI and test runner.
- News content flows from remote APIs into the News UI, with bookmarks stored locally and migrated if needed.
- Podcast metadata flows from external feeds into the backend, then into the app for listing, playback, and downloads.
- Firebase services cross-cut the app for analytics, config, and platform integration.
14. Overall, this is an offline-friendly, content-heavy mobile learning platform with a thin supporting backend. The strongest architectural boundary is between the Flutter client, which owns most user experience and local persistence, and the Node backend, which mainly curates and serves podcast data.
Main entry points: app.dart App shell · learn Learn hub · service Shared services · index.ts API entry
Components 20
Flutter app
Primary offline-friendly mobile client and its local service layer.
- App bootstrap · Main app startup, dependency wiring, navigation, and logging.
mobile-app/lib/main.dart - App shell · Central app composition with router, service locator, and logger.
mobile-app/lib/app/app.dart - Learn hub · Curriculum landing, chapters, daily challenges, and test runner entry.
mobile-app/lib/ui/views/learn - Challenge views · Specialized block and challenge templates for interactive curriculum content.
mobile-app/lib/ui/views/learn/challenge/templates - Learn services · Loads packaged curriculum assets, local content, scene assets, and notifications.
mobile-app/lib/service/learn - Curriculum assets · Local databases, SQL scripts, JSON content, and the test runner bundle.
mobile-app/assets - Test runner · Embedded integration runner used to execute in-app coding challenges.
mobile-app/lib/ui/views/learn/test_runner.dart - News hub · Feeds, search, tutorials, authors, image viewing, and bookmarks.
mobile-app/lib/ui/views/news - News services · Remote news API access plus bookmark persistence and migration.
mobile-app/lib/service/news - Podcasts · Podcast listing, episode browsing, detail, download, and playback screens.
mobile-app/lib/ui/views/podcast - Podcast services · Podcast retrieval, legacy migration, downloads, and notifications.
mobile-app/lib/service/podcast - Profile & settings · Profile, login, settings, and account deletion flows.
mobile-app/lib/ui/views/profile - Shared services · Authentication, Dio networking, locale, navigation shortcuts, storage, and developer helpers.
mobile-app/lib/service - Firebase · Analytics, remote config, and app configuration integration.
mobile-app/lib/service/firebase - Native platforms · Android and iOS host apps, manifests, signing, and push/app setup.
mobile-app/android
Node API
Lightweight podcast ingestion and serving backend.
- API entry · Backend bootstrap, routing, and database connection startup.
mobile-api/src/index.ts - API routes · Server route definitions exposed to the mobile app.
mobile-api/src/routes.ts - Podcast models · Podcast and episode database models used by the backend.
mobile-api/src/models - Feed updater · Periodic job that ingests external podcast feeds and normalizes data.
mobile-api/src/jobs/update-podcasts.ts
Delivery
Build, test, and release automation across mobile and API.
- CI/CD · GitHub Actions, Codemagic, and Fastlane build/test/deploy pipelines.
.github/workflows
Connections 22
- App bootstrap → App shell: boots · Main entry initializes the composed app shell and routing.
- App shell → Learn hub: navigates · Router sends users into the learn experience.
- App shell → News hub: navigates · Router exposes the news experience.
- App shell → Podcasts: navigates · Router exposes the podcast experience.
- App shell → Profile & settings: navigates · Router exposes profile, login, and settings flows.
- Learn hub → Challenge views: renders · Learn screens compose challenge and block templates.
- Learn hub → Learn services: loads · Learn UI depends on offline curriculum and scene services.
- Learn services → Curriculum assets: reads · Curriculum services consume bundled databases, JSON, SQL, and test assets.
- Learn hub → Test runner: executes · Curriculum test runner validates in-app coding challenges.
- News hub → News services: fetches · News screens use API and bookmark services.
- News services → Shared services: uses · News services reuse networking and storage primitives.
- Podcasts → Podcast services: plays · Podcast screens rely on download and audio services.
- Podcast services → Shared services: uses · Podcast services reuse storage and networking primitives.
- Profile & settings → Shared services: depends on · Auth, locale, navigation, and storage support profile/settings flows.
- Shared services → Firebase: integrates · Shared app services connect to analytics and remote config.
- Native platforms → Firebase: configures · Android and iOS hosts provide native Firebase setup.
- API entry → API routes: serves · Server entry mounts HTTP routes.
- API entry → Podcast models: connects · Backend initializes persistence and model access.
- Feed updater → Podcast models: updates · Scheduled ingestion populates podcast and episode data.
- Feed updater → API routes: feeds · Ingested podcast data is made available to the API.
- CI/CD → App bootstrap: builds/tests · Mobile pipelines cover Flutter tests and releases.
- CI/CD → API entry: builds/tests · API pipelines cover backend build, test, and deploy.