Stack Specification
Section 05

Tech stack

The agreed stack and the structure that organises it. Defaults are committed where possible; remaining choices are listed in Section 20 — Open Decisions.

5.1 — Mobile app

ConcernChoiceNotes
FrameworkFlutterStable channel. Lock the SDK version in pubspec.yaml.
LanguageDartSound null safety on.
PlatformsiOS, AndroidTablet layouts in scope; not a launch priority.
ArchitectureFeature‑first clean architectureOne folder per feature; shared concerns in core/.
RenderingCustomPainterSingle painter per canvas surface — see Section 11.
StateRiverpod 2.xPin major version. Avoid mixing with Provider.
RoutingGoRouterDeclarative routes; deep linking enabled.
HTTPDioInterceptors for auth, retries, logging.
Local DBDriftChosen over Isar — see Section 20.
Secure storageflutter_secure_storageFor auth tokens and receipt cache.
IAPin_app_purchaseStoreKit 2 on iOS, Billing 6+ on Android.
Files / cachepath_providerBundle cache under app‑support directory.
Path parsingpath_drawingRequired to parse SVG path strings — see Section 06.
Compressionbrotli (Dart)Used to decompress region payloads.
Remote configGrowthBook or equivalentFor paywall toggles and staged rollouts.

Suggested module structure

lib/
  app/
  core/
    network/
    storage/
    analytics/
    config/
  features/
    library/
    artwork_detail/
    download/
    canvas/
    palette/
    progress/
    auth/
    paywall/
    admin_preview/
    settings/

5.2 — Backend

ConcernChoice
PlatformInsForge
DatabasePostgreSQL (managed via InsForge)
API layerPostgREST‑style auto‑generated APIs + edge functions for write paths
AuthenticationInsForge Auth (email + Apple + Google)
StorageInsForge Storage (S3‑compatible) fronted by a CDN
AuthorisationRow‑level security policies — see Section 07

InsForge is responsible for user authentication, the catalogue, asset hosting, entitlement records, purchase validation, progress sync, the admin publishing workflow, and the signed‑URL gateway for premium asset access.

5.3 — Asset storage layout

Artwork assets are stored remotely as structured bundles, one folder per artwork:

artworks/
  <slug>/
    manifest.json
    regions.bin.br          # binary, brotli-compressed
    preview.webp
    thumbnail.webp
    line_art.svg            # optional, reference only
    version.txt

The app downloads bundles on demand and caches them under the app‑support directory. Locale variants of manifest.json are not stored alongside the bundle — translatable strings live in PostgreSQL (see Section 07).