Devportalen
Arkitekturen
Skal och moduler, de tre ytformerna, dataflödet och rollfiltreringen.
Bärande idé
Skalet äger kromet och kompositionen. Modulen äger innehållet och sin data. Kontraktet däremellan är ModuleManifest – och det är avsiktligt tunt.
Kompositionen
┌──────────────────────────────────────────────┐
│ Skalet (apps/projekt/src/shell) │
│ sidopanel · AI-fält · rollväxling · rutnät │
└───────────────┬──────────────────────────────┘
│ läser registry, filtrerar på roll
┌───────────────▼──────────────────────────────┐
│ ModuleManifest (packages/module-sdk) │
│ nav · routes · slots · ai │
└───────────────┬──────────────────────────────┘
│ ett paket per modul
┌────────┬───────────┼───────────┬──────────┬───────────┐
oversikt agera arenden kalender ledighet utveckling …
│ │ │ │ │
└─────────┴──────────┴───────────┴──────────┘
hämtar sin egen data på servern (ADR-006)| Ansvar | Skalet | Modulen |
|---|---|---|
| Layout och krom | Ja – sidopanel, rutnät, sidfot, fokusläge | Nej |
| Vad som visas | Nej – vet bara vilken slot en widget hör till | Ja |
| Data | Nej | Ja – hämtar själv på servern |
| Roll och identitet | Ja – cookie, demoanvändare, UserContext | Nej – tar emot ctx |
| Designtokens och primitiver | Ja – tillhandahåller | Nej – konsumerar |
| Beslut om att skapa något | Ja – route handlern validerar | Nej – föreslår |
Tre ytformer, ett skal
Alla tre delar sidopanel, tokens och AI-märkning. De skiljer sig i vad skalet renderar runt innehållet.
| Ytform | Facit i docs/ | Kännetecken | Deklareras med |
|---|---|---|---|
| Verktygsyta | startsidan-prototyp-v3.html | Rollfiltrerad, datadriven, komponerad av modulernas slots | slots.kpi / main / side / actions |
| Sida | it-support-prototyp.html, innehallssida-prototyp.html | Redaktionellt innehåll, brödsmulor, sidkontext i AI-fältet | pages: PageManifest[] (ADR-016) – layout "hub", "article" eller "embed" (ram, ADR-017), innehåll som ContentBlock |
| Fokusflöde | felanmalan-poc.html | Helskärm utan sidopanel, smal topprad med Avbryt | routes med mode: "focus" (ADR-004) |
| Modulvy | – (kort och artikel ur /dev/ui) | Modulens egen vy med sidopanel och menyrad, t.ex. personalakten | routes med mode: "standard" under /verktyg/, path med :parametrar (ADR-019) |
| Modulvy över hela ytan | – (Min AI) | Sidopanelen kvar, vyn tar hela arbetsytan i skärmens höjd – som en chattjänst | routes med mode: "full" under /verktyg/ (ADR-025) |
En modul kan bidra med alla tre. felanmalan äger ett fokusflöde och snabbvägskortet som leder dit från IT-supportsidan.
Dataflödet
- Rollen bor i en cookie och läses på servern med getCurrentUser() (ADR-006).
- Skalet gör om användaren till UserContext och skickar den till varje widget.
- Widgeten är en async server component som anropar modulens egen datafunktion i data/ – inget nätverksanrop, ingen fetch. I fas 4 byts funktionens insida mot BFF:en.
- /api/mock/<modul> är inte modulens datakälla utan en tunn spegel: route handlern anropar samma funktion och visar vilken form ett riktigt mikrotjänst-API skulle ge.
- Ingenting om användaren skickas upp från klienten. En profil som klienten skickar vore en injektionsväg rakt in i ärendet.
Så ser en widget ut
export async function Idag({ ctx }: { ctx: UserContext }) {
const { poster } = await hamtaDagen(ctx); // modulens egen data
return <Card headingId="idag-h" title="Idag">…</Card>;
}Rollfiltrering
Allt filtreras mot två roller: medarbetare och chef. Filtret finns på tre nivåer och den snävaste vinner – modulen, widgeten, nav-posten.
export const manifest = defineModule({
id: "kalender",
roles: ["medarbetare", "chef"], // modulens roller
slots: {
side: [
{ id: "kalender-idag", order: 10, Component: Idag },
{ id: "kalender-aterkommande", order: 40,
roles: ["chef"], // snävare än modulen
Component: AterkommandeHandelser },
],
},
});Rollskillnader i text väljs i komponenten, inte genom två manifestposter: title={ctx.role === "chef" ? … : …}.