Hopp til innhold
KI

Min første blogg

Ludo Fourrage Ludo Fourrage 8. april 2026 8 min lesetid
Min første blogg

Problem Statement:

Plattformen mangler en innholdsmarkedsføringskanal. En blogg gjør det mulig for hver tenant å publisere SEO-optimaliserte, flerspråklige artikler skrevet i Strapi CMS og gjengitt i SvelteKit-appen – noe som øker organisk trafikk, bygger autoritet og støtter den eksisterende i18n-pipelinen med 13 lokaliteter.

Suksesskriterier

  • Blogginnlegg skrevet i Strapi vises på frontend med leietakerens egen branding
  • Innlegg autotranslateres til alle 13 språkversjoner via eksisterende webhook-pipeline (ingen endringer i oversettelsesinfrastrukturen)
  • Bloggsider rangerer i søkemotorer (structured data, sitemap, hreflang, og:article)
  • Leietakere uten blog feature-flagget får ingen bloggruter (404)

User Stories

  • Som innholdsforfatter vil jeg skrive blogginnlegg i Strapi med rik markdown, bilder og video-innbygginger slik at jeg kan publisere innhold uten å røre kode
  • Som en nettstedsbesøkende vil jeg bla i blogginnlegg filtrert etter kategori slik at jeg kan finne relevant innhold
  • Som en nettstedsbesøkende vil jeg ha en innholdsfortegnelse på lange innlegg slik at jeg kan navigere raskt
  • Som en nettstedsbesøkende vil jeg lese innlegg på mitt språk, med automatisk oversettelse fra engelsk
  • Som en nettstedsbesøkende vil jeg dele innlegg i sosiale medier
  • Som en nettstedsbesøkende vil jeg oppdage relaterte innlegg og bli kjent med forfatteren
  • Som en SEO-ansvarlig vil jeg at hvert innlegg skal ha riktige metatagger, strukturert data og oppføringer i sitemapet

Funksjonelle krav

Må ha (MVP)

  1. Strapi-innholdstyper: blog-posts, blog-authors, blog-categories — alle med tenant, locale, inherit-felter
  2. Bloggoversiktsside (/blog) — paginert rutenett med innlegg, kategorifilter via query-param
  3. Detaljside for innlegg (/blog/[slug]) — full markdown-rendering med innholdsfortegnelse, forfatterkort, relaterte innlegg, deling i sosiale medier
  4. Kategoriside (/blog/category/[slug]) — filtrert oversikt som gjenbruker de samme listekomponentene
  5. Forfatterside (/blog/author/[slug]) — forfatterbio + deres innlegg
  6. Innholdsfortegnelse — auto-generert fra h2/h3-overskrifter, sticky sidebar på desktop, kollapsbar på mobil, aktiv overskrift markeres via Intersection Observer
  7. YouTube/Vimeo-innbygging — rene URL-er i markdown auto-konverteres til responsive iframes (youtube-nocookie.com for personvern)
  8. Lesetid — beregnes server-side ut fra ordantall (Math.ceil(words / 200))
  9. Delingsknapper for sosiale medier — X, Facebook, LinkedIn, e-post, kopier-lenke (Web Share API der det er tilgjengelig)
  10. Relaterte innlegg — samme kategori, ekskluder nåværende, maks 3, sortert på publishedAt desc
  11. RSS-feed (/blog/rss.xml) — RSS 2.0, locale via query-param
  12. SEO — SeoComponent per innlegg, og:article-tags, BlogPosting JSON-LD-skjema, kanoniske URL-er
  13. Sitemap — dynamiske URL-er for blogginnlegg/kategori/forfatter legges til eksisterende sitemap med hreflang
  14. Feature flagblog: boolean i TenantConfig.features, layout-guard returnerer 404 når deaktivert
  15. i18n — Paraglide-meldingsnøkler for alle UI-strenger (navigasjon, etiketter, paginering), Strapi-innhold auto-oversettes via eksisterende webhook
  16. Paginering — sidebasert ved bruk av Strapis innebygde paginering (9 innlegg per side)
  17. Fremhevet innlegg — boolsk featured-flagg på blog-posts; fremhevet innlegg vises som et hero-kort øverst på /blog-oversiktssiden (større kort, full bredde, over rutenettet)

