feat(content): fetch published posts from Supabase per site

This commit is contained in:
autoblog 2026-07-03 00:36:36 +00:00
parent 41e438be13
commit 768ba0ec7e

View file

@ -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<void> {
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);
}
}