Source code of justresults.no, the editorial homepage of just Results Consulting a.s. (Leif Næss). A Svelte 5 + TypeScript + Vite single-page application — built for human readers and for the growing share of visitors who arrive via LLM agents rather than search.
just Results is an Agentic-AI practice for Norwegian pentahelix clients — startups, SMEs, enterprises, universities and government in process, energy and manufacturing. Three productised systems carry the work:
Each product has its own overview at justresults.no.
$state, $derived, $effect, $props) — no stores, no legacy $:@fontsource<dialog> element for the brief/CV lightbox, with history.pushState-based iOS back-swipe dismissalmainnpm run dev # Vite dev server with HMR (bound to 0.0.0.0 for LAN access)
npm run build # Production build → dist/
npm run preview # Serve the production build locally
npm run check # svelte-check + tsc
npm run test # vitest run
npm run test:watch # vitest watch
Single-file test runs: npx vitest run src/lib/BriefDialog.test.ts
index.html # Static <head>: title, meta, CSP, JSON-LD, OG tags
public/
llms.txt # Plain-markdown summary for LLM crawlers
robots.txt # Explicit allow for GPTBot / ClaudeBot / PerplexityBot / …
briefs/ # PNG system overviews + tech stack + CV
src/
main.ts # Entry — mounts App.svelte, imports fonts + app.css
App.svelte # Editorial shell: nav, <main>, hero, sections
app.css # Design tokens, typography, section stagger animation
lib/
ProjectList.svelte # Expandable project table (centerpiece)
ContactForm.svelte # Underlined editorial fields + "how we work" lead-in
About.svelte # Firm description + CV button
BriefDialog.svelte # Native <dialog> lightbox for brief PNGs
briefDialog.svelte.ts # Shared state + preload helper
data/projects.ts # Project data
*.test.ts # Vitest specs live alongside the code they test
Palette (dark theme is canonical; a light variant exists under prefers-color-scheme):
--bg #1e2a4a — deep navy--text #d4c5a0 — warm parchment body--text-h #f0e6c8 — headings--accent #e8d5a3 — light gold; used for hairline rules, section numbers, focus states, CTAsTypography
font-variation-settings: 'SOFT' 0, 'WONK' 0, 'opsz' 144Layout
main > section) fade + rise on initial load with a 100 ms stagger; disabled under prefers-reduced-motion: reduceThe site is built assuming LLM agents (ChatGPT browsing, Claude, Perplexity, Google AI Overviews) are first-class visitors alongside humans. Supporting pieces:
index.html — ProfessionalService for the firm (with serviceType, knowsAbout, areaServed) and Person for the founder (credentials, expertise)public/llms.txt — markdown summary following the emerging convention, so crawlers that respect it can skip DOM rendering entirelypublic/robots.txt — explicitly names GPTBot, ClaudeBot, PerplexityBot, Google-Extended, CCBot so the allow-list is unambiguousNote: this is a client-rendered SPA. Agents that execute JavaScript read the hydrated DOM; agents that don't fall back to index.html + JSON-LD + llms.txt, which is why the load-bearing facts are duplicated in the static head.
The site is a static SPA with no backend, no database, and no user-generated content. The attack surface is correspondingly small.
In-code defences
index.html: default-src 'self'; script-src 'self' https://analytics.justresults.no; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' ws: wss: https://analytics.justresults.no; object-src 'none'; base-uri 'self'; frame-ancestors 'none'referrer-policy: strict-origin-when-cross-origin meta tag{@html ...} of user input — Svelte's default auto-escaping covers XSS; the one {@html} site (markdown rendered from a checked-in file) is build-time content under version controlExpected from the production host (set as HTTP headers at the edge)
Content-Security-Policy — same policy as above, plus upgrade-insecure-requestsStrict-Transport-Security: max-age=31536000; includeSubDomains; preloadX-Content-Type-Options: nosniffX-Frame-Options: DENY (or equivalent via CSP frame-ancestors)Permissions-Policy — a conservative default disabling camera/microphone/geolocationOpen items
submitted flag. When wired to a real endpoint, add: honeypot field, rate limiting, and Cloudflare Turnstile (or equivalent).LinkedIn → add to the Person JSON-LD sameAs array once the founder profile refresh is published.npm audit before each release.This project uses strict test-driven development. For every new feature:
Tests live next to source as *.test.ts. File-level specs (src/seo.test.ts, src/motion.test.ts, src/shell.test.ts) assert static-file and shell-level invariants; component specs cover rendering and interaction.
vite.config.ts sets server.host: true so the dev server binds to 0.0.0.0 and can be reached from other devices on the LAN (useful for testing on a phone). Default port is 5173; strictPort: true prevents silent fallback.
MIT — Copyright (c) 2026 Leif Næss / just Results Consulting a.s.