@toobstudio/blog
v0.2.1
Published
SDK para consumir a API de blog do TOOB
Downloads
488
Readme
@toobstudio/blog
SDK oficial para consumir a API de blog do TOOB.
Instalação
npm install @toobstudio/blogConfiguração
Defina as variáveis de ambiente no seu projeto:
TOOB_API_KEY=sua_chave_aqui
TOOB_PROJECT_ID=seu_project_idVocê encontra essas informações no painel do TOOB, na seção Conexão API.
Uso
Inicialização
import { ToobBlog } from "@toobstudio/blog";
// Lê TOOB_API_KEY e TOOB_PROJECT_ID das variáveis de ambiente
const blog = new ToobBlog();
// Ou com configuração explícita
const blog = new ToobBlog({
apiKey: "toob_xxx",
projectId: "abc123",
});Listar posts
const { posts, total, page, totalPages } = await blog.getPosts({
page: 1, // padrão: 1
limit: 12, // padrão: 12, máximo: 50
tag: "tech", // opcional: filtrar por tag
});Buscar post por slug
const post = await blog.getPost("meu-post-slug");
// Retorna null se o post não existirExemplo com Next.js App Router
// app/blog/page.tsx
import { ToobBlog } from "@toobstudio/blog";
const blog = new ToobBlog();
export default async function BlogPage() {
const { posts } = await blog.getPosts();
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}// app/blog/[slug]/page.tsx
import { ToobBlog } from "@toobstudio/blog";
import { notFound } from "next/navigation";
const blog = new ToobBlog();
export default async function PostPage({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const post = await blog.getPost(slug);
if (!post) notFound();
return (
<article>
<h1>{post.title}</h1>
<article className="toob-blog-content" dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}Estilos para o conteúdo do post
O conteúdo dos posts (post.content) é HTML gerado pelo editor TipTap. O SDK inclui um CSS pronto para estilizar esse conteúdo.
Importando o CSS
// No layout.tsx, _app.tsx ou arquivo global
import "@toobstudio/blog/styles.css";Usando no HTML do post
Envolva o conteúdo do post com a classe toob-blog-content:
<article
className="toob-blog-content"
dangerouslySetInnerHTML={{ __html: post.content }}
/>Customizando cores
O CSS usa CSS custom properties com valores padrão. Sobrescreva no seu CSS para adaptar ao seu tema:
.toob-blog-content {
--toob-text: #1a1a1a;
--toob-text-muted: #6b7280;
--toob-bg: #ffffff;
--toob-bg-muted: #f5f5f5;
--toob-border: #e5e5e5;
--toob-link: #f97316;
--toob-link-hover: #ea580c;
--toob-font-body: system-ui, -apple-system, sans-serif;
--toob-font-display: system-ui, -apple-system, sans-serif;
--toob-font-mono: ui-monospace, "SFMono-Regular", Menlo, monospace;
}Sobre cache
O cache dos posts é gerenciado inteiramente no servidor do TOOB. Quando um post é criado, editado ou deletado no painel, o cache é invalidado automaticamente. Não é necessário implementar nenhuma estratégia de cache no lado do cliente — cada request bate no servidor TOOB que já serve do cache interno.
Referência da API
new ToobBlog(config?)
| Parâmetro | Tipo | Descrição |
| -------------------- | -------- | ---------------------------------- |
| config.apiKey | string | Chave da API (ou env TOOB_API_KEY) |
| config.projectId | string | ID do projeto (ou env TOOB_PROJECT_ID) |
blog.getPosts(options?)
Retorna Promise<BlogPostList>.
| Opção | Tipo | Padrão | Descrição |
| ------- | -------- | ------ | -------------------- |
| page | number | 1 | Página |
| limit | number | 12 | Itens por página (máx 50) |
| tag | string | — | Filtrar por tag |
blog.getPost(slug)
Retorna Promise<BlogPost | null>. Retorna null se o post não for encontrado.
Tipos exportados
import type {
BlogPost,
BlogPostList,
BlogPostListItem,
GetPostsOptions,
ToobBlogConfig,
} from "@toobstudio/blog";Implementação com IA (Claude Code / Codex / Cursor)
Copie o prompt abaixo e cole no seu assistente de IA para implementar o blog automaticamente no seu projeto:
Implemente um blog completo no meu projeto usando o SDK @toobstudio/blog.
## Passo 1: Instalação
Instale o pacote:
npm install @toobstudio/blog
## Passo 2: Variáveis de ambiente
Adicione no .env (ou .env.local se for Next.js):
TOOB_API_KEY=<minha_chave>
TOOB_PROJECT_ID=<meu_project_id>
## Passo 3: Criar as páginas
### Página de listagem de posts (/blog)
- Use `ToobBlog` do `@toobstudio/blog`
- Instancie `const blog = new ToobBlog()` (lê as envs automaticamente)
- Chame `blog.getPosts({ page, limit: 12 })` para listar posts
- Renderize cards com: título, excerpt, coverImage, tags, publishedAt, authorName
- Implemente paginação usando `total`, `page` e `totalPages` da resposta
- Suporte filtro por tag via query string (ex: /blog?tag=tech)
- Use os dados de SEO do post (`post.seo.metaTitle`, `post.seo.metaDescription`) para gerar metadata da página
### Página individual do post (/blog/[slug])
- Chame `blog.getPost(slug)` para buscar o post
- Se retornar `null`, mostre 404 (no Next.js use `notFound()`)
- Renderize: título, coverImage, content (é HTML, use dangerouslySetInnerHTML ou equivalente), tags, authorName, publishedAt
- Use `post.seo` para gerar metadata/og tags da página
- Se `post.structuredData` existir, injete como JSON-LD no <head>
- Se `post.geo` existir:
- Renderize `geo.faq` como seção de FAQ (accordion ou lista)
- Renderize `geo.keyTakeaways` como lista de pontos-chave
- Use `geo.aiSummary` como resumo no topo do post se disponível
## Tipos disponíveis no SDK (para referência)
interface BlogPostListItem {
id: string;
title: string;
slug: string;
excerpt: string;
coverImage: string | null;
tags: string[];
authorName: string;
publishedAt: string | null;
createdAt: string;
seo: {
metaTitle: string | null;
metaDescription: string | null;
ogImageUrl: string | null;
} | null;
geo: {
aiSummary: string | null;
faq: Array<{ question: string; answer: string }>;
keyTakeaways: string[];
topicCategory: string | null;
contentType: string | null;
entities: string[];
} | null;
}
interface BlogPost extends BlogPostListItem {
content: string; // HTML
structuredData: unknown | null; // JSON-LD
}
interface BlogPostList {
posts: BlogPostListItem[];
total: number;
page: number;
totalPages: number;
}
## Passo 4: Estilos do conteúdo
- Importe o CSS do SDK no layout ou arquivo global: `import "@toobstudio/blog/styles.css";`
- Envolva o `post.content` com a classe `toob-blog-content`:
`<article className="toob-blog-content" dangerouslySetInnerHTML={{ __html: post.content }} />`
- O CSS já estiliza headings, listas, code blocks, blockquotes, tabelas, imagens, task lists, etc.
- Para customizar cores, sobrescreva as CSS variables (--toob-text, --toob-link, --toob-border, etc.) no CSS do projeto
## Regras importantes
- NÃO implemente cache — o servidor TOOB gerencia todo o cache
- NÃO use `next: { revalidate }` nem nenhuma estratégia de cache
- Cada chamada do SDK = 1 fetch direto para a API
- Use o sistema de estilização que já existe no projeto (Tailwind, CSS Modules, etc) para os COMPONENTES (cards, layout, paginação), mas use a classe `toob-blog-content` com o CSS do SDK para o conteúdo HTML do post
- Siga os padrões e convenções já existentes no projeto
- Adapte a estrutura de pastas ao framework usado (Next.js App Router, Pages Router, Astro, etc)
- Trate erros: importe `ToobAuthError` e `ToobRateLimitError` de `@toobstudio/blog` para erros específicosTratamento de erros
| Classe | Status | Mensagem |
| ------------------- | ------ | ----------------------------------------------------------- |
| ToobAuthError | 401 | API Key inválida. Verifique a variável TOOB_API_KEY. |
| ToobRateLimitError| 429 | Limite de requisições excedido. Tente novamente em instantes.|
| ToobApiError | outros | Erro na API TOOB: {status} {statusText} |
import { ToobAuthError, ToobRateLimitError, ToobApiError } from "@toobstudio/blog";
try {
const posts = await blog.getPosts();
} catch (error) {
if (error instanceof ToobAuthError) {
// API key inválida
}
}