Chuyển đến nội dung chính

Bài đăng

Subscription groups, upgrades, and proration explained

Confusing tiers cause refunds and support load. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence How to structure tiers so users do not double-pay. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Design one group per entitlement family. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent and calls the boundary. The bound...

In-app purchases with StoreKit 2 and Play Billing in Flutter

Monetization bugs are revenue bugs. Use maintained IAP packages and real sandbox tests. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Subscription groups, offers, and restore flows that pass review. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Restore purchases must work offline-ish and be obvious in settings. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. ...

Impeller on desktop: SDF text and Metal/Vulkan defaults

Desktop Impeller defaults land with Signed Distance Function text and Wide Gamut on macOS. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Flutter 3.47 makes Impeller the default desktop renderer — what changes for text and jank. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Shader compilation jank dies; SDF glyphs stay sharp on lower-density desktop displays. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an ...

Image caching and decode budgets in Flutter lists

Image decode is one of the most common raster-thread hogs in feed apps. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence precache, ResizeImage, and avoiding 12MP avatars in chat lists. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Always decode near display size, not camera size. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates...

Flutter localization with ARB and gen_l10n that translators like

Ship the l10n pipeline early — retrofitting 200 strings is painful. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Untranslated messages, plurals, and gender-aware copy. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model ARB + gen_l10n is the supported path; keep keys stable for translators. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case ...

HTTP in Flutter: timeouts, retries, and cancellation

Mobile networks lie. Timeouts and cancel tokens are mandatory. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence dio interceptors that do not hang the UI forever. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model One retry with backoff; do not hammer APIs from flaky clients. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the inten...

Home screen widgets with Flutter shells

Widgets are a retention surface. Data must sync from the main app. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence WidgetKit + Glance patterns and shared storage with Flutter. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Write snapshot JSON to the app group after key app events. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validate...

Hiring mobile engineers in a Flutter+native world

Hire for systems thinking and platform empathy, not syntax trivia. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Signals that predict ramp time and code quality. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Use a small take-home that includes accessibility and offline. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the in...

Hero animations without the glitches

Heroes are the cheapest way to make navigation feel spatial. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence FlightShuttleBuilder, tags that do not collide, and photo galleries. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Unique tags per item are mandatory in lists. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent...

Healthcare mobile basics: beyond the buzzword checklist

HIPAA is a process, not a checkbox SDK. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Minimum security, audit logs, and BAAs. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Encrypt, audit access, and sign BAAs with vendors. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent and calls the boundary. The boundary retur...

Health and wellness apps: regulations that bite

Health features attract regulatory attention fast. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Medical device status, HIPAA-ish duties, and store labels. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Declare medical device status accurately in ASC. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent and calls the b...

Hybrid Composition++: Vulkan-composited platform views

HCPP lets Android own layer compositing via SurfaceControl and hardware-buffer swapchains. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Enable HCPP for WebView and maps without Virtual Display tearing. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model No new Dart API — existing platform views upgrade when the flag is on. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or ...

Prompt injection defenses for mobile AI features

Mobile AI features are public attack surfaces. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Input isolation, tool allowlists, and user-visible scopes. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Treat model output as untrusted input to tools. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent and calls the bounda...

Accessibility procurement for public-sector mobile apps

Public deals often require documented accessibility. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence VPAT-style docs, WCAG mapping, and audits. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Map Flutter semantics to WCAG criteria in a living doc. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent and calls the boundary...

go_router deep links and URL strategies that scale

Deep links are a growth feature. A single router for mobile and web keeps them honest. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Path parameters, redirects, and web URL strategies in one router. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Redirects belong in the router, not scattered in widgets. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A control...

GenUI: when agents compose widgets instead of markdown

Chat UIs trained users to accept walls of markdown. GenUI flips the contract to structured UI. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence A2UI and the Flutter GenUI SDK build live UI from structured agent output. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Catalog-constrained widgets + critic loops beat unconstrained generation for reliability. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent su...

Genkit Dart: full-stack AI flows in one language

Genkit Dart runs server-side or inside Flutter clients with a model-agnostic plugin API. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Model-agnostic tools, structured output, and observability for Flutter and servers. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Shared Dart models cut JSON drift between AI flows and UI. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh,...

On-device Gemma with flutter_gemma and LiteRT-LM

On-device models keep data local, work offline, and cut per-request cost. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Local inference across six Flutter platforms with GPU/NPU acceleration. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model LiteRT-LM abstracts hardware differences across Android, iOS, Web, desktop. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry....