feat: add ESP-RainMaker and ESP-Matter frameworks and update existing framework metadata in frameworks.json

This commit is contained in:
Lucas Rayan committed 2026-08-25 16:55:38 -03:00
1 parent 07dac4f6de
commit d71dc8df3c
19 files changed
+2458 -282

No files matched your search

+74
View File
@@ -0,0 +1,74 @@
import { paginaMeta, jsonLd } from "@/lib/seo";
export const metadata = paginaMeta({
titulo: "ESP Component Registry & IDF Component Manager · ESPDocs",
descricao: "Catálogo oficial e interativo do ESP Component Registry: drivers de displays, LVGL, reconhecimento de voz ESP-SR, RainMaker, BSPs e gerador de idf_component.yml.",
caminho: "/componentes",
keywords: [
"ESP Component Registry",
"IDF Component Manager",
"idf_component.yml",
"idf.py add-dependency",
"componentes ESP32",
"espressif esp_lvgl_port",
"espressif esp_rainmaker",
"espressif esp-sr",
"bibliotecas ESP-IDF",
],
});
const faqs = [
{
pergunta: "O que é o ESP Component Registry e o IDF Component Manager?",
resposta: "O ESP Component Registry (components.espressif.com) é o repositório oficial de pacotes modulares da Espressif. O IDF Component Manager é a ferramenta integrada ao ESP-IDF (a partir do v4.4 e padrão no v5.x+) que baixa, compila e resolve versões de dependências automaticamente a partir do manifesto idf_component.yml.",
},
{
pergunta: "Como adicionar um componente ao meu projeto ESP-IDF?",
resposta: "Você pode executar o comando 'idf.py add-dependency \"namespace/componente^versao\"' no terminal do projeto (por exemplo: idf.py add-dependency \"espressif/esp_lvgl_port^2.4.0\") ou editar diretamente o arquivo main/idf_component.yml.",
},
{
pergunta: "Qual a diferença entre usar o Component Registry e git submodules?",
resposta: "O Component Registry elimina a complexidade de gerenciar submódulos Git pesados e versões manuais. Ele oferece versionamento semântico (^ e ~), resolução automática de dependências transitivas e compilação modular sob demanda.",
},
{
pergunta: "Posso criar e publicar meus próprios componentes?",
resposta: "Sim, qualquer desenvolvedor ou empresa pode publicar componentes públicos ou privados no ESP Component Registry utilizando a ferramenta oficial Compote CLI (pip install idf-component-manager).",
},
];
export default function ComponentesLayout({ children }) {
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(
jsonLd.trilha([
{ nome: "Início", caminho: "/" },
{ nome: "ESP Component Registry", caminho: "/componentes" },
])
),
}}
/>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(jsonLd.perguntas(faqs)),
}}
/>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(
jsonLd.aplicacaoWeb({
nome: "Hub do ESP Component Registry & Construtor de Manifesto",
descricao: "Catálogo curado e gerador de manifesto idf_component.yml para componentes modulares do ESP-IDF.",
caminho: "/componentes",
})
),
}}
/>
{children}
</>
);
}
+644
View File
@@ -0,0 +1,644 @@
"use client";
import { useState, useMemo } from "react";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
import Link from "next/link";
import {
CATEGORIAS_COMPONENTES,
COMPONENTES_REGISTRY,
GUIA_COMPONENT_MANAGER
} from "@/lib/componentRegistryData";
import {
Layers,
Search,
Copy,
Check,
ExternalLink,
Sparkles,
Terminal,
Code2,
Plus,
Trash2,
Download,
Cpu,
Box,
CheckCircle2,
ChevronRight,
HelpCircle,
ArrowRight,
BookOpen,
ShieldCheck,
Zap,
Monitor,
Cloud,
Brain,
Home,
CircuitBoard,
Wrench
} from "lucide-react";
export default function ComponentRegistryPage() {
const [busca, setBusca] = useState("");
const [categoriaAtiva, setCategoriaAtiva] = useState("todos");
const [chipFiltro, setChipFiltro] = useState("todos");
const [copiadoId, setCopiadoId] = useState(null);
const [manifestoCopiado, setManifestoCopiado] = useState(false);
// Componentes selecionados no construtor de idf_component.yml
const [componentesSelecionados, setComponentesSelecionados] = useState([
"espressif-esp_lvgl_port",
"espressif-led_indicator"
]);
// Lista de chips únicos para filtro
const chipsDisponiveis = ["todos", "ESP32", "ESP32-S3", "ESP32-C6", "ESP32-P4", "ESP32-H2", "ESP32-C3"];
// Filtragem dos componentes
const componentesFiltrados = useMemo(() => {
return COMPONENTES_REGISTRY.filter((comp) => {
const matchCategoria = categoriaAtiva === "todos" || comp.categoria === categoriaAtiva;
const matchChip = chipFiltro === "todos" || (comp.chips && comp.chips.includes(chipFiltro));
const matchBusca =
busca.trim() === "" ||
comp.name.toLowerCase().includes(busca.toLowerCase()) ||
comp.namespace.toLowerCase().includes(busca.toLowerCase()) ||
comp.titulo.toLowerCase().includes(busca.toLowerCase()) ||
comp.descricao.toLowerCase().includes(busca.toLowerCase()) ||
comp.tags.some((t) => t.toLowerCase().includes(busca.toLowerCase()));
return matchCategoria && matchChip && matchBusca;
});
}, [busca, categoriaAtiva, chipFiltro]);
// Manipuladores de cópia
const copiarComando = (id, comando) => {
navigator.clipboard.writeText(comando);
setCopiadoId(id);
setTimeout(() => setCopiadoId(null), 2000);
};
const toggleSelecaoManifesto = (id) => {
setComponentesSelecionados((prev) =>
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]
);
};
// Geração dinâmica do manifesto YAML
const manifestoYaml = useMemo(() => {
const selecionados = COMPONENTES_REGISTRY.filter((c) =>
componentesSelecionados.includes(c.id)
);
if (selecionados.length === 0) {
return `# Nenhum componente selecionado.\n# Clique em "+ Adicionar ao Manifesto" nos cards abaixo.`;
}
let yaml = `# main/idf_component.yml\n# Gerado via ESPDocs Component Hub (https://espdocs.cienciaembarcada.com.br/componentes)\n\ndependencies:\n`;
selecionados.forEach((c) => {
yaml += ` ${c.namespace}/${c.name}: "${c.versao}"\n`;
});
return yaml;
}, [componentesSelecionados]);
const copiarManifesto = () => {
navigator.clipboard.writeText(manifestoYaml);
setManifestoCopiado(true);
setTimeout(() => setManifestoCopiado(false), 2000);
};
const baixarManifesto = () => {
const blob = new Blob([manifestoYaml], { type: "text/yaml;charset=utf-8" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "idf_component.yml";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
};
// Mapeamento de ícones de categoria
const renderIconeCategoria = (id) => {
switch (id) {
case "ui_display":
return <Monitor className="w-4 h-4" />;
case "cloud_conectividade":
return <Cloud className="w-4 h-4" />;
case "audio_voz_ia":
return <Brain className="w-4 h-4" />;
case "smart_home_mesh":
return <Home className="w-4 h-4" />;
case "drivers_perifericos":
return <Cpu className="w-4 h-4" />;
case "bsp_placas":
return <CircuitBoard className="w-4 h-4" />;
case "sistema_utilitarios":
return <Wrench className="w-4 h-4" />;
default:
return <Layers className="w-4 h-4" />;
}
};
return (
<div className="bg-gradient-to-br from-slate-100 via-slate-50 to-purple-100/40 dark:from-slate-950 dark:via-slate-950 dark:to-slate-900 min-h-screen text-slate-900 dark:text-slate-100 transition-colors duration-300">
<Header />
<main id="conteudo" className="px-4 md:px-6 pt-12 md:pt-16 pb-24 max-w-7xl mx-auto space-y-12">
{/* Top Hero Section */}
<section className="text-center select-none relative">
<div className="inline-flex items-center gap-2 bg-white/80 dark:bg-slate-900/60 backdrop-blur-md px-4 py-2 rounded-full mb-6 border border-slate-300 dark:border-slate-800/80 shadow-xs">
<Box className="w-4 h-4 text-purple-500" />
<span className="text-xs font-bold text-slate-700 dark:text-slate-300 uppercase tracking-wider">
ESP-IDF Component Manager
</span>
<span className="bg-purple-100 dark:bg-purple-950/80 text-purple-700 dark:text-purple-300 text-[10px] font-extrabold px-2 py-0.5 rounded-full">
Oficial
</span>
</div>
<h1 className="text-4xl md:text-6xl font-display font-extrabold bg-gradient-to-r from-blue-600 via-purple-600 to-pink-600 dark:from-blue-400 dark:via-purple-400 dark:to-pink-400 bg-clip-text text-transparent mb-6 pb-2 pt-1 leading-tight md:leading-[1.18] tracking-tight">
ESP Component Registry
</h1>
<p className="text-sm md:text-base text-slate-600 dark:text-slate-350 max-w-3xl mx-auto leading-relaxed font-semibold">
O catálogo oficial de pacotes reutilizáveis da Espressif para o ESP-IDF.
Adicione drivers de displays, reconhecimento de voz, pilhas industriais e bibliotecas
com comandos de um clique e geração de manifesto declarativo.
</p>
<div className="flex flex-wrap items-center justify-center gap-3 mt-6">
<a
href="https://components.espressif.com"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-500 hover:to-indigo-500 text-white text-xs font-bold px-4 py-2.5 rounded-xl shadow-md transition-all active:scale-95"
>
<span>Acessar Registry Oficial</span>
<ExternalLink className="w-3.5 h-3.5" />
</a>
<a
href="#manifesto-builder"
className="inline-flex items-center gap-2 bg-white dark:bg-slate-900 border border-slate-300 dark:border-slate-800 text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800 text-xs font-bold px-4 py-2.5 rounded-xl shadow-xs transition-all active:scale-95"
>
<Code2 className="w-3.5 h-3.5 text-purple-500" />
<span>Gerador de idf_component.yml</span>
</a>
</div>
</section>
{/* Interactive Search & Filter Bar */}
<section className="bg-white dark:bg-slate-900/60 backdrop-blur-xl rounded-3xl p-6 border border-slate-300 dark:border-slate-800/80 shadow-xl space-y-5">
<div className="flex flex-col md:flex-row gap-4 items-center justify-between">
{/* Search Input */}
<div className="relative w-full md:flex-1">
<Search className="w-4 h-4 absolute left-3.5 top-1/2 -translate-y-1/2 text-slate-400" />
<input
type="text"
value={busca}
onChange={(e) => setBusca(e.target.value)}
placeholder="Buscar componentes por nome, namespace, funcionalidade ou tags (ex: lvgl, rainmaker, ws2812)..."
className="w-full pl-10 pr-4 py-2.5 bg-slate-50 dark:bg-slate-950/70 border border-slate-250 dark:border-slate-800 rounded-2xl text-xs md:text-sm font-semibold text-slate-800 dark:text-slate-100 placeholder:text-slate-400 focus:outline-hidden focus:ring-2 focus:ring-purple-500 transition-all"
/>
{busca && (
<button
onClick={() => setBusca("")}
className="absolute right-3 top-1/2 -translate-y-1/2 text-xs font-bold text-slate-400 hover:text-slate-600 dark:hover:text-slate-200"
>
Limpar
</button>
)}
</div>
{/* Chip Filter */}
<div className="flex items-center gap-1.5 w-full md:w-auto overflow-x-auto pb-1 md:pb-0">
<span className="text-[11px] font-bold text-slate-500 uppercase tracking-wider shrink-0 mr-1">
SoC:
</span>
{chipsDisponiveis.map((chip) => (
<button
key={chip}
onClick={() => setChipFiltro(chip)}
className={`px-3 py-1.5 rounded-xl text-xs font-bold shrink-0 transition-all cursor-pointer ${
chipFiltro === chip
? "bg-purple-600 text-white shadow-xs"
: "bg-slate-100 dark:bg-slate-800/80 text-slate-650 dark:text-slate-350 hover:bg-slate-200 dark:hover:bg-slate-700"
}`}
>
{chip === "todos" ? "Todos SoCs" : chip}
</button>
))}
</div>
</div>
{/* Category Tabs */}
<div className="flex items-center gap-2 overflow-x-auto pb-2 border-t border-slate-200 dark:border-slate-800/60 pt-4">
{CATEGORIAS_COMPONENTES.map((cat) => {
const ativa = categoriaAtiva === cat.id;
const contagem =
cat.id === "todos"
? COMPONENTES_REGISTRY.length
: COMPONENTES_REGISTRY.filter((c) => c.categoria === cat.id).length;
return (
<button
key={cat.id}
onClick={() => setCategoriaAtiva(cat.id)}
className={`inline-flex items-center gap-2 px-3.5 py-2 rounded-xl text-xs font-bold shrink-0 transition-all cursor-pointer ${
ativa
? "bg-purple-50 dark:bg-purple-950/60 text-purple-600 dark:text-purple-400 border border-purple-200 dark:border-purple-800/60 shadow-xs"
: "text-slate-600 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-slate-800/60"
}`}
>
{renderIconeCategoria(cat.id)}
<span>{cat.nome}</span>
<span
className={`text-[10px] px-1.5 py-0.2 rounded-full ${
ativa
? "bg-purple-200 dark:bg-purple-900 text-purple-800 dark:text-purple-200"
: "bg-slate-200 dark:bg-slate-800 text-slate-600 dark:text-slate-400"
}`}
>
{contagem}
</span>
</button>
);
})}
</div>
</section>
{/* Components Grid */}
<section className="space-y-4">
<div className="flex items-center justify-between">
<h2 className="text-lg font-display font-extrabold text-slate-850 dark:text-slate-100 flex items-center gap-2">
<Sparkles className="w-5 h-5 text-purple-500" />
<span>Componentes Disponíveis ({componentesFiltrados.length})</span>
</h2>
<span className="text-xs text-slate-500 font-semibold">
Clique em um comando para copiar para o terminal
</span>
</div>
{componentesFiltrados.length === 0 ? (
<div className="text-center py-16 bg-white dark:bg-slate-900/40 rounded-3xl border border-slate-300 dark:border-slate-800 p-8">
<Box className="w-12 h-12 text-slate-400 mx-auto mb-3 opacity-60" />
<p className="text-base font-bold text-slate-750 dark:text-slate-200">
Nenhum componente encontrado para esses filtros.
</p>
<p className="text-xs text-slate-500 mt-1">
Tente buscar por termos mais genéricos ou resetar a categoria.
</p>
<button
onClick={() => {
setBusca("");
setCategoriaAtiva("todos");
setChipFiltro("todos");
}}
className="mt-4 px-4 py-2 bg-purple-600 text-white rounded-xl text-xs font-bold"
>
Limpar Todos os Filtros
</button>
</div>
) : (
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{componentesFiltrados.map((comp) => {
const selecionado = componentesSelecionados.includes(comp.id);
const cliCmd = `idf.py add-dependency "${comp.namespace}/${comp.name}${comp.versao}"`;
const foiCopiado = copiadoId === comp.id;
return (
<div
key={comp.id}
className={`bg-white dark:bg-slate-900/45 backdrop-blur-xl border rounded-3xl shadow-lg hover:shadow-2xl transition-all duration-300 flex flex-col justify-between overflow-hidden relative group ${
selecionado
? "border-purple-500/80 ring-2 ring-purple-500/20"
: "border-slate-300 dark:border-slate-800/80 hover:-translate-y-1"
}`}
>
{/* Top Header Card */}
<div className="p-6 pb-4 border-b border-slate-150 dark:border-slate-850/40">
<div className="flex items-start justify-between gap-3 mb-2">
<div>
<div className="flex items-center gap-1.5 mb-1">
<span className="text-[10px] font-extrabold text-slate-400 uppercase tracking-wider">
{comp.namespace}/
</span>
{comp.oficial && (
<span className="inline-flex items-center gap-1 bg-emerald-100 dark:bg-emerald-950/60 text-emerald-700 dark:text-emerald-300 text-[9px] font-extrabold px-2 py-0.2 rounded-full border border-emerald-300 dark:border-emerald-800/60">
<ShieldCheck className="w-3 h-3" />
Oficial
</span>
)}
</div>
<h3 className="text-xl font-display font-extrabold text-slate-850 dark:text-slate-100 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors">
{comp.name}
</h3>
<p className="text-xs font-semibold text-purple-600 dark:text-purple-400">
{comp.titulo}
</p>
</div>
<span className="px-2.5 py-1 rounded-lg text-[10px] font-mono font-bold bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300 border border-slate-200 dark:border-slate-700 shrink-0">
{comp.versao}
</span>
</div>
<p className="text-xs text-slate-500 dark:text-slate-350 leading-relaxed mt-2.5 line-clamp-3">
{comp.descricao}
</p>
{/* Tags */}
<div className="flex flex-wrap gap-1.5 mt-3.5">
{comp.tags.map((tag) => (
<span
key={tag}
className="text-[9px] font-bold bg-slate-100 dark:bg-slate-950/60 text-slate-600 dark:text-slate-400 px-2 py-0.5 rounded-md border border-slate-250 dark:border-slate-800"
>
{tag}
</span>
))}
</div>
</div>
{/* Interactive CLI Action Box */}
<div className="p-6 py-4 bg-slate-50/50 dark:bg-slate-950/40 space-y-3">
<div>
<div className="flex items-center justify-between text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-1">
<span className="flex items-center gap-1">
<Terminal className="w-3 h-3 text-purple-500" />
Comando CLI
</span>
{foiCopiado && (
<span className="text-emerald-500 font-bold flex items-center gap-0.5">
<Check className="w-3 h-3" /> Copiado!
</span>
)}
</div>
<button
onClick={() => copiarComando(comp.id, cliCmd)}
className="w-full text-left bg-slate-900 text-slate-100 p-2.5 rounded-xl font-mono text-[11px] hover:bg-slate-800 border border-slate-800 flex items-center justify-between group/cmd transition-colors cursor-pointer"
title="Clique para copiar comando"
>
<span className="truncate pr-2">{cliCmd}</span>
<Copy className="w-3.5 h-3.5 text-slate-400 group-hover/cmd:text-white shrink-0" />
</button>
</div>
{/* Compatible Chips */}
<div>
<span className="text-[10px] font-bold text-slate-400 uppercase tracking-wider block mb-1">
SoCs Compatíveis:
</span>
<div className="flex flex-wrap gap-1">
{comp.chips.map((chip) => (
<span
key={chip}
className="text-[9px] font-semibold text-slate-650 dark:text-slate-350 bg-slate-200/60 dark:bg-slate-800 px-1.5 py-0.2 rounded"
>
{chip}
</span>
))}
</div>
</div>
</div>
{/* Bottom Actions */}
<div className="p-4 px-6 border-t border-slate-150 dark:border-slate-850/40 flex items-center justify-between text-xs font-bold">
<button
onClick={() => toggleSelecaoManifesto(comp.id)}
className={`inline-flex items-center gap-1.5 px-3 py-1.5 rounded-xl transition-all cursor-pointer ${
selecionado
? "bg-purple-600 text-white shadow-xs"
: "bg-purple-50 dark:bg-purple-950/40 text-purple-600 dark:text-purple-400 border border-purple-200 dark:border-purple-800/40 hover:bg-purple-100"
}`}
>
{selecionado ? (
<>
<CheckCircle2 className="w-3.5 h-3.5" />
<span>No Manifesto</span>
</>
) : (
<>
<Plus className="w-3.5 h-3.5" />
<span>Adicionar ao Manifesto</span>
</>
)}
</button>
<div className="flex items-center gap-2">
<a
href={comp.urlRegistry}
target="_blank"
rel="noopener noreferrer"
className="text-slate-400 hover:text-purple-600 dark:hover:text-purple-400 transition-colors p-1"
title="Ver página oficial no ESP Component Registry"
>
<ExternalLink className="w-4 h-4" />
</a>
</div>
</div>
</div>
);
})}
</div>
)}
</section>
{/* Interactive Manifest Builder Section */}
<section
id="manifesto-builder"
className="bg-white dark:bg-slate-900/60 backdrop-blur-xl rounded-3xl p-6 md:p-8 border border-purple-300 dark:border-purple-800/60 shadow-2xl space-y-6"
>
<div className="flex flex-col md:flex-row items-start md:items-center justify-between gap-4 pb-4 border-b border-slate-250 dark:border-slate-800">
<div>
<div className="inline-flex items-center gap-2 px-3 py-1 bg-purple-100 dark:bg-purple-950/60 text-purple-700 dark:text-purple-300 text-xs font-bold rounded-full mb-2">
<Code2 className="w-3.5 h-3.5" />
<span>Gerador de Manifesto Declarativo</span>
</div>
<h2 className="text-2xl font-display font-extrabold text-slate-850 dark:text-slate-100">
Construtor de `idf_component.yml`
</h2>
<p className="text-xs text-slate-500 dark:text-slate-400 mt-1 font-semibold">
Adicione este arquivo na pasta <code>main/</code> do seu projeto ESP-IDF para
instalar todas as bibliotecas automaticamente na compilação.
</p>
</div>
<div className="flex items-center gap-2.5 w-full md:w-auto">
<button
onClick={copiarManifesto}
className="flex-1 md:flex-none inline-flex items-center justify-center gap-1.5 bg-gradient-to-r from-purple-600 to-indigo-600 text-white px-4 py-2.5 rounded-xl text-xs font-bold hover:opacity-90 shadow-md transition-all active:scale-95 cursor-pointer"
>
{manifestoCopiado ? (
<>
<Check className="w-4 h-4" />
<span>Manifesto Copiado!</span>
</>
) : (
<>
<Copy className="w-4 h-4" />
<span>Copiar YAML</span>
</>
)}
</button>
<button
onClick={baixarManifesto}
className="inline-flex items-center justify-center gap-1.5 bg-slate-100 dark:bg-slate-800 hover:bg-slate-200 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-200 px-4 py-2.5 rounded-xl text-xs font-bold transition-all active:scale-95 cursor-pointer"
title="Baixar arquivo idf_component.yml pronto"
>
<Download className="w-4 h-4" />
<span className="hidden sm:inline">Baixar .yml</span>
</button>
{componentesSelecionados.length > 0 && (
<button
onClick={() => setComponentesSelecionados([])}
className="p-2.5 text-slate-400 hover:text-rose-500 rounded-xl hover:bg-rose-50 dark:hover:bg-rose-950/30 transition-colors"
title="Limpar seleção"
>
<Trash2 className="w-4 h-4" />
</button>
)}
</div>
</div>
{/* YAML Output Terminal */}
<div className="relative">
<div className="bg-slate-950 text-slate-200 rounded-2xl p-4 md:p-6 font-mono text-xs md:text-sm overflow-x-auto border border-slate-800 shadow-inner">
<pre>{manifestoYaml}</pre>
</div>
</div>
{/* Selected components badges */}
<div className="flex flex-wrap items-center gap-2 pt-2">
<span className="text-xs font-bold text-slate-500 uppercase tracking-wider mr-2">
Componentes Inclusos ({componentesSelecionados.length}):
</span>
{componentesSelecionados.map((id) => {
const c = COMPONENTES_REGISTRY.find((item) => item.id === id);
if (!c) return null;
return (
<span
key={id}
className="inline-flex items-center gap-1.5 bg-purple-50 dark:bg-purple-950/60 text-purple-700 dark:text-purple-300 border border-purple-300 dark:border-purple-800 px-3 py-1 rounded-xl text-xs font-bold"
>
<span>{c.name}</span>
<button
onClick={() => toggleSelecaoManifesto(id)}
className="hover:text-rose-500 ml-1 cursor-pointer"
title="Remover"
>
×
</button>
</span>
);
})}
</div>
</section>
{/* Educational Guide: O que é o Component Manager */}
<section className="bg-white dark:bg-slate-900/40 backdrop-blur-xl rounded-3xl p-6 md:p-8 border border-slate-300 dark:border-slate-800 shadow-xl space-y-8 select-none">
<div>
<div className="flex items-center gap-3 mb-2">
<div className="p-2.5 rounded-xl bg-purple-50 dark:bg-purple-950/50 text-purple-600 dark:text-purple-400">
<BookOpen className="w-5 h-5" />
</div>
<h2 className="text-2xl font-display font-extrabold text-slate-850 dark:text-slate-100">
{GUIA_COMPONENT_MANAGER.titulo}
</h2>
</div>
<p className="text-xs md:text-sm text-slate-600 dark:text-slate-350 leading-relaxed font-semibold max-w-4xl">
{GUIA_COMPONENT_MANAGER.resumo}
</p>
</div>
{/* Vantagens Grid */}
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-4">
{GUIA_COMPONENT_MANAGER.vantagens.map((v, i) => (
<div
key={i}
className="bg-slate-50/70 dark:bg-slate-950/40 p-5 rounded-2xl border border-slate-200 dark:border-slate-800/80 space-y-2"
>
<div className="w-8 h-8 rounded-xl bg-purple-100 dark:bg-purple-900/40 text-purple-600 dark:text-purple-400 flex items-center justify-center text-xs font-extrabold">
0{i + 1}
</div>
<h3 className="text-sm font-bold text-slate-850 dark:text-slate-100">{v.titulo}</h3>
<p className="text-xs text-slate-500 dark:text-slate-400 leading-relaxed">
{v.descricao}
</p>
</div>
))}
</div>
{/* Comandos Essenciais da CLI */}
<div className="space-y-3">
<h3 className="text-base font-display font-extrabold text-slate-850 dark:text-slate-100 flex items-center gap-2">
<Terminal className="w-4 h-4 text-purple-500" />
<span>Comandos Essenciais no Terminal</span>
</h3>
<div className="space-y-3">
{GUIA_COMPONENT_MANAGER.comandosCli.map((cmd, i) => (
<div
key={i}
className="bg-slate-900 text-slate-100 p-4 rounded-2xl border border-slate-800 flex flex-col md:flex-row md:items-center justify-between gap-3 font-mono text-xs"
>
<div>
<span className="text-purple-400 font-bold">$ {cmd.exemplo}</span>
<p className="text-[11px] text-slate-400 font-sans mt-1">
{cmd.explicacao}
</p>
</div>
<button
onClick={() => copiarComando(`cmd-${i}`, cmd.exemplo)}
className="self-start md:self-auto inline-flex items-center gap-1 bg-slate-800 hover:bg-slate-700 px-3 py-1.5 rounded-lg text-[11px] font-bold text-slate-200 transition-colors shrink-0"
>
{copiadoId === `cmd-${i}` ? (
<>
<Check className="w-3.5 h-3.5 text-emerald-400" />
<span>Copiado</span>
</>
) : (
<>
<Copy className="w-3.5 h-3.5" />
<span>Copiar</span>
</>
)}
</button>
</div>
))}
</div>
</div>
{/* Versioning Semantics Callout */}
<div className="bg-purple-50 dark:bg-purple-950/30 rounded-2xl p-5 border border-purple-200 dark:border-purple-800/40 text-xs space-y-2">
<h4 className="font-bold text-purple-900 dark:text-purple-300 flex items-center gap-1.5">
<HelpCircle className="w-4 h-4 text-purple-600 dark:text-purple-400" />
<span>Regras de Versionamento Semântico no ESP-IDF</span>
</h4>
<ul className="list-disc list-inside space-y-1 text-slate-750 dark:text-slate-350">
<li>
<code>^1.2.0</code>: Permite atualizações menores e correções (ex: 1.2.1, 1.3.0),
mas bloqueia grandes mudanças de API (2.0.0). <strong>(Recomendado)</strong>
</li>
<li>
<code>~1.2.0</code>: Permite apenas correções de bugs (ex: 1.2.1, 1.2.5), travando
na mesma versão menor.
</li>
<li>
<code>1.2.0</code>: Trava na versão exata indicada, sem receber atualizações.
</li>
<li>
<code>*</code>: Aceita qualquer versão disponível (não recomendado para produção).
</li>
</ul>
</div>
</section>
</main>
<Footer />
</div>
);
}
+16 -1
View File
@@ -526,7 +526,11 @@ export default function DiagnosticoPage() {
const estaAberto = cardAberto === erro.id;
const lang = linguagemCodigo[erro.id] || "arduino";
const codigoAtual =
lang === "arduino" ? erro.codigoArduino : erro.codigoEspIdf;
lang === "arduino"
? erro.codigoArduino
: lang === "espidf"
? erro.codigoEspIdf
: erro.codigoMicroPython || "# Exemplo não aplicável";
const catInfo = categoriasDiagnostico.find(
(c) => c.id === erro.categoria
@@ -703,6 +707,17 @@ export default function DiagnosticoPage() {
>
ESP-IDF (C)
</button>
<button
type="button"
onClick={() => setLang(erro.id, "micropython")}
className={`text-xs px-3 py-1 rounded-lg font-bold transition-all cursor-pointer ${
lang === "micropython"
? "bg-white dark:bg-slate-900 text-amber-600 dark:text-amber-400 shadow-xs"
: "text-slate-600 dark:text-slate-400 hover:text-slate-900"
}`}
>
MicroPython
</button>
</div>
<button
+44 -9
View File
@@ -17,7 +17,11 @@ import {
FileText,
Sliders,
Award,
Target
Target,
Box,
Sparkles,
ExternalLink,
ArrowRight
} from "lucide-react";
export default async function FrameworkDetail({ params }) {
@@ -30,6 +34,7 @@ export default async function FrameworkDetail({ params }) {
const features = framework.caracteristicas || [];
const useCases = framework.casos_uso || [];
const isEspIdf = key === "ESP-IDF";
return (
<div className="bg-gradient-to-br from-slate-100 via-slate-50 to-purple-100/40 dark:from-slate-950 dark:via-slate-950 dark:to-slate-900 min-h-screen text-slate-900 dark:text-slate-100 transition-colors duration-300">
@@ -51,7 +56,7 @@ export default async function FrameworkDetail({ params }) {
<Header />
<main className="px-6 pt-16 pb-24 max-w-7xl mx-auto">
<main className="px-4 md:px-6 pt-12 md:pt-16 pb-24 max-w-7xl mx-auto">
{/* Back navigation link */}
<div className="mb-8">
<Link
@@ -112,7 +117,7 @@ export default async function FrameworkDetail({ params }) {
</div>
</div>
<p className="text-sm text-slate-500 dark:text-slate-200 mt-6 leading-relaxed max-w-4xl font-semibold">
<p className="text-sm text-slate-600 dark:text-slate-200 mt-6 leading-relaxed max-w-4xl font-semibold">
{framework.descricao}
</p>
</div>
@@ -129,7 +134,7 @@ export default async function FrameworkDetail({ params }) {
<span>LINGUAGEM DE DESENVOLVIMENTO</span>
</h3>
<p className="text-2xl font-extrabold text-slate-800 dark:text-slate-100">{framework.linguagem}</p>
<p className="text-xs text-slate-400 mt-1">Sintaxe principal do ecossistema</p>
<p className="text-xs text-slate-400 mt-1">Sintaxe e ecossistema</p>
</div>
<div
@@ -233,9 +238,39 @@ export default async function FrameworkDetail({ params }) {
</div>
</div>
{/* Coding examples container (renders only if framework has examples defined) */}
{framework.exemplos && (
<div className="mt-12">
{/* Special Section: ESP Component Registry Callout for ESP-IDF */}
{isEspIdf && (
<div className="bg-gradient-to-r from-purple-900/90 to-indigo-900/90 rounded-3xl p-6 md:p-8 text-white shadow-2xl border border-purple-500/40 mb-12 relative overflow-hidden">
<div className="flex flex-col lg:flex-row items-start lg:items-center justify-between gap-6 relative z-10">
<div className="space-y-2 max-w-2xl">
<div className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-purple-500/20 border border-purple-400/30 text-purple-300 text-xs font-bold">
<Box className="w-3.5 h-3.5" />
<span>Arquitetura Moderna ESP-IDF</span>
</div>
<h3 className="text-2xl font-display font-extrabold text-white">
Gerenciamento Modular com ESP Component Registry
</h3>
<p className="text-xs md:text-sm text-slate-200 leading-relaxed font-medium">
Nos projetos ESP-IDF v4.4+ e v5.x+, as bibliotecas não precisam mais ser adicionadas como submódulos Git.
Utilize o <code>idf_component.yml</code> e o comando <code>idf.py add-dependency</code> para baixar automaticamente drivers de displays (LVGL), pilhas industriais (Modbus), RainMaker e mais.
</p>
</div>
<Link
href="/componentes"
className="inline-flex items-center gap-2 bg-white text-purple-900 hover:bg-slate-100 font-extrabold text-xs uppercase tracking-wider px-6 py-3.5 rounded-xl shadow-lg transition-all active:scale-95 shrink-0"
>
<Sparkles className="w-4 h-4 text-purple-600" />
<span>Explorar Componentes ESP-IDF</span>
<ArrowRight className="w-4 h-4 text-purple-600" />
</Link>
</div>
</div>
)}
{/* Coding examples container */}
{framework.exemplo && (
<div className="mt-8">
<CodeExample framework={framework} />
</div>
)}
@@ -283,8 +318,8 @@ export async function generateMetadata({ params }) {
return {
...paginaMeta({
titulo: `${framework.nome} para ESP32`,
descricao: `${framework.nome_completo}: ${framework.descricao} Guia em português com exemplo de código e quando usar.`,
titulo: `${framework.nome} para ESP32 · Guia Técnico`,
descricao: `${framework.nome_completo}: ${framework.descricao} Guia com exemplos práticos de código e casos de uso.`,
caminho: `/frameworks/${encodeURIComponent(key)}`,
tipo: "article",
keywords: [
+139 -54
View File
@@ -17,15 +17,31 @@ import {
Music,
Camera,
Brain,
Home
Home,
Box,
Cloud,
Radio,
ShieldCheck,
Mic
} from "lucide-react";
export const metadata = paginaMeta({
titulo: "Frameworks para ESP32",
descricao: "ESP-IDF, Arduino, MicroPython, ESP-ADF, ESP-DSP, ESP-WHO, ESP-NN e ESP-Matter: para que serve cada framework do ESP32, com exemplo de código e quando usar.",
titulo: "Frameworks & SDKs para ESP32: Guia Completo e Comparativo",
descricao: "Guia completo de desenvolvimento: ESP-IDF, ESP-RainMaker, ESP-Matter, Rust, ESP-ADF, ESP-SR, ESP-WHO, Arduino e MicroPython com exemplos de código.",
caminho: "/frameworks",
keywords: ["ESP-IDF", "Arduino ESP32", "MicroPython ESP32", "frameworks ESP32", "programar ESP32"],
keywords: [
"ESP-IDF",
"ESP-RainMaker",
"ESP-Matter",
"Rust ESP32",
"ESP-SR",
"ESP-ADF",
"ESP-IoT-Solution",
"Arduino ESP32",
"MicroPython ESP32",
"frameworks ESP32",
"programar ESP32"
],
});
export default function Frameworks() {
@@ -35,34 +51,70 @@ export default function Frameworks() {
<div className="bg-gradient-to-br from-slate-100 via-slate-50 to-purple-100/40 dark:from-slate-950 dark:via-slate-950 dark:to-slate-900 min-h-screen text-slate-900 dark:text-slate-100 transition-colors duration-300">
<Header />
<main id="conteudo" className="px-6 pt-16 pb-24 max-w-7xl mx-auto">
<main id="conteudo" className="px-4 md:px-6 pt-12 md:pt-16 pb-24 max-w-7xl mx-auto space-y-12">
{/* Top Hero Section */}
<section className="text-center mb-16 select-none">
<div className="inline-flex items-center gap-2 bg-white dark:bg-slate-900/50 backdrop-blur-md px-4 py-2 rounded-full mb-6 border border-slate-300 dark:border-slate-800/60 shadow-xs">
<section className="text-center select-none">
<div className="inline-flex items-center gap-2 bg-white/80 dark:bg-slate-900/60 backdrop-blur-md px-4 py-2 rounded-full mb-6 border border-slate-300 dark:border-slate-800/80 shadow-xs">
<Layers className="w-4 h-4 text-purple-500" />
<span className="text-xs font-bold text-slate-700 dark:text-slate-350 uppercase tracking-wider">Ferramentas de Desenvolvimento</span>
<span className="text-xs font-bold text-slate-700 dark:text-slate-350 uppercase tracking-wider">
Ecossistema de Desenvolvimento
</span>
<span className="bg-purple-100 dark:bg-purple-950/80 text-purple-700 dark:text-purple-300 text-[10px] font-extrabold px-2 py-0.5 rounded-full">
14 SDKs
</span>
</div>
<h1 className="text-4xl md:text-6xl font-display font-extrabold bg-gradient-to-r from-blue-600 via-purple-600 to-pink-600 dark:from-blue-400 dark:via-purple-400 dark:to-pink-400 bg-clip-text text-transparent mb-6 leading-none tracking-tight">
Frameworks ESP32
<h1 className="text-4xl md:text-6xl font-display font-extrabold bg-gradient-to-r from-blue-600 via-purple-600 to-pink-600 dark:from-blue-400 dark:via-purple-400 dark:to-pink-400 bg-clip-text text-transparent mb-6 pb-2 pt-1 leading-tight md:leading-[1.18] tracking-tight">
Frameworks & SDKs ESP32
</h1>
<p className="text-sm md:text-base text-slate-500 dark:text-slate-400 max-w-2xl mx-auto leading-relaxed font-semibold">
Descubra o ecossistema de software do ESP32. De desenvolvimento geral C/C++ a
soluções dedicadas a áudio de alto desempenho, visão computacional na borda e IoT inteligente.
<p className="text-sm md:text-base text-slate-600 dark:text-slate-400 max-w-3xl mx-auto leading-relaxed font-semibold">
Descubra o ecossistema completo de software do ESP32. Do desenvolvimento nativo C/C++
com FreeRTOS ao ecossistema moderno em Rust, passando por nuvem IoT, reconhecimento de voz local,
áudio de alta fidelidade e o padrão universal Matter.
</p>
</section>
{/* Highlight Callout: ESP Component Registry */}
<section className="bg-gradient-to-r from-purple-900/90 via-indigo-900/90 to-slate-900/90 text-white rounded-3xl p-6 md:p-8 shadow-2xl border border-purple-500/30 relative overflow-hidden flex flex-col lg:flex-row items-start lg:items-center justify-between gap-6">
<div className="absolute -right-12 -top-12 w-64 h-64 bg-purple-500/10 rounded-full blur-3xl pointer-events-none" />
<div className="space-y-2 max-w-3xl relative z-10">
<div className="inline-flex items-center gap-2 px-3 py-1 bg-purple-500/20 text-purple-300 text-xs font-bold rounded-full border border-purple-400/30">
<Box className="w-3.5 h-3.5 text-purple-300" />
<span>Arquitetura Modular</span>
</div>
<h2 className="text-2xl md:text-3xl font-display font-extrabold text-white">
ESP Component Registry & IDF Component Manager
</h2>
<p className="text-xs md:text-sm text-slate-300 leading-relaxed font-medium">
Desenvolva de forma modular: instale drivers de displays (LVGL), pilhas industriais (Modbus),
recursos de nuvem (RainMaker) e pacotes de suporte a placas (BSPs) com uma única linha no seu manifesto <code>idf_component.yml</code>.
</p>
</div>
<div className="relative z-10 shrink-0 w-full lg:w-auto">
<Link
href="/componentes"
className="inline-flex items-center justify-center gap-2 w-full lg:w-auto bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-400 hover:to-pink-400 text-white font-bold text-xs uppercase tracking-wider px-6 py-3.5 rounded-2xl shadow-lg transition-all active:scale-95"
>
<Sparkles className="w-4 h-4" />
<span>Explorar Component Registry</span>
<ArrowRight className="w-4 h-4" />
</Link>
</div>
</section>
{/* Cards Grid */}
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{frameworks.map(([key, framework]) => (
<Link
key={key}
href={`/frameworks/${key}`}
href={`/frameworks/${encodeURIComponent(key)}`}
className="group flex"
>
<div
className="bg-white dark:bg-slate-900/40 backdrop-blur-xl border border-slate-300 dark:border-slate-800/80 rounded-3xl shadow-lg hover:shadow-2xl transition-all duration-500 hover:-translate-y-1.5 flex flex-col justify-between overflow-hidden w-full"
className="bg-white dark:bg-slate-900/40 backdrop-blur-xl border border-slate-300 dark:border-slate-800/80 rounded-3xl shadow-lg hover:shadow-2xl transition-all duration-300 hover:-translate-y-1.5 flex flex-col justify-between overflow-hidden w-full"
style={{ borderTop: `4px solid ${framework.cor}` }}
>
@@ -80,6 +132,9 @@ export default function Frameworks() {
>
{framework.linguagem}
</span>
<span className="text-[9px] font-bold text-slate-400 dark:text-slate-500">
{framework.tipo}
</span>
</div>
</div>
@@ -104,7 +159,7 @@ export default function Frameworks() {
<Target className="w-3.5 h-3.5 text-blue-500" />
<span>Objetivo Principal</span>
</h4>
<p className="text-xs text-slate-650 dark:text-slate-200 font-medium leading-relaxed">
<p className="text-xs text-slate-650 dark:text-slate-200 font-medium leading-relaxed line-clamp-2">
{framework.funcao_principal}
</p>
</div>
@@ -153,9 +208,9 @@ export default function Frameworks() {
</div>
{/* Bottom Informative Cards Section */}
<div className="mt-16 grid md:grid-cols-2 gap-8 select-none">
<div className="grid md:grid-cols-3 gap-6 select-none">
{/* Card 1: Beginner Guide */}
<div className="bg-white dark:bg-slate-900/40 backdrop-blur-xl rounded-3xl shadow-xl p-8 border border-slate-300 dark:border-slate-800/80 flex flex-col justify-between relative overflow-hidden">
<div className="bg-white dark:bg-slate-900/40 backdrop-blur-xl rounded-3xl shadow-xl p-6 md:p-8 border border-slate-300 dark:border-slate-800/80 flex flex-col justify-between relative overflow-hidden">
<div>
<div className="flex items-center gap-3.5 mb-5">
<div className="w-12 h-12 bg-blue-500/10 border border-blue-500/20 rounded-2xl flex items-center justify-center text-blue-500">
@@ -170,32 +225,67 @@ export default function Frameworks() {
</div>
<p className="text-xs text-slate-500 dark:text-slate-400 leading-relaxed mb-6 font-semibold">
Se você está iniciando a sua jornada de hardware, recomendamos adotar o ecossistema&nbsp;
<strong className="text-slate-750 dark:text-slate-300">Arduino</strong> ou&nbsp;
Se você está iniciando a sua jornada, o&nbsp;
<strong className="text-slate-750 dark:text-slate-300">Arduino Core</strong> ou&nbsp;
<strong className="text-slate-750 dark:text-slate-300">MicroPython</strong>&nbsp;
para testar sensores e APIs. Para projetos profissionais industriais de alta performance e eficiência energética, o framework nativo&nbsp;
<strong className="text-slate-750 dark:text-slate-300">ESP-IDF</strong> é o padrão exigido no mercado.
são ideais para testar sensores e APIs. Para produtos comerciais, adote o&nbsp;
<strong className="text-slate-750 dark:text-slate-300">ESP-IDF</strong> ou&nbsp;
<strong className="text-slate-750 dark:text-slate-300">Rust on ESP32</strong>.
</p>
</div>
<div className="flex flex-wrap gap-2.5 pt-4 border-t border-slate-200 dark:border-slate-850/40 mt-auto">
<Link href="/frameworks/Arduino" className="inline-flex items-center gap-1.5 px-4 py-2.5 bg-blue-500/10 text-blue-600 dark:text-blue-400 border border-blue-500/20 rounded-xl text-xs font-bold hover:bg-blue-500/20 transition-all">
<div className="flex flex-wrap gap-2 pt-4 border-t border-slate-200 dark:border-slate-850/40 mt-auto">
<Link href="/frameworks/Arduino" className="inline-flex items-center gap-1 px-3 py-2 bg-blue-500/10 text-blue-600 dark:text-blue-400 border border-blue-500/20 rounded-xl text-xs font-bold hover:bg-blue-500/20 transition-all">
<span>Arduino</span>
<ArrowRight className="w-3.5 h-3.5" />
</Link>
<Link href="/frameworks/MicroPython" className="inline-flex items-center gap-1.5 px-4 py-2.5 bg-purple-500/10 text-purple-600 dark:text-purple-400 border border-purple-500/20 rounded-xl text-xs font-bold hover:bg-purple-500/20 transition-all">
<Link href="/frameworks/MicroPython" className="inline-flex items-center gap-1 px-3 py-2 bg-purple-500/10 text-purple-600 dark:text-purple-400 border border-purple-500/20 rounded-xl text-xs font-bold hover:bg-purple-500/20 transition-all">
<span>MicroPython</span>
<ArrowRight className="w-3.5 h-3.5" />
</Link>
<Link href="/frameworks/ESP-IDF" className="inline-flex items-center gap-1.5 px-4 py-2.5 bg-red-500/10 text-red-600 dark:text-red-450 border border-red-500/20 rounded-xl text-xs font-bold hover:bg-red-500/20 transition-all">
<span>ESP-IDF</span>
<ArrowRight className="w-3.5 h-3.5" />
<Link href="/frameworks/Rust-ESP" className="inline-flex items-center gap-1 px-3 py-2 bg-amber-500/10 text-amber-600 dark:text-amber-400 border border-amber-500/20 rounded-xl text-xs font-bold hover:bg-amber-500/20 transition-all">
<span>Rust</span>
</Link>
</div>
</div>
{/* Card 2: Specialized Solutions */}
<div className="bg-white dark:bg-slate-900/40 backdrop-blur-xl rounded-3xl shadow-xl p-8 border border-slate-300 dark:border-slate-800/80 flex flex-col justify-between relative overflow-hidden">
{/* Card 2: Cloud & Smart Home */}
<div className="bg-white dark:bg-slate-900/40 backdrop-blur-xl rounded-3xl shadow-xl p-6 md:p-8 border border-slate-300 dark:border-slate-800/80 flex flex-col justify-between relative overflow-hidden">
<div>
<div className="flex items-center gap-3.5 mb-5">
<div className="w-12 h-12 bg-indigo-500/10 border border-indigo-500/20 rounded-2xl flex items-center justify-center text-indigo-500">
<Cloud className="w-6 h-6" />
</div>
<div>
<h3 className="text-xl font-display font-extrabold text-slate-850 dark:text-slate-100">
Cloud & Smart Home
</h3>
<p className="text-[10px] font-bold text-indigo-500 uppercase tracking-wider leading-none">Conectividade Avançada</p>
</div>
</div>
<p className="text-xs text-slate-500 dark:text-slate-400 leading-relaxed mb-6 font-semibold">
Crie dispositivos interoperáveis com&nbsp;
<strong className="text-slate-750 dark:text-slate-300">ESP-Matter</strong>, implemente produtos de nuvem rápida com&nbsp;
<strong className="text-slate-750 dark:text-slate-300">ESP-RainMaker</strong> ou redes locais com&nbsp;
<strong className="text-slate-750 dark:text-slate-300">ESP-NOW</strong> e&nbsp;
<strong className="text-slate-750 dark:text-slate-300">Zigbee 3.0</strong>.
</p>
</div>
<div className="flex flex-wrap gap-2 pt-4 border-t border-slate-200 dark:border-slate-850/40 mt-auto">
<Link href="/frameworks/ESP-RainMaker" className="inline-flex items-center gap-1 px-3 py-2 bg-blue-500/10 text-blue-600 dark:text-blue-400 border border-blue-500/20 rounded-xl text-xs font-bold hover:bg-blue-500/20 transition-all">
<span>RainMaker</span>
</Link>
<Link href="/frameworks/ESP-Matter" className="inline-flex items-center gap-1 px-3 py-2 bg-amber-500/10 text-amber-600 dark:text-amber-400 border border-amber-500/20 rounded-xl text-xs font-bold hover:bg-amber-500/20 transition-all">
<span>Matter</span>
</Link>
<Link href="/frameworks/ESP-Zigbee-SDK" className="inline-flex items-center gap-1 px-3 py-2 bg-pink-500/10 text-pink-600 dark:text-pink-400 border border-pink-500/20 rounded-xl text-xs font-bold hover:bg-pink-500/20 transition-all">
<span>Zigbee</span>
</Link>
</div>
</div>
{/* Card 3: Specialized Edge AI */}
<div className="bg-white dark:bg-slate-900/40 backdrop-blur-xl rounded-3xl shadow-xl p-6 md:p-8 border border-slate-300 dark:border-slate-800/80 flex flex-col justify-between relative overflow-hidden">
<div>
<div className="flex items-center gap-3.5 mb-5">
<div className="w-12 h-12 bg-purple-500/10 border border-purple-500/20 rounded-2xl flex items-center justify-center text-purple-500">
@@ -203,38 +293,33 @@ export default function Frameworks() {
</div>
<div>
<h3 className="text-xl font-display font-extrabold text-slate-850 dark:text-slate-100">
Soluções Especializadas
Áudio, Voz & IA
</h3>
<p className="text-[10px] font-bold text-purple-500 uppercase tracking-wider leading-none">Domínios Avançados</p>
<p className="text-[10px] font-bold text-purple-500 uppercase tracking-wider leading-none">Domínios Especializados</p>
</div>
</div>
<p className="text-xs text-slate-500 dark:text-slate-400 leading-relaxed mb-6 font-semibold">
Projetos complexos de IoT demandam bibliotecas altamente otimizadas na arquitetura.
A Espressif fornece extensões prontas como o&nbsp;
<strong className="text-slate-750 dark:text-slate-300">ESP-ADF</strong> para processamento de áudio digital,&nbsp;
<strong className="text-slate-750 dark:text-slate-300">ESP-WHO</strong> para processamento de imagem por câmera,&nbsp;
<strong className="text-slate-750 dark:text-slate-300">ESP-NN</strong> para redes neurais locais e&nbsp;
<strong className="text-slate-750 dark:text-slate-300">ESP-Matter</strong> para automação residencial.
Processe áudio com o&nbsp;
<strong className="text-slate-750 dark:text-slate-300">ESP-ADF</strong>, reconheça fala offline com o&nbsp;
<strong className="text-slate-750 dark:text-slate-300">ESP-SR</strong>, processe vídeo com o&nbsp;
<strong className="text-slate-750 dark:text-slate-300">ESP-WHO</strong> e acelere TinyML com o&nbsp;
<strong className="text-slate-750 dark:text-slate-300">ESP-NN</strong>.
</p>
</div>
<div className="flex flex-wrap gap-2.5 pt-4 border-t border-slate-200 dark:border-slate-850/40 mt-auto">
<Link href="/frameworks/ESP-ADF" className="inline-flex items-center gap-1.5 px-3.5 py-2 bg-slate-150/45 dark:bg-slate-850 text-slate-700 dark:text-slate-300 border border-slate-300 dark:border-slate-850/60 rounded-xl text-xs font-bold hover:bg-slate-200 dark:hover:bg-slate-800 transition-all">
<Music className="w-3.5 h-3.5 text-blue-500" />
<div className="flex flex-wrap gap-2 pt-4 border-t border-slate-200 dark:border-slate-850/40 mt-auto">
<Link href="/frameworks/ESP-ADF" className="inline-flex items-center gap-1 px-3 py-2 bg-blue-500/10 text-blue-600 dark:text-blue-400 border border-blue-500/20 rounded-xl text-xs font-bold hover:bg-blue-500/20 transition-all">
<Music className="w-3.5 h-3.5" />
<span>Áudio</span>
</Link>
<Link href="/frameworks/ESP-WHO" className="inline-flex items-center gap-1.5 px-3.5 py-2 bg-slate-150/45 dark:bg-slate-850 text-slate-700 dark:text-slate-300 border border-slate-300 dark:border-slate-850/60 rounded-xl text-xs font-bold hover:bg-slate-200 dark:hover:bg-slate-800 transition-all">
<Camera className="w-3.5 h-3.5 text-orange-500" />
<span>Visão</span>
<Link href="/frameworks/ESP-SR" className="inline-flex items-center gap-1 px-3 py-2 bg-indigo-500/10 text-indigo-600 dark:text-indigo-400 border border-indigo-500/20 rounded-xl text-xs font-bold hover:bg-indigo-500/20 transition-all">
<Mic className="w-3.5 h-3.5" />
<span>Voz</span>
</Link>
<Link href="/frameworks/ESP-NN" className="inline-flex items-center gap-1.5 px-3.5 py-2 bg-slate-150/45 dark:bg-slate-850 text-slate-700 dark:text-slate-300 border border-slate-300 dark:border-slate-850/60 rounded-xl text-xs font-bold hover:bg-slate-200 dark:hover:bg-slate-800 transition-all">
<Brain className="w-3.5 h-3.5 text-teal-500" />
<span>Inteligência Artificial</span>
</Link>
<Link href="/frameworks/ESP-Matter" className="inline-flex items-center gap-1.5 px-3.5 py-2 bg-slate-150/45 dark:bg-slate-850 text-slate-700 dark:text-slate-300 border border-slate-300 dark:border-slate-850/60 rounded-xl text-xs font-bold hover:bg-slate-200 dark:hover:bg-slate-800 transition-all">
<Home className="w-3.5 h-3.5 text-yellow-500" />
<span>Matter</span>
<Link href="/frameworks/ESP-NN" className="inline-flex items-center gap-1 px-3 py-2 bg-teal-500/10 text-teal-600 dark:text-teal-400 border border-teal-500/20 rounded-xl text-xs font-bold hover:bg-teal-500/20 transition-all">
<Brain className="w-3.5 h-3.5" />
<span>IA</span>
</Link>
</div>
</div>
+16 -5
View File
@@ -21,16 +21,17 @@ import {
Radio,
ShieldCheck,
Code,
HelpCircle
HelpCircle,
Box
} from "lucide-react";
export default function Home() {
// Estatísticas da Plataforma
const stats = [
{ value: "12", label: "Séries Documentadas", desc: "Do ESP32 clássico ao P4 e C61" },
{ value: "8", label: "Frameworks & SDKs", desc: "ESP-IDF, Arduino, MicroPython, etc." },
{ value: "14", label: "Frameworks & SDKs", desc: "ESP-IDF, RainMaker, Rust, Matter, etc." },
{ value: "20+", label: "Componentes Curados", desc: "ESP Component Registry & idf_component.yml" },
{ value: "30+", label: "Guias de Diagnóstico", desc: "Soluções para bootloops, brownouts e WDT" },
{ value: "60+", label: "Termos Técnicos", desc: "Glossário completo de arquitetura e IoT" },
];
// Ferramentas da Plataforma (100% Clicáveis)
@@ -45,6 +46,16 @@ export default function Home() {
iconBg: "text-purple-600 bg-purple-50 dark:bg-purple-950/40 dark:text-purple-400",
ctaText: "Iniciar Quiz de Seleção",
},
{
title: "ESP Component Registry",
badge: "Oficial & Modular",
badgeColor: "bg-purple-100 text-purple-700 dark:bg-purple-950/60 dark:text-purple-300",
description: "Explore o catálogo oficial de pacotes modulares da Espressif (LVGL, RainMaker, ESP-SR, BSPs) e gere manifestos idf_component.yml.",
href: "/componentes",
icon: <Box className="w-6 h-6" />,
iconBg: "text-purple-600 bg-purple-50 dark:bg-purple-950/40 dark:text-purple-400",
ctaText: "Explorar Componentes",
},
{
title: "Diagnóstico de Falhas",
badge: "30+ Soluções",
@@ -87,9 +98,9 @@ export default function Home() {
},
{
title: "Frameworks & SDKs",
badge: "C++, Python & Rust",
badge: "14 Frameworks",
badgeColor: "bg-teal-100 text-teal-700 dark:bg-teal-950/60 dark:text-teal-300",
description: "Documentação de frameworks oficiais e comunitários: ESP-IDF, Arduino Core, MicroPython, ESP-Matter, ESP-WHO e mais.",
description: "Documentação completa de frameworks oficiais: ESP-IDF, RainMaker, Rust, Matter, ESP-SR, Arduino, MicroPython e mais.",
href: "/frameworks",
icon: <Terminal className="w-6 h-6" />,
iconBg: "text-teal-600 bg-teal-50 dark:bg-teal-950/40 dark:text-teal-400",
+1
View File
@@ -21,6 +21,7 @@ export default function sitemap() {
{ caminho: "/diagnostico", prioridade: 0.9, frequencia: "weekly", lastModified: dataRevisao },
{ caminho: "/seletor", prioridade: 0.8, frequencia: "monthly", lastModified: dataRevisao },
{ caminho: "/frameworks", prioridade: 0.8, frequencia: "monthly", lastModified: dataRevisao },
{ caminho: "/componentes", prioridade: 0.8, frequencia: "weekly", lastModified: dataRevisao },
{ caminho: "/glossario", prioridade: 0.7, frequencia: "monthly", lastModified: dataRevisao },
{ caminho: "/catalogo", prioridade: 0.6, frequencia: "weekly", lastModified: dataRevisao },
{ caminho: "/sobre", prioridade: 0.4, frequencia: "yearly", lastModified: dataRevisao },