Skip to content
Fusion

Portfolio — the home

The Portfolio is what you land on after signing in (/home). It's the example's "home screen": a ranked view of every building you're part of, most-urgent first, with the AI assistant (Carola) front and centre. Click a building to enter its workspace at /project/$projectKey, where the project-scoped apps — ProcessN, ProtokollN, NyhetN, WikiN — live.

Coming from Django? This is your index view — a dashboard that aggregates across several apps. The twist: it composes data from multiple server functions in one loader, and the primary surface is a chat box, not a table.

Where it lives

LayerFiles
Routessrc/routes/_authed.home.tsx (the landing) · src/routes/index.tsx (the public, signed-out home)
Server functionssrc/lib/project-server.ts (getPortfolio) · src/lib/briefing-server.ts (deadlines) · src/lib/agent-server.ts (notifications, approvals)
Componentssrc/components/portfolio/Portfolio.tsx · CarolaInline · NeedsYou · ProjectMapPanel

What you see

The Portfolio is deliberately chat-first and minimal — not a wall of widgets:

  • a one-line greeting and Carola's briefing (a single sentence: clear, or "something's overdue"),
  • the single most urgent thing that needs you (an overdue task, a pending approval),
  • a prominent composer — ask Carola anything; the full overview comes back in the conversation, on demand,
  • a map of your buildings (ProjectMapPanel, client-only / lazy-loaded), rendered only when you're not mid-conversation.

The design rule worth knowing if you extend it: Carola's UI is one inline canvas that expands and reflows — never in-page overlays, modals, popovers, or floating widgets; everything happens in the page flow. Once a conversation opens it gets its own header (rename · star · add-to-project · files · pop-out) and the right rail becomes Carola's companion. The one exception to "no floating widgets" is floating Carola — the live conversation popped into a real, separate OS window via Document Picture-in-Picture (Carola).

How it loads

/home is a single loader that fans out to a few server functions and composes them:

example/src/routes/_authed.home.tsx
export const Route = createFileRoute("/_authed/home")({
	// `?scope=` carries Carola's scope so switching it re-lenses the conversation in place
	// (pathname stays `/home`) and a reload / deep-link restores it. The provider resolves the
	// value (a project key, or "portfolio" / "general") against the viewer's projects.
	validateSearch: (search: Record<string, unknown>): { scope?: string } => ({
		scope: typeof search.scope === "string" ? search.scope : undefined,
	}),
	loader: async () => {
		const [buildings, findings, approvals, deadlines] = await Promise.all([
			getPortfolio(),
			listMyNotifications(),
			listMyApprovals(),
			listMyDeadlines(),
		]);
		return { buildings, findings, approvals, deadlines };
	},
	component: Home,
});

The loader fires the reads in parallel (Promise.all) and hands the component { buildings, findings, approvals, deadlines }. getPortfolio() returns each building the viewer can see (the same permission filters the apps use) with its urgency signal — overdue / due-soon ProcessN tasks and the next ProtokollN meeting — so the list can sort "what needs me most" to the top. The "needs you" rollup (findings + approvals) comes from the proactive agent.

The seed

bun run db:seed fills the Portfolio (and every app) with realistic data so the rules are visible, not theoretical. It models Tikab's live portfolio — "Tikab – aktiva uppdrag" — as nine real construction projects (Slussen, Slakthusområdet, Hisingsbron, Sturekvarteret, …), each with map coordinates.

  • Ten Tikab logins sign in (password password123); the site admin is andre.holmstrom.tikab@p4o.se (André Holmström). The other nine are his colleagues — same fornamn.efternamn.tikab@p4o.se pattern. Each login has real assignments (at least one overdue and one due-soon), so the urgency ranking is genuine.
  • ~665 register people are members of the projects, and ~1000 background users give the admin table realistic volume — but only the ten Tikab logins can actually sign in (everyone else has no password).
  • 100+ news posts and 100+ wiki articles carry concrete, askable facts, so "ask the project a question" has real answers (NyhetN · WikiN).

Sign in as different people and the same pages change — André (site admin, owns four projects) sees everything; a viewer-role member sees the project but can change nothing. Authorization explains why.

Extending it

  • A new urgency signal → add it to getPortfolio() in project-server.ts and fold it into the ranking; the building cards read whatever the server returns.
  • A new landing surface → keep it inline (no modal/widget) and gate it on the conversation state, like ProjectMapPanel does.
  • A whole new page → not everything belongs on /home; add a route and follow Building a feature.