diff --git a/apps/blog/src/components/PostCard.astro b/apps/blog/src/components/PostCard.astro index ee1a6bb..090d7e9 100644 --- a/apps/blog/src/components/PostCard.astro +++ b/apps/blog/src/components/PostCard.astro @@ -12,102 +12,50 @@ interface Props { locale?: string readingTime: number author?: Author + featured?: boolean class?: string } -const { title, description, date, tags, cover, href, locale, readingTime, author, class: className } = Astro.props +const { title, description, date, tags, cover, href, locale, author, featured = false, class: className } = Astro.props +const category = tags[0] --- -
- -
-
- -
- {cover ? ( - {title} - ) : ( -
- )} -
- -
-
- {tags.slice(0, 3).map((tag) => ( - - {tag} - - ))} - + - - - - diff --git a/apps/blog/src/components/TagFilter.tsx b/apps/blog/src/components/TagFilter.tsx index 386aa2b..2b540d1 100644 --- a/apps/blog/src/components/TagFilter.tsx +++ b/apps/blog/src/components/TagFilter.tsx @@ -3,19 +3,11 @@ import { useTranslations } from '../i18n/utils'; interface TagFilterProps { tags: { name: string; count: number }[] + totalCount: number initialTags?: string[] locale?: string } -function TagIcon({ className }: { className?: string }) { - return ( - - - - - ) -} - function SearchIcon({ className }: { className?: string }) { return ( @@ -41,7 +33,7 @@ function writeURL(selectedTags: string[], query: string) { window.history.replaceState(null, '', url) } -export function TagFilter({ tags, initialTags = [], locale = 'en' }: TagFilterProps) { +export function TagFilter({ tags, totalCount, initialTags = [], locale = 'en' }: TagFilterProps) { const t = useTranslations(locale) const [selectedTags, setSelectedTags] = useState(initialTags) const [query, setQuery] = useState('') @@ -88,38 +80,43 @@ export function TagFilter({ tags, initialTags = [], locale = 'en' }: TagFilterPr return ( <> -
-
+
+
+ {t('index.filterLabel')} + {totalCount} {t('index.articleCount')} +
+ {tags.map((tag) => { + const active = selectedTags.includes(tag.name) + return ( + + ) + })} +
+
+ +
setQuery(e.target.value)} placeholder={t('tagFilter.placeholder')} - className="w-full rounded-md border border-border bg-transparent pl-10 pr-4 py-2 max-w-sm text-sm text-foreground placeholder:text-muted-foreground outline-none transition-colors focus:border-primary/50" + className="w-full lg:w-64 rounded-md border border-border bg-transparent pl-10 pr-4 py-2 text-sm text-foreground placeholder:text-muted-foreground outline-none transition-colors focus:border-primary/50" />
- -
- {tags.map((tag) => { - const active = selectedTags.includes(tag.name) - return ( - - ) - })} -
{hasActiveFilter && visibleCount === 0 && ( diff --git a/apps/blog/src/i18n/ui.ts b/apps/blog/src/i18n/ui.ts index 6b95da4..b89b743 100644 --- a/apps/blog/src/i18n/ui.ts +++ b/apps/blog/src/i18n/ui.ts @@ -4,10 +4,13 @@ export const ui = { en: { // Index page 'index.title': 'Articles', - 'index.heading.prefix': 'Latest', - 'index.heading.highlight': 'articles', + 'index.label': 'Blog', + 'index.heading.prefix': 'Latest updates from', + 'index.heading.highlight': 'FerrisKey.', 'index.empty': 'No articles yet.', 'index.noResults': 'No articles match your search.', + 'index.filterLabel': 'Filter by category', + 'index.articleCount': 'articles', // RSS 'rss.title': 'Explainer Blog', @@ -49,10 +52,13 @@ export const ui = { fr: { // Index page 'index.title': 'Articles', - 'index.heading.prefix': 'Derniers', - 'index.heading.highlight': 'articles', + 'index.label': 'Blog', + 'index.heading.prefix': 'Les dernières nouvelles de', + 'index.heading.highlight': 'FerrisKey.', 'index.empty': 'Aucun article pour le moment.', 'index.noResults': 'Aucun article ne correspond à votre recherche.', + 'index.filterLabel': 'Filtrer par catégorie', + 'index.articleCount': 'articles', // RSS 'rss.title': 'Blog Explainer', diff --git a/apps/blog/src/pages/index.astro b/apps/blog/src/pages/index.astro index c74ff6d..e4dfcf6 100644 --- a/apps/blog/src/pages/index.astro +++ b/apps/blog/src/pages/index.astro @@ -3,7 +3,7 @@ import { getCollection } from 'astro:content' import Base from '../layouts/base.astro' import { TagFilter } from '../components/TagFilter' import PostCard from '../components/PostCard.astro' -import { getPublishedPosts, getPostHref, getPostLocale, getLocales, getAllTags, getReadingTime } from '../lib/posts' +import { getPublishedPosts, getPostHref, getPostLocale, getPostsByLocale, getLocales, getAllTags, getReadingTime, getFeaturedPosts, getNonFeaturedPosts } from '../lib/posts' import { getAuthor } from '../lib/authors' import { defaultLang } from '../i18n/ui' import { useTranslations } from '../i18n/utils' @@ -14,35 +14,73 @@ const posts = getPublishedPosts(allPosts) const tags = getAllTags(posts) const locale = defaultLang const t = useTranslations(locale) + +// Split into featured/rest per locale, not across the mixed-locale array — +// otherwise an EN and FR copy of the same post can both land in the 2 +// featured slots, and hiding the wrong-locale one leaves an empty grid gap. +const postsByLocale = locales.map((loc) => { + const localePosts = getPostsByLocale(posts, loc) + return { + loc, + featured: getFeaturedPosts(localePosts, 2), + rest: getNonFeaturedPosts(localePosts, 2), + } +}) + +function cardProps(post: (typeof posts)[number]) { + return { + title: post.data.title, + description: post.data.short_description ?? post.data.description, + date: post.data.date, + tags: post.data.tags, + cover: post.data.cover ?? `${getPostHref(post)}/thumbnail.png`, + href: getPostHref(post), + locale, + readingTime: getReadingTime(post.body ?? ''), + author: post.data.author ? getAuthor(post.data.author) : undefined, + } +} --- -
-

+
+

+ + {t('index.label')} +

+

{t('index.heading.prefix')} {t('index.heading.highlight')}

- + {posts.length > 0 && ( -
- {posts.map((post) => ( -
- +
+ {postsByLocale.map(({ loc, featured, rest }) => ( +
+ {featured.length > 0 && ( +
1 && 'lg:grid-cols-2']}> + {featured.map((post) => ( +
+ +
+ ))} +
+ )} + + {rest.length > 0 && ( +
+ {rest.map((post) => ( +
+ +
+ ))} +
+ )}
))}
diff --git a/apps/website/src/components/comparison-section.astro b/apps/website/src/components/comparison-section.astro index 79547f4..f96da84 100644 --- a/apps/website/src/components/comparison-section.astro +++ b/apps/website/src/components/comparison-section.astro @@ -87,25 +87,32 @@ const rows: Row[] = [ -
- Compare vs - {competitors.map((c, i) => ( - - ))} +
+ Compare vs +
+ {competitors.map((c, i) => ( + + ))} +
- +
+ + + + +
diff --git a/apps/website/src/components/core-team-section.astro b/apps/website/src/components/core-team-section.astro index 6494097..f294d30 100644 --- a/apps/website/src/components/core-team-section.astro +++ b/apps/website/src/components/core-team-section.astro @@ -51,7 +51,7 @@ const team = [ -
+ -

+

A Modern IAM Built for Distributed Systems @@ -70,7 +70,7 @@ import { Button } from "@explainer/ui"; rel="noopener noreferrer" > Getting Started -