Kjekt å ha (Post-MVP)

  1. Fritekstsøk på tvers av blogginnlegg
  2. Innleggsserier / artikler i flere deler
  3. Lesefremdriftsindikator
  4. Kommentarer (trolig via tredjeparts-embed)
  5. CTA for nyhetsbrevpåmelding inne i innlegg
  6. Visningsteller / analyseintegrasjon

Tekniske krav

Datamodell (Strapi Content Types)

blog-posts (api::blog-post.blog-post):

Felt Type Lokaliseres Notater
title Tekst (obligatorisk) Ja Matches av oversettelseskonfigurasjon
slug UID (fra title) Nei Ekskludert fra oversettelse
excerpt Tekst Ja For kortvisning + meta-beskrivelse
body Rich Text (Markdown) Ja Renderes via marked
featuredImage Media (enkelt) Nei URL + alternativeText
category Relasjon (manyToOne -> blog-category) Nei
author Relasjon (manyToOne -> blog-author) Nei
featured Boolean (standard false) Nei Fremhevet innlegg vises som hero-kort i listing
seo Komponent (shared.seo) Ja Gjenbruk eksisterende SeoComponent
tenant Tekst Nei Standard tenant-filter
inherit Boolean (standard true) Nei Auto-oversettelsesflagg

blog-authors (api::blog-author.blog-author):

Felt Type Lokaliseres Notater
name Tekst (obligatorisk) Ja
slug UID (fra name) Nei
bio Rich Text (Markdown) Ja
avatar Media (enkelt) Nei
socialLinks JSON Nei { twitter?, linkedin?, website? }
tenant Tekst Nei
inherit Boolean (standard true) Nei

blog-categories (api::blog-category.blog-category):

Felt Type Lokaliseres Notater
name Tekst (obligatorisk) Ja
slug UID (fra name) Nei
description Tekst Ja
color Tekst Nei Hex-farge for UI-badges
tenant Tekst Nei
inherit Boolean (standard true) Nei

TypeScript-grensesnitt

Se src/lib/services/strapi-types.ts for BlogPost, BlogAuthor, BlogCategory.

Ruter

Alle under src/routes/(marketing)/blog/:

Rute Server-load Formål
blog/+layout.server.ts Feature guard + laste kategorier Gate + navigasjonsdata
blog/+page.server.ts Paginert liste med innlegg, valgfritt ?category=-filter Listing
blog/[slug]/+page.server.ts Innlegg etter slug + relaterte innlegg + beregning av lesetid Detalj
blog/category/[slug]/+page.server.ts Innlegg filtrert på kategori Kategorilisting
blog/author/[slug]/+page.server.ts Forfatter + deres innlegg Forfatterside
blog/rss.xml/+server.ts RSS 2.0 XML, ?locale=-parameter Feed

UI-komponenter

Alle i src/lib/components/blog/:

Komponent Props Notater
BlogPostCard.svelte post: BlogPost Kort med bilde, kategorimerke, tittel, utdrag, forfatter, dato, lesetid
BlogPostContent.svelte body: string Markdown til HTML via marked med video-embed-utvidelse + heading-ID-er
TableOfContents.svelte entries: TocEntry[] Sticky sidebar, Intersection Observer for aktiv tilstand, sammenleggbar på mobil
AuthorCard.svelte author: BlogAuthor Avatar, navn, bio, sosiale lenker
SocialShare.svelte url: string, title: string Deleknapper med fallback til Web Share API
RelatedPosts.svelte posts: BlogPost[] Grid med BlogPostCard
BlogPagination.svelte pagination: StrapiPagination, basePath: string Forrige/neste + sidenumre

Sikkerhet og autentisering

  • Blogg er offentlig (ingen autentisering kreves) — markedsføringsinnhold
  • Strapi API-lesetilgang via eksisterende STRAPI_JWT-token
  • Video-innbygging bruker youtube-nocookie.com for GDPR-kompatibilitet

Randtilfeller og feilhåndtering

  • Innlegg ikke funnet: 404 via SvelteKit error()
  • Ingen innlegg i kategori: Tomtilstand med blog_no_posts-melding
  • Mangler fremhevet bilde: Kortet rendres uten bilde
  • Oversettelse ikke tilgjengelig: loadContentWithFallback() faller tilbake til engelsk
  • RTL-språk: Layout respekterer dir="rtl" (ar, he, ur)

E2E testplan

Testfilene ligger i tests/blog/. Følg eksisterende mønstre: parameterisert på tvers av visningsflater (viewports), Axe for universell utforming (a11y), networkidle venter på Strapi-innhold.

Kritiske flyttester

  1. Bloggoversikt lastes/blog viser et rutenett med postkort med tittel, utdrag, kategorimerke, forfatter, dato og lesetid
  2. Paginering fungerer/blog?page=2 viser side 2 av resultatene; forrige/neste-knapper navigerer riktig; side 1 har ingen «Forrige»-knapp
  3. Kategorifilter — å klikke på en kategoribrikke filtrerer innlegg; URL oppdateres til ?category=<slug>; «Alle»-brikken fjerner filteret
  4. Innleggsdetaljer rendres/blog/[slug] viser tittel, fremhevet bilde, formatert brødtekst, forfatterkort, lesetid og publiseringsdato
  5. Innholdsfortegnelse — detaljsiden for innlegg genererer innholdsfortegnelse fra h2/h3-overskrifter; klikk på en ToC-oppføring scroller til riktig overskrift
  6. Relaterte innlegg — detaljsiden viser opptil 3 relaterte innlegg fra samme kategori (uten å inkludere gjeldende innlegg)
  7. Kategori-side/blog/category/[slug] viser kategoriens navn, beskrivelse og kun innlegg fra den kategorien
  8. Forfatterside/blog/author/[slug] viser forfatterbio, avatar, sosiale lenker og deres innlegg
  9. Delingsknapper for sosiale medier — delingsknapper er synlige på detaljsiden; «Kopier lenke» kopierer URL-en og viser en bekreftelsestekst
  10. RSS-feedGET /blog/rss.xml returnerer gyldig XML med Content-Type: application/rss+xml og inneholder innleggsoppføringer
  11. Navigasjon — blogglenken i hovedmenyen navigerer til /blog; brødsmulestien viser korrekt hierarki
  12. Fremhevet innlegg/blog viser det fremhevede innlegget som et større hero-kort over det vanlige rutenettet

Randtilfeller og feilhåndtering

  1. Innlegg ikke funnet/blog/nonexistent-slug returnerer en 404-side
  2. Tom kategori — en kategori uten innlegg viser tomtilstands-meldingen blog_no_posts
  3. Manglende fremhevet bilde — postkort rendres på en god måte uten bilde (ingen ødelagt <img>)
  4. Manglende forfatter/kategori — innlegg uten forfatter eller kategori rendres uten disse elementene (ingen krasj)
  5. Feature flag deaktivert — når blog: false, returnerer /blog 404

Tverrgående tester

  1. i18n: bytte av språkversjon — naviger til /fr/blog, verifiser at UI-strenger (sidetittel, «Les mer», pagineringsetiketter) er på fransk; innholds­teksten faller tilbake til engelsk hvis den ikke er oversatt
  2. i18n: RTL-layout — naviger til /ar/blog og /ar/blog/[slug], verifiser at dir="rtl" er satt og at layouten rendres korrekt (ToC på riktig side)
  3. SEO: metatagger — detaljsiden for innlegg har og:type=article, og:title, og:description, article:published_time og kanonisk lenke
  4. SEO: JSON-LD — detaljsiden for innlegg inneholder en <script type="application/ld+json"> med @type: BlogPosting, overskrift, forfatter, datePublished
  5. SEO: sitemap/sitemap.xml inkluderer URL-er til blogginnlegg med hreflang-alternativer
  6. Tilgjengelighet — kjør Axe-audits på /blog, /blog/[slug], /blog/author/[slug] både på mobil- og desktop-visningsflater (følger eksisterende a11y-testmønster)
  7. Tastaturnavigasjon — ToC-oppføringer og pagineringsknapper kan fokus­eres og aktiveres via tastatur; fokusmarkeringer er synlige

Utenfor omfang

  • Kommentarer på blogginnlegg
  • Fulltekstsøk
  • Integrasjon av nyhetsbrev i innlegg
  • Analyse/visningsstatistikk
  • Egendefinerte innleggsmaler per leietaker
Ludo Fourrage
Ludo Fourrage

Ludo er lærer og gründer innen teknologi, drevet av en enkel tro: utdanning av høy kvalitet skal være tilgjengelig for alle.