From f1418fe25b38d599d9d39b5f3c80d880cced30c0 Mon Sep 17 00:00:00 2001 From: Matheo Guilbert Date: Fri, 17 Apr 2026 12:05:36 +0200 Subject: [PATCH] blog article summary --- app/[locale]/blog/[slug]/page.tsx | 4 ++ components/sections/ArticleSummary.tsx | 54 ++++++++++++++++++++++++++ content/blog/en/template.mdx | 5 +++ content/blog/fr/template.mdx | 5 +++ messages/en.json | 5 ++- messages/fr.json | 5 ++- 6 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 components/sections/ArticleSummary.tsx diff --git a/app/[locale]/blog/[slug]/page.tsx b/app/[locale]/blog/[slug]/page.tsx index d9b08dc..98a571a 100644 --- a/app/[locale]/blog/[slug]/page.tsx +++ b/app/[locale]/blog/[slug]/page.tsx @@ -2,6 +2,7 @@ import { notFound } from "next/navigation"; import { MDXRemote } from "next-mdx-remote/rsc"; import { getArticleBySlug, getArticleSlugs } from "@/lib/blog/get-articles"; import { ArticleHero } from "@/components/sections/ArticleHero"; +import { ArticleSummary } from "@/components/sections/ArticleSummary"; import { locales } from "@/middleware"; type props = { @@ -43,6 +44,9 @@ export default async function ArticlePage({ params }: props) { cover={article.cover} />
+ {article.summary && article.summary.length > 0 && ( + + )} {article.tags.length > 0 && (
{article.tags.map((tag) => ( diff --git a/components/sections/ArticleSummary.tsx b/components/sections/ArticleSummary.tsx new file mode 100644 index 0000000..6f3a3e4 --- /dev/null +++ b/components/sections/ArticleSummary.tsx @@ -0,0 +1,54 @@ +'use client'; + +import { useRef, useEffect } from 'react'; +import { useTranslations } from 'next-intl'; + +type props = { + items: string[]; +}; + +export function ArticleSummary({ items }: props) { + const ref = useRef(null); + const t = useTranslations('blogPage'); + + useEffect(() => { + const el = ref.current; + if (!el) return; + const observer = new IntersectionObserver( + ([entry]) => { + if (entry.isIntersecting) { + el.querySelectorAll('.reveal').forEach((node, i) => { + setTimeout(() => node.classList.add('visible'), i * 80); + }); + observer.unobserve(el); + } + }, + { threshold: 0.1 } + ); + observer.observe(el); + return () => observer.disconnect(); + }, []); + + return ( +
+
+ + + {t('summary.label')} + +
+
    + {items.map((item, i) => ( +
  1. + + {String(i + 1).padStart(2, '0')} + + + {item} + +
  2. + ))} +
+
+ ); +} diff --git a/content/blog/en/template.mdx b/content/blog/en/template.mdx index a63ee17..3c55b40 100644 --- a/content/blog/en/template.mdx +++ b/content/blog/en/template.mdx @@ -10,6 +10,11 @@ tags: - "Scalability" - "Cloud" readTime: "8 min" +summary: + - "Good architecture starts with understanding the real constraints of the system, not by picking a technology." + - "A monolith is often the best starting point; microservices are justified by organizational maturity, not project size." + - "Scalability must be designed upfront: stateless services, event-driven decoupling, multi-level caching." + - "Technical debt is inevitable, but it must be actively managed to avoid paralyzing the product in the medium term." ---
diff --git a/content/blog/fr/template.mdx b/content/blog/fr/template.mdx index 83f8172..f8d3c4e 100644 --- a/content/blog/fr/template.mdx +++ b/content/blog/fr/template.mdx @@ -10,6 +10,11 @@ tags: - "Scalabilité" - "Cloud" readTime: "8 min" +summary: + - "Poser les bonnes fondations" + - "Monolithe ou microservices ?" + - "La scalabilité, une propriété à concevoir dès le départ" + - "La dette technique : l'ennemi silencieux" ---
diff --git a/messages/en.json b/messages/en.json index 8f25925..435568d 100644 --- a/messages/en.json +++ b/messages/en.json @@ -68,7 +68,10 @@ "backToBlog": "Back to blog", "scrollPrompt": "Scroll", "readArticle": "Read article", - "noArticles": "No articles yet." + "noArticles": "No articles yet.", + "summary": { + "label": "Summary" + } }, "projectPage": { "hero": { diff --git a/messages/fr.json b/messages/fr.json index c2520ca..1d80cc1 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -68,7 +68,10 @@ "backToBlog": "Retour au blog", "scrollPrompt": "Défiler", "readArticle": "Lire l'article", - "noArticles": "Aucun article pour le moment." + "noArticles": "Aucun article pour le moment.", + "summary": { + "label": "En résumé" + } }, "projectPage": { "hero": {