Gå til innholdet

Arkitektur og stack

Monorepo gir felles TypeScript-typer, delt konfigurasjon og effektiv bygging. Turborepo cacher builds og kjører tasks parallelt. pnpm er raskere og mer diskeffektiv enn npm/yarn.

packages/types/ — Delte typer som importeres av både API og Web
packages/db/ — Drizzle-skjema, migrations, tilkobling
packages/auth/ — Auth.js-konfigurasjon, passord-hashing, middleware
apps/api/ — Express.js: routes, services, AI-integrasjon
apps/web/ — React: pages, components, hooks

Enkel og veldokumentert. Gir full kontroll over routing, middleware og API-design uten magi.

Lag-ansvar (strict separation):

  • Routes — Input-validering med Zod + HTTP-respons. Ingen forretningslogikk.
  • Services — All domenelogikk. Typede feil. Ingen HTTP-avhengighet.
  • DB — Drizzle-spørringer. Kalles kun fra services.
  • AI — Kontekstbygging, prompts, API-kall.

Database: PostgreSQL 16 + Drizzle ORM + pgvector

Section titled “Database: PostgreSQL 16 + Drizzle ORM + pgvector”

PostgreSQL er valgt framfor grafdatabase (Neo4j) fordi relasjonene i dette systemet ikke krever graftraversal. Drizzle ORM gir typesikre spørringer og full SQL-kontroll.

pgvector gjør semantisk søk mulig uten ekstern vector store (Pinecone, Weaviate). Embeddings lagres som vector(1536) kolonner direkte i PostgreSQL.


Self-hosted med Credentials-provider (e-post/passord). Ingen ekstern avhengighet.

  • Passord-hashing: PBKDF2-SHA256, 100 000 iterasjoner, Node.js crypto (ikke bcrypt)
  • Sesjon: JWT i httpOnly-cookie
  • Middleware: requireAuth og requireAdmin på Express-routes

S3-kompatibel objektlagring i Docker. Kan erstattes av AWS S3 eller Cloudflare R2 uten kodeendringer — identisk API. Håndterer bilder, PDF-er og dokumenter.


Når brukeren stiller et spørsmål, bygges en strukturert kontekstblokk:

Eiendom: Hellebakken 9, enebolig, byggeår 1975
Valgt rom: Stue (34 m², 1. etasje)
Designretning interiør: nordisk, naturlig, varm
Brukerprofil: balanced budsjett, hybrid arbeidsstrategi

Brukerens spørsmål embeddes (text-embedding-3-small) og søkes mot:

  • Rom-beskrivelser
  • Issue-tekster
  • Observation-tekster
  • DesignDirection-tekster
  • Manualinnhold (chunked)

De mest relevante entitetene inkluderes i konteksten (cosine similarity).

PDF-onboarding i 8 steg:

Upload → Queue → Parse → Extract → Structure → Store → Review → Persist

Kritisk prinsipp: AI foreslår → bruker godkjenner → system lagrer.

// Forenklet extraction-prompt
const systemPrompt = `
Du er ekspert på norske takstrapporter.
Ekstraher strukturerte data og returner JSON.
For hvert faktum: verdi, sidenummer, tekstutdrag, confidence (0.0-1.0).
`

Kostnad per takstrapport: ~$0.25 (60 sider ≈ 80 000 tokens ved Sonnet 4.6-priser).


services:
postgres: PostgreSQL 16 + pgvector + pgcrypto
minio: S3-kompatibel fillagring
api: Express.js (multi-stage Dockerfile)
web: React + Nginx (statisk bygg)

Ekstern tilgang via Cloudflare Tunnel — ingen åpne porter i hjemmeruteren.

Arkitekturen er container-basert og kan flyttes til Fly.io, Railway, Render, AWS eller GCP uten kodeendringer — kun miljøvariabler og CI/CD.


Se råteksten fra tech-architecture.md for den fullstendige begrunnelsen.