Impulse AI Docs
Intern dokumentasjon
skipLink.label

Systemarkitektur

Komplett oversikt over systemarkitekturen til Impulse AI. Dokumentet dekker alle lag fra monorepo-oppsett til AI-pipeline, og forklarer de viktigste arkitekturbeslutningene og hvorfor de ble tatt.

Plattformoversikt

heading.anchorLabel

Impulse AI er en impuls-drevet transformasjonsplattform med tre hoveddistribusjonskanaler:

KanalTeknologiDeploy
iOS-appSwiftUI + KMP sharedApp Store
Android-appJetpack Compose + KMP sharedGoogle Play
APIFastify (Node.js)Railway
DatabaseSupabase (PostgreSQL)Supabase Cloud

Monorepo-struktur

heading.anchorLabel

Prosjektet bruker Turborepo med pnpm workspaces for a organisere alle applikasjoner og pakker i ett repository.

im/
├── apps/
│ ├── api/ # Fastify API-server (port 3001)
│ ├── mobile-kmp/ # Kotlin Multiplatform mobilapp
│ │ ├── shared/ # KMP delt modul (Kotlin)
│ │ ├── iosApp/ # iOS-app (SwiftUI)
│ │ └── androidApp/ # Android-app (Jetpack Compose)
│ ├── console/ # Kontrollrom for ClawdBot (Next.js)
│ ├── landing/ # Distribusjonsplattform (Next.js)
│ └── docs/ # Starlight dokumentasjon
├── packages/
│ ├── shared/ # Delte TypeScript-typer og skjemaer
│ ├── api-client/ # Typet API-klient
│ ├── auth/ # Autentiseringsverktoy
│ └── database/ # Supabase-migrasjoner + genererte typer

Fordeler med monorepo

heading.anchorLabel
  • En kildekode: Alle tjenester deler typer og kontrakter
  • Atomiske endringer: Database-migrasjoner, API-endringer og klientoppdateringer i samme PR
  • Delt verktoy: Lint, formatering og typesjekk konfigurert en gang

Fastify-server

heading.anchorLabel

API-serveren er bygget med Fastify og kjorer pa Railway. Den hhandterer all forretningslogikk, AI-integrasjon og databasetilgang.

apps/api/
├── src/
│ ├── routes/ # HTTP-endepunkter (REST)
│ ├── services/ # Forretningslogikk
│ ├── middleware/ # Auth, subscription, rate limiting
│ ├── ai/ # AI-workloads og pipeline
│ ├── queues/ # BullMQ bakgrunnsjobber
│ ├── state-machines/ # Robot3 tilstandsmaskiner
│ └── lib/ # Database, logging, utilities

Viktige moonstre:

  • Route-moenster: Schema-validering + preHandler (auth, tier-sjekk) + handler
  • Serialiseringskonvensjon: Database-kolonner bruker snake_case, JSONB-innhold bruker camelCase
  • Tier-hhandheving: Middleware sjekker abonnement for operasjoner (trial, foundation, mastery, partner)
// Typisk route-moenster
fastify.post('/path', {
schema: { /* OpenAPI-skjema */ },
preHandler: [requireAuth, requireTier(['foundation', 'mastery'])],
}, async (request, reply) => {
// 1. Valider input
// 2. Sjekk tillatelser
// 3. Kjor forretningslogikk
// 4. Returner strukturert respons
})

Bakgrunnsjobber (BullMQ)

heading.anchorLabel

Asynkrone operasjoner som AI-klassifisering og embedding-generering kjorer via BullMQ-koer med Redis:

  • Impulse-klassifisering: Analytisk + kreativ AI-analyse etter impulsfangst
  • Embedding-generering: Voyage AI vektorer for semantisk sok
  • Sesjonoppsummering: AI-generert oppsummering etter fullfort sesjon
  • Innsikt-regenerering: Periodisk oppdatering av personlige innsikter

