From 768ba0ec7ebd4520ad9b729b3c4b1cf58060d0ce Mon Sep 17 00:00:00 2001 From: autoblog Date: Fri, 3 Jul 2026 00:36:36 +0000 Subject: [PATCH] feat(content): fetch published posts from Supabase per site --- Template-01/src/data/articles.ts | 68 +++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/Template-01/src/data/articles.ts b/Template-01/src/data/articles.ts index 2212d40..5b0bd78 100644 --- a/Template-01/src/data/articles.ts +++ b/Template-01/src/data/articles.ts @@ -1,6 +1,6 @@ import { Article } from '../types'; -export const articles: Article[] = [ +const FALLBACK_ARTICLES: Article[] = [ { id: '1', slug: 'o-impacto-da-ia-generativa-na-busca-organica-2026', @@ -652,3 +652,69 @@ Search Generative Experience (SGE) provides direct answers at the top of the SER } ]; +// Array real, consumido por Home/BlogPost/CategoryPage. Começa com o conteúdo +// de demonstração e é substituído no lugar (mesma referência) assim que +// loadArticles() resolve, antes do React montar (ver main.tsx). +export const articles: Article[] = [...FALLBACK_ARTICLES]; + +const SUPABASE_URL = 'https://ccfezpxxmwpngqhlsbxz.supabase.co'; +const SUPABASE_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNjZmV6cHh4bXdwbmdxaGxzYnh6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzU2ODk4NTcsImV4cCI6MjA5MTI2NTg1N30.TqXoUsunJoX9xQwOOq3PTugltyrMGn1OrZysO6C9hRM'; + +function mapPostToArticle(post: any): Article { + return { + id: post.id, + slug: post.slug, + title: post.title, + excerpt: post.excerpt || '', + content: post.content || '', + category: post.category || 'Geral', + author: { + name: post.author_name || 'Equipe Editorial', + role: post.author_role || 'Redação', + avatar: post.author_avatar || 'https://i.pravatar.cc/150?u=' + post.id + }, + publishedAt: post.published_at || post.created_at, + image: post.image || 'https://images.unsplash.com/photo-1499750310107-5fef28a66643?auto=format&fit=crop&q=80&w=1600', + readTime: post.read_time || '5 min', + metaTitle: post.meta_title || post.title, + metaDescription: post.meta_description || post.excerpt || '', + tags: post.tags || [], + lang: post.lang || 'pt-br' + }; +} + +// Busca os posts publicados deste site específico (identificado pelo próprio +// hostname, igual o ThemeListener já faz pra aparência) e troca o conteúdo +// do array `articles` no lugar. Se der erro ou não houver post publicado, +// mantém o conteúdo de demonstração (FALLBACK_ARTICLES). +export async function loadArticles(): Promise { + try { + const host = window.location.hostname; + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 4000); + + const res = await fetch( + `${SUPABASE_URL}/rest/v1/sites?custom_domain=ilike.*${host}*&select=id,posts(*)&posts.status=eq.published`, + { + headers: { apikey: SUPABASE_KEY, Authorization: `Bearer ${SUPABASE_KEY}` }, + signal: controller.signal + } + ); + clearTimeout(timeout); + + if (!res.ok) return; + + const data = await res.json(); + const posts = data?.[0]?.posts; + + if (Array.isArray(posts) && posts.length > 0) { + const mapped = posts.map(mapPostToArticle); + articles.length = 0; + articles.push(...mapped); + } + } catch (err) { + console.error('[loadArticles] Falling back to demo content:', err); + } +} + +