koder_kit
- Area: Developer Platform
- Path:
engines/sdk/koder_kit - Kind: Flutter SDK — base package for all Koder Flutter apps
Role in the stack
- Version: 0.39.3
engines/sdk/koder_kit is the foundational Flutter package that every Koder app depends on. Wrapping the app root with KoderApp(config: ..., home: ...) or KoderApp.router(config: ..., routerConfig: ...) automatically injects the full set of behaviors mandated by specs/koder-app/behaviors.kmd:
- Theme — Material 3 light/dark using Koder design tokens;
KoderThemeTogglewidget - Auth — Full OIDC authorization-code + PKCE browser flow (
KoderAuth.signIn()); SSO via KoderIPC; token storage and auto-refresh - Auth UI —
KoderSignInButton,KoderUserBadge,KoderAuthGatefor sign-in/out flows - Error boundary — catches unhandled Flutter errors, renders a user-friendly screen with a unique error ID (
PRODUCT-CAT-CODE-SEQ) and "Ver detalhes" toggle;KoderErrorBannerwidget - Update checker — queries Koder Hub on startup (cached 24h); blocks usage on mandatory updates
- Telemetry — batched structured logs and error events sent to the Koder observability stack
- Safe area —
KoderSafeScaffoldandKoderApp(safeArea: true)perspecs/app-layout/safe-area.kmd - Back behavior —
KoderBackScopeperspecs/navigation/back-behavior.kmd - Motion —
KdsMotionstatic tokens (5 durations, 4 easing curves, 6 spring descriptions, reduced-motion helpers) perspecs/themes/motion/; widgets adopt viaKdsMotion.durationMedium/KdsMotion.easeDecelerate/KdsMotion.reduced(ctx, d)instead of hardcodedDuration(...)/Curves.X - AI widgets — 41-widget
koder_kit/ai.dartnamespace (KAiChat, KAiBrowserView, KAiCheckpointTimeline, KAiFollowUps, KAiModelSelector, KAiPauseControls, KAiPlanReview, KAiPreview, KAiPublish, KAiRating, KAiScheduleList, KAiShareDialog, KAiSkillCardCreatorLibrary, KAiWorkspaceTree, KAiParallelTabs, KoderAIBubble, KoderAIDisclaimer, KoderAICodeBlock, KoderArtifactPanel, KoderCitationList, KoderComposer, KoderConversationList, KoderCostBadge, KoderGhostTextField, KoderMCPElicitationDialogPermissionSheetSamplingDialogServerChipServerDrawer/ToolCard, KoderMemoryPanel, KoderModelPicker, KoderPromptGallery, KoderStreamingText, KoderSystemPromptEditor, KoderThinkingBlock, KoderVoiceModeSheet, KoderAgentStepTrace) per umbrella KIT-030 (closed 2026-05-19, full T-suite coverage)
No wiring required: any app that uses KoderApp as its root gets all behaviors automatically.
Primary couplings
| Module | Relationship |
|---|---|
foundation/id |
Auth: OIDC authorize + token + userinfo endpoints at id.koder.dev |
dev/store |
Updates: hub.koder.dev/api/v1/apps/{slug}/latest |
observe/log |
Telemetry: api.koder.dev/api/v1/logs batch endpoint |
engines/sdk/koder_ipc |
IPC: bundled as dependency — KoderApp auto-registers the IPC server on startup |
| Every Koder Flutter app | Consumer — KoderApp is the required root widget |
Public API
// Minimal usage
KoderApp(
config: KoderConfig(
slug: 'dek',
version: '1.0.0',
ipcCapabilities: ['play', 'pause', 'stop'],
),
home: const MyHomePage(),
)
// Auth — full OIDC browser flow
await auth.signIn(); // SSO via IPC first, then browser PKCE
final user = auth.user; // KoderUser after sign-in
final token = await auth.getValidToken(); // auto-refreshed
// Auth UI widgets
KoderSignInButton(onPressed: () => auth.signIn())
KoderUserBadge(user: auth.user!, onSignOut: () => auth.signOut())
KoderAuthGate(
auth: auth,
signedOut: (ctx) => KoderSignInButton(onPressed: () => auth.signIn()),
signedIn: (ctx, user) => HomeScreen(user: user),
)
// Theme toggle
KoderThemeToggle() // renders the light/dark toggle per spec
// Error banner
KoderErrorBanner(error: someError)Interfaces
| Export | Kind | Description |
|---|---|---|
KoderApp |
Widget | Root widget — injects all behaviors |
KoderConfig |
Class | App-level config (slug, version, base URLs) |
KoderAuth |
ChangeNotifier | OIDC PKCE + ROPC flows, token storage, auto-refresh, user info, IPC SSO, OIDC end_session, isLoading ValueListenable, configurable storage prefix (KoderConfig.storagePrefix + legacyStoragePrefix migration). Full feature parity with flutter_appauth-based stacks (#026 + #027 shipped 2026-05-08) |
parseKoderUserFromIdToken |
top-level fn | Local JWT-claims parse (subemailnamepreferred_usernamepicture); seeds userNotifier immediately without /userinfo round-trip |
KoderAuthCallbackHandler |
Class | Multiplatform OAuth redirect delivery: AppLinks subscription on Android/iOS, 127.0.0.1:<callbackLoopbackPort> loopback HTTP server on desktop, Uri.base read on web. Auto-wired by KoderApp; non-OAuth URIs surfaced via KoderApp.onDeepLink. Eliminates need for flutter_appauth (#028) |
KoderUser |
Class | User profile from /userinfo (id, email, name, picture) |
KoderSignInButton |
Widget | Spec-compliant "Sign in with Koder ID" button |
KoderUserBadge |
Widget | Avatar + display name + sign-out popup |
KoderAuthGate |
Widget | Reactive signed-in / signed-out switcher |
KoderThemeToggle |
Widget | Lightdark toggle per `specsthemes/light-dark.kmd` |
KoderErrorBoundary |
Widget | Error screen with ID + "Ver detalhes" |
KoderErrorBanner |
Widget | Inline error banner for non-fatal errors |
KoderSafeScaffold |
Widget | Window-insets-aware scaffold |
KoderBackScope |
Widget | Back-button behavior per specs/navigation/back-behavior.kmd |
KoderViewSwitcher |
Widget | Adaptive view switcher that relocates header↔bottom-bar by header-space pressure (GNOME AdwViewSwitcher; #075) — KoderViewSwitcherScaffold + pure resolveViewSwitcherPlacement policy, orthogonal to window-size class |
MoneyValue |
Class | Pure money core (#080) — integer minor-units + ISO-4217 currency, NEVER a float; float-free parseformathalf-up, per-currency precision, withCurrency |
KoderMoneyInput |
Widget | Currency-aware amount field (#080) over MoneyValue — affix, blur-reformat, min/max inline; emits canonical MoneyValue? |
KoderStateLabel |
Widget | Read-only VCS-entity status pill (#083) bound to a fixed issue/PR state machine (GitHub Primer); pure koderStateLabelStyle mapping |
KoderNumberSpec |
Class | Pure numeric-field core (#081) — bounds [min,max]stepexplicit precision, clamp, keyboard strides, locale-aware float-safe formatparse (integer-scaled, no double in the value path); the generic base moneyphone specialize |
KoderNumberInput |
Widget | Numeric field with +- spin buttons (#081) over KoderNumberSpec — a11y steppers disabled at bounds, blur clamp+inline message, ↑↓PageUp-Down/Home-End, empty≠zero; emits canonical double? |
PhoneValue / PhoneCountry |
Class | Country-aware phone core (#082#084) — vendored dataset kPhoneCountries (66 countries incl. full CPLP; self-hosted, no libphonenumber dep) + E.164 normalize, locale-aware mask, per-country length validation, locale→country default, E.164 paste detection (NANP +1 USCA by area code); coverage grows by data row |
KoderPhoneInput |
Widget | Phone field (#082) over PhoneValue — KoderCombobox country selector (#084), live mask, ISO E.164 storage, ✓/✗ validation states, paste auto-switches country; emits canonical PhoneValue? (.e164) |
KoderCombobox / comboboxFilter |
Widget/fn | Canonical searchable select (#084) over Material 3 DropdownMenu (reuse-first; combobox.kmd) + the standardized case/diacritic-insensitive substring matcher (label + keywords); single-select v1 |
MediaTransportController / MediaBackend / MediaPlayerModel |
Class | Headless media transport core (#076, package:koder_kit/media.dart) — playpauseseekstop state machine where pause preserves position (kills the "Pause restarts" bug class, audiovideo.kmd §4.1 R1–R7); MediaBackend is the platform-player seam (injected; koder_kit pulls no media plugin), MediaPlayerModel binds them |
KoderAudioPlayer / KoderVideoPlayer / KoderSeekBar |
Widget | Assembled players (#076) over MediaPlayerModel — time readout + tapdrag KoderSeekBar + playpause; video adds injected render surface + fullscreen (V2 preserves position+state); backend injected (appadapter-package provides the real audioplayersjustaudio/videoplayer impl) |
KoderScaffold |
Widget | Koder-branded scaffold with app bar + KoderThemeToggle |
KoderUpdater |
Class | Update check + download-and-apply against Koder Hub (fail-closed SHA-256 verify; per-platform installer via UpdaterHost seam; resume-on-relaunch) |
UpdaterHost |
Abstract class | Platform seam for the apply path (staging fs / process spawn / AppImage swap); IoUpdaterHost on desktop/mobile, web stub |
KoderUpdateBanner |
Widget | Non-mandatory update hint banner (listens to KoderUpdate.notifier) |
KoderUpdate |
Abstract class | Static ValueNotifier<UpdateInfo?> for update state |
KoderTelemetry |
Class | Structured logging and error events |
KoderTrack |
Abstract class | Static helpers: tap(), page(), event() — fan to KoderTelemetry |
KoderL10n |
Abstract class | Static multi-locale string loader with en-US fallback |
koderTheme |
Function | Returns ThemeData for light or dark |
KoderColors |
Abstract class | Koder design token color constants |
generateErrorId |
Function | Generates PRODUCT-CAT-CODE-SEQ IDs |
OIDC browser flow (v0.6.0+)
KoderApp automatically subscribes to deep links on bootstrap via app_links. Redirect URIs per platform:
| Platform | Redirect URI |
|---|---|
| Android / iOS | dev.koder.<slug>://auth |
| Desktop (LinuxmacOSWindows) | http://127.0.0.1:18787/auth |
| Web | ${idBaseUrl}/callback |
Host apps must declare the URL scheme in AndroidManifest.xml / Info.plist. The desktop loopback port is handled transparently by app_links.
The IPC auth_token method is exposed automatically on every KoderApp so peer Koder apps can reuse the session without prompting the user again (per koder-app/behaviors.kmd §1.3).
Specs
specs/koder-app/behaviors.kmd— normative list of what every Koder app must implementspecs/errors/user-facing-messages.kmd— error screen format and ID structurespecs/themes/light-dark.kmd— theme requirementsspecs/themes/motion.kmd— Motion index over the 3 sub-specs belowspecs/themes/motion/easing-duration.kmd— R1 5 durations + R2 5 easing curves (consumed byKdsMotion.duration*/easeX)specs/themes/motion/physics.kmd— R1 reduced-motion contract + R4 spring tokens (consumed byKdsMotion.springSpatial*/springEffect*andKdsMotion.reduced(...)helper)specs/themes/motion/transitions.kmd— R1 transition pattern catalog + R3 page-level transitionsspecs/app-layout/safe-area.kmd— safe area / window insetsspecs/navigation/back-behavior.kmd— back button behavior
Status
embeds/ — 2026-05-20. All six § Escopo widgets of #001 shipping live on kds.koder.dev: theme-toggle, sign-in-button, l10n-switcher, ui-style-picker, command-palette, title-bar. Each mounts only its widget in a thin _EmbedRoot and renders via <koder-embed widget="<slug>"> on the matching detail page. Built via make embeds in tools/design-gen/ (pattern rule embed-%); runtime canvaskit fetched from gstatic.com (Flutter --web-resources-cdn default), keeping each per-widget compressed bundle ≈0.69 MB (cap 2.5 MB). title-bar ships visual fidelity only — dragdouble-tap have no iframe equivalent so the embed shows the chrome with a one-line caption explaining the gap; spec doc remains the source of truth for desktop semantics. Adding a widget = clone `embedsseed, write libmain.dart, append slug to EMBED_WIDGETS in Makefile, flip EmbedShipped: true`.
v0.39.3 — 2026-05-19. KdsMotion adoption — KAiChat._scrollToBottom now uses KdsMotion.durationMedium + KdsMotion.easeDecelerate + reduced-motion gate (jumpTo when MediaQuery.disableAnimations). First production adopter of the motion module shipped in 0.39.2.
v0.39.2 — 2026-05-19. KdsMotion module — canonical motion tokens per specs/themes/motion/. 5 Duration constants, 4 Cubic easing curves, 6 SpringDescription (3 spatial + 3 effect) with stiffnessdamping computed from spring dampingRatio per spec. Reduced-motion helpers: KdsMotion.respectsReducedMotion(ctx), KdsMotion.reduced(ctx, d), KdsMotion.reducedSpring(ctx, s). Wave 3 of the motion programme — Flutter-side counterpart to the CSS tokens emitted by `toolsdesign-gen at kds.koder.dev`. Mirror policy: when CSS tokens evolve (spec changes / Wave 2C build-time generation), bump the matching Dart constants in tandem.
v0.39.1 — 2026-05-19. T-suites for the 23 KAi widgets shipped 2026-05-19 (umbrella KIT-030). Smoke render + 1-2 behavior tests each; full suite 427/427 passes.
v0.39.0 — 2026-05-19. KAI suite umbrella KIT-030 closed (12 carved sub-tickets + 5 pre-existing widgets). 23 widgets total in koder_kit/ai.dart namespace.
v0.7.0 — 2026-04-23. Spec encapsulation batch: KoderScaffold (branded scaffold + theme toggle), KoderTrack (static tappageevent telemetry), KoderUpdateBanner + KoderUpdate.notifier (non-mandatory update UI), KoderL10n (multi-locale string loader), KoderConfig.productName + displayName (auto window title). KoderApp wires all new helpers on bootstrap.
v0.6.0 — 2026-04-23. Full OIDC authorization-code + PKCE browser flow shipped. KoderUser moved to auth.dart; auth UI widgets (KoderSignInButton, KoderUserBadge, KoderAuthGate) added in v0.5.0. KoderSafeScaffold in v0.3.0. KoderBackScope in v0.4.0.