Impulse AI bruker Supabase som database-plattform, med PostgreSQL, innebygd autentisering og Row Level Security (RLS).

Se Databasearkitektur for fullstendig dokumentasjon av tabeller, JSONB-konvensjoner og migrasjonsarbeidsflyt.

Kotlin Multiplatform

heading.anchorLabel

Den delte mobillogikken lever i apps/mobile-kmp/shared/ og inneholder:

shared/src/commonMain/kotlin/com/im/shared/
├── domain/ # Domenemodeller (Impulse, Session, Insight)
├── stores/ # FlowMVI stores (state management)
├── data/ # API-klienter og repository-implementasjoner
├── i18n/ # Moko streng-ressurser
└── util/ # Delte verktoy

KMP deler:

  • Domenemodeller (Impulse, Session, CheckIn, etc.)
  • API-klienter (Ktor-basert HTTP)
  • Autentiseringshhandtering (AuthManager)
  • State management (FlowMVI stores)
  • Lokalisering (Moko Resources)

iOS-arkitektur (SwiftUI)

heading.anchorLabel

iOS-appen folger en feature-basert mappestruktur med @Observable StoreWrappers som bro mellom KMP og SwiftUI:

iosApp/
├── Features/ # Feature-moduler (en mappe per skjerm)
│ ├── Home/ # Hjem-skjerm
│ ├── Insights/ # Innsikter (2 dataprodukter)
│ ├── Journey/ # Impuls-reise
│ ├── Sessions/ # 5-stegs sesjoner
│ ├── CheckIn/ # Sjekk-inn
│ ├── Capture/ # Impulsfangst
│ └── Navigation/ # Tab bar
├── Stores/ # KMP StoreWrappers (@Observable)
├── Components/ # Delte UI-komponenter
├── Theme/ # Fargetokens, typografi
└── Services/ # Plattformtjenester

State management

heading.anchorLabel

Appen bruker FlowMVI i KMP for unidireksjonal tilstandshhandtering, med @Observable StoreWrappers pa iOS-siden:

┌─────────────────────────────────────────────────┐
│ SwiftUI View │
│ Leser @Observable StoreWrapper properties │
└──────────────────────┬──────────────────────────┘
│ Intent-dispatch
┌──────────────────────▼──────────────────────────┐
│ @Observable StoreWrapper │
│ • Abonnerer pa KMP state flow (via SKIE) │
│ • Eksponerer Swift-vennlige properties │
│ • Dispatcher intents til KMP store │
└──────────────────────┬──────────────────────────┘
│ SKIE bridging
┌──────────────────────▼──────────────────────────┐
│ KMP FlowMVI Store │
│ • Hhandterer state via reduce {} │
│ • Kjorer async operasjoner (API-kall) │
│ • Emitter actions for side effects │
└─────────────────────────────────────────────────┘

Dataflyt: State (KMP) -> View (SwiftUI) -> Intent (brukerhandling) -> Reducer (KMP) -> ny State

Kommunikasjonsmekanismer

heading.anchorLabel

Appen bruker tre distinkte kommunikasjonsmonstre mellom lag:

MekanismeJobbRetningEksempel
@Observable stateReaktive UI-oppdateringerStore -> View (automatisk)Loading-spinnere, listedata
CallbacksNavigasjons-sideeffekterStore -> View (imperativt)Apne fullScreenCover, dismiss view
AppEventBusKryss-store koordineringStore -> Store (KMP-niva)“Analyse ferdig” -> HomeStore refresher

Kryss-domene events (AppEventBus)

heading.anchorLabel
sealed interface AppEvent {
data class ImpulseUpdated(val impulseId: String) : AppEvent
data class SessionCompleted(val impulseId: String, val sessionType: String) : AppEvent
data object UserLoggedOut : AppEvent
// ...
}
object AppEventBus {
private val _events = MutableSharedFlow<AppEvent>(
extraBufferCapacity = 20,
onBufferOverflow = BufferOverflow.DROP_OLDEST
)
val events: SharedFlow<AppEvent> = _events.asSharedFlow()
}

Derived View State (enum state machines)

heading.anchorLabel

Nar en SwiftUI view avhenger av flere @Observable stores, utledes visningstilstanden gjennom en computed enum — aldri gjennom if-else-kjeder i view body.

// Enum fanger ALLE mulige tilstander
enum FooContentState {
case loading
case empty
case content
case error(String)
}
// Computed property -- ett eneste utledningspunkt
private var contentState: FooContentState {
if store.isLoading && !store.hasData { return .loading }
if !store.hasData { return .empty }
return .content
}
// Exhaustive switch -- kompilatoren sikrer fullstendighet
switch contentState {
case .loading: ProgressView()
case .empty: EmptyState()
case .content: ContentView()
case .error(let msg): ErrorView(msg)
}

AI-integrasjonen bruker Anthropic Claude (via Vercel AI SDK) for tekst og Voyage AI for embedding-generering.

Se AI Pipeline for fullstendig dokumentasjon av workloads, modellvalg og prompter.

Overordnet flyt

heading.anchorLabel
Brukerhandling
API-endepunkt (Fastify)
BullMQ koe (asynkron)
AI Workload (Anthropic Claude / Voyage AI)
Database-oppdatering (Supabase)
Klient-oppdatering (polling / SSE)

Viktige arkitekturbeslutninger

heading.anchorLabel

Hvorfor KMP (Kotlin Multiplatform)?

heading.anchorLabel
  • Delt forretningslogikk: API-klienter, domenemodeller og state management skrives en gang
  • Plattformnative UI: SwiftUI og Jetpack Compose gir best mulig brukeropplevelse
  • SKIE bridging: Seker Kotlin/Swift interop for flows, sealed classes og coroutines

Hvorfor Fastify (ikke Next.js API routes)?

heading.anchorLabel
  • Ytelse: Fastify er vesentlig raskere enn Express/Next.js API routes
  • Schema-validering: Innebygd JSON Schema-validering med OpenAPI-generering
  • Plugin-okosystem: Strukturert plugin-system for middleware, auth, rate limiting
  • Separat deploy: API deployes uavhengig av frontend pa Railway

Hvorfor Supabase?

heading.anchorLabel
  • PostgreSQL: Full relasjonsdatabase med pgvector for embedding-sok
  • Innebygd auth: Supabase Auth med social login (Apple, Google)
  • RLS: Row Level Security for finkornet tilgangskontroll
  • Realtime: Innebygd stoette for sanntidsoppdateringer
  • Migrasjoner: SQL-baserte migrasjoner med versjonskontroll

Hvorfor FlowMVI?

heading.anchorLabel
  • Predikerbar tilstandsflyt: Enveis dataflyt gjor state-endringer sporbare
  • Kryssplattform: Samme forretningslogikk pa iOS og Android
  • Typesikkerhet: Compile-time verifisering av State/Intent/Action-kontrakter
  • Testbarhet: Pure reducers og isolerte sideeffekter

Hvorfor Vercel AI SDK?

heading.anchorLabel
  • Strukturerte outputs: Automatisk Zod-til-JSON-Schema konvertering med validering
  • Prompt caching: Innebygd stotte for Anthropic prompt caching (kostnadsreduksjon)
  • Provider-abstraksjon: Enkelt a bytte mellom AI-modeller
  • Retry-logikk: Automatisk retry pa HTTP-feil (429, 500, 503)

Porter og miljoer

heading.anchorLabel
TjenestePortMiljo
API (Fastify)3001Railway (produksjon)
Console (Next.js)3004Vercel
Landing (Next.js)3003Vercel
Supabase Studio54323Lokal
PostgreSQL54332Lokal
Redis6380Lokal / Railway