Publisert tittel, ingress, OG-bilde og undertittel er nå egne noder koblet til artikler via title/subtitle/summary/og_image-edges. Rendering bruker presentasjonselementer med fallback til artikkelfelt. Backend: - Ny query: GET /query/presentation_elements?article_id=... - render_article_to_cas henter presentasjonselementer via edges - fetch_article + fetch_index_articles bruker pres.elementer - Batch-henting for forsideartikler (én SQL-spørring) - ArticleData utvides med subtitle + og_image - Alle fire temaer viser subtitle og OG-bilde - SEO og_image-tag fylles fra presentasjonselement Frontend: - PresentationEditor.svelte: opprett/rediger tittel, undertittel, ingress, OG-bilde med variantvelger (editorial/ai/social/rss) - Integrert i PublishDialog via <details>-seksjon - API-klient: fetchPresentationElements(), deleteNode() Grunnlag for A/B-testing (oppgave 14.17): edge-metadata støtter ab_status/impressions/clicks/ctr, best_of() prioriterer winner > testing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
75 lines
2.5 KiB
HTML
75 lines
2.5 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}{{ article.title }} — {{ collection_title }}{% endblock %}
|
|
|
|
{% block seo %}
|
|
<meta name="description" content="{{ seo.description }}">
|
|
<link rel="canonical" href="{{ seo.canonical_url }}">
|
|
<meta property="og:type" content="article">
|
|
<meta property="og:title" content="{{ seo.og_title }}">
|
|
<meta property="og:description" content="{{ seo.description }}">
|
|
<meta property="og:url" content="{{ seo.canonical_url }}">
|
|
<meta property="og:site_name" content="{{ collection_title }}">
|
|
{% if seo.og_image %}<meta property="og:image" content="{{ seo.og_image }}">{% endif %}
|
|
<meta property="article:published_time" content="{{ article.published_at }}">
|
|
<link rel="alternate" type="application/atom+xml" title="{{ collection_title }} — RSS" href="{{ base_url }}/feed.xml">
|
|
<script type="application/ld+json">{{ seo.json_ld | safe }}</script>
|
|
{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
.mag-article {
|
|
max-width: var(--layout-max-width);
|
|
margin: 0 auto;
|
|
padding: 0 1rem;
|
|
}
|
|
.mag-article__header {
|
|
text-align: center;
|
|
padding: 3rem 0 2rem;
|
|
max-width: 720px;
|
|
margin: 0 auto;
|
|
}
|
|
.mag-article__title {
|
|
font-family: var(--font-heading);
|
|
font-size: 3rem;
|
|
line-height: 1.1;
|
|
color: var(--color-primary);
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
.mag-article__meta {
|
|
color: var(--color-muted);
|
|
font-size: 0.9rem;
|
|
}
|
|
.mag-article__content {
|
|
max-width: 680px;
|
|
margin: 0 auto;
|
|
font-size: 1.1rem;
|
|
line-height: 1.8;
|
|
padding-bottom: 3rem;
|
|
}
|
|
.mag-article__content p { margin-bottom: 1.25em; }
|
|
.mag-article__back {
|
|
display: inline-block;
|
|
margin-top: 2rem;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.mag-article__title { font-size: 2rem; }
|
|
.mag-article__header { padding: 2rem 0 1.5rem; }
|
|
}
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<article class="mag-article">
|
|
{% if article.og_image %}<img src="/cas/{{ article.og_image }}" alt="{{ article.title }}" style="width:100%;max-height:500px;object-fit:cover;margin-bottom:0;">{% endif %}
|
|
<header class="mag-article__header">
|
|
<h1 class="mag-article__title">{{ article.title }}</h1>
|
|
{% if article.subtitle %}<p style="font-size:1.25rem;color:var(--color-muted);margin-top:0.5rem;font-family:var(--font-heading);">{{ article.subtitle }}</p>{% endif %}
|
|
<div class="mag-article__meta">Publisert {{ article.published_at_short }}</div>
|
|
</header>
|
|
<div class="mag-article__content">
|
|
{{ article.content | safe }}
|
|
<a class="mag-article__back" href="{{ base_url }}">← Tilbake</a>
|
|
</div>
|
|
</article>
|
|
{% endblock %}
|