Stack Specification
Section 11

Engineering considerations

The Flutter colouring engine is the highest technical risk in the project. Everything in this section exists to manage that risk.

11.1 — Rendering approach

Use a single CustomPainter per canvas surface. Do not create one widget per region. The painter draws layers in order:

1. Unfilled region outlines (cached as a single Picture)
2. Filled regions  (incrementally added; cached as a Picture per ~256 regions)
3. Region number labels (clipped to the current viewport)
4. Selection highlights and feedback

Filled‑region caches are rebuilt only when a layer crosses 256 new fills. The outline picture is built once on artwork open.

11.2 — Hit testing

screen tap
  → InteractiveViewer matrix-inverse → canvas coords
  → spatial-index lookup (grid of N × N cells over the canvas)
  → for each candidate region:
       cheap bounds reject
       precise Path.contains() test
  → on hit: check selected colour
  → if correct: set bit, schedule paint, persist
  → if wrong:  gentle haptic + 80ms pulse on the correct colour swatch

A 32 × 32 grid spatial index is sufficient for MVP and trivial to build at artwork open. Upgrade to an R‑tree only if profiling demands it.

11.3 — Local‑first behaviour

  • Artwork bundles persist under the app‑support directory and survive restarts.
  • Progress writes are local‑first; the sync queue retries with exponential backoff.
  • The app is fully playable offline for any artwork already downloaded.
  • No interaction is blocked on a network round‑trip during colouring.

11.4 — Backend security

  • Catalogue reads enforced by RLS (is_published = true).
  • Premium downloads gated through a server‑side function — never by the client.
  • Signed URLs expire in 15 minutes; the function re‑issues on demand for resumed downloads.
  • Receipt validation is exclusively server‑side via Apple ASSN v2 and Google Play API.
  • Admin endpoints check a role claim and run with the service role.
  • Rate limits on download‑URL and sync‑progress functions.

11.5 — Children’s product considerations

  • Age‑appropriate or no behavioural ads when profiles.child_mode = true.
  • Parental gate (long‑press + arithmetic challenge) on purchases and external links.
  • Privacy compliance (COPPA, UK Children’s Code, App Store / Google Play family policies).
  • Clear in‑app reporting flow on every artwork detail screen.
  • Safe account model — display name optional, no public profiles.

11.6 — Performance budget

MetricTarget (mid‑range Android, ~2024 baseline)
Cold start to library≤ 1.8 s
Artwork open (cached)≤ 600 ms
Steady‑state frame time≤ 16 ms during pan / zoom
Tap → fill latency≤ 50 ms
Memory (large artwork loaded)≤ 220 MB resident