Conceitos
São seis conceitos que fazem todo app Fayz encaixar. Domine estes e você lê qualquer projeto Fayz sem se perder: o plugin e seu manifesto, a biblioteca core multi-tenant, os providers, os dois caminhos de construção, os canais de versão e os plugins incubator. Cada um vem com um parágrafo e, quando ajuda, um trecho de código.
1. Plugin e manifesto
Um plugin é uma capacidade empacotada — agenda, CRM, financeiro. Você o cria chamando a factory dele (createAgendaPlugin, createCrmPlugin, …), que retorna um manifesto: a descrição, em dados, de tudo que aquele plugin contribui para o app. Rotas, navegação, widgets de dashboard, migrações de banco, ferramentas de IA — tudo declarado num objeto, não espalhado pelo código.
import { createAgendaPlugin } from '@fayz-ai/plugin-agenda'
const agenda = createAgendaPlugin()
// → { id, name, icon, version, navigation, routes, widgets?,
// dashboardWidgets?, migrations?, ... } = PluginManifest
O app compõe uma lista desses manifestos e o runtime faz o resto: monta a navegação, resolve as rotas, registra os widgets e ordena as migrações. A regra que mantém isso são: um plugin não emite nada específico do app por padrão — o que ele contribui para uma superfície compartilhada é opt-in. O app decide o que aparece.
2. Biblioteca core multi-tenant
Todo app Fayz senta sobre a biblioteca core (antes chamada saas_core): as tabelas-base que todo negócio precisa — tenants, people, tenant_members, role_permissions, appointments, transactions. Essas tabelas não vivem num schema core. separado — moram todas em public.*. Por cima delas, o modelo tem só mais duas camadas:
public.* tabelas-base compartilhadas (tenants, people, tenant_members, role_permissions, appointments…) plg_* tabelas que um plugin instala e possui (plg_shop_products, plg_courses_*…) suas tabelas o que o seu app/incubator cria por cima
Um plugin instala as próprias tabelas com prefixo plg_ e reutiliza as tabelas do core que precisa em vez de copiá-las; se o financeiro precisa saber "quem recebeu", ele referencia public.people, não guarda uma cópia. Uma fonte de verdade por entidade.
O tenant é o cliente do seu SaaS (um salão, uma clínica). Toda tabela — do core, de plugin ou sua — carrega tenant_id, e o isolamento é garantido por RLS (Row-Level Security) do Postgres, chaveada nesse tenant_id. O RLS é a fronteira, não a separação de schemas: você não filtra por tenant na aplicação — o banco recusa linhas de outro tenant. Você traz o seu próprio Supabase (BYOS) e ele recebe exatamente essa forma; é a mesma que a plataforma hospeda em escala. O detalhe completo está em Dados → Modelo e RLS e multi-tenant.
3. Providers (mock-first)
Um provider é a abstração de backend de um plugin: a mesma interface, duas implementações. Todo app nasce com backend.provider: "mock" — dados de exemplo, auth simulada, zero variável de ambiente — então você desenvolve e demonstra sem tocar em infraestrutura. Quando estiver pronto, você faz o flip: troca o provider para supabase e o mesmo plugin passa a falar com o Postgres real.
// app.manifest.json — de mock para real é uma linha:
"backend": { "provider": "mock" }
"backend": { "provider": "supabase", "projectRef": "<seu-ref>" }
No nível do plugin isso aparece como um provider seguro que escolhe Supabase quando há credenciais e cai no mock quando não há — a mesma interface dos dois lados, então nada no resto do plugin muda no flip. Como conectar o Supabase de verdade está em Dados → Supabase.
4. Os dois caminhos
Existem dois jeitos de construir. No App Fayz você ganha um shell de admin completo pronto — navegação gerada, troca de tenant, permissões, CRUD — a partir da sua config. No Fayz Headless você consome o core e os bundles de plugin dentro do seu próprio site, sendo dono da casca. Os dois usam os mesmos plugins e o mesmo backend; muda quem monta a interface em volta.
Escolher o caminho certo no começo economiza retrabalho — a comparação completa, com quando usar cada um, está em Os dois caminhos.
5. Canais de versão
Duas coisas diferentes usam nomes parecidos, então separe-as:
- Canais de release (
stable,latest,preview) são conjuntos de versões — grupos coerentes de pacotes@fayz-ai/*que você instala juntos.fayz createfixa seu app no canalstablepor padrão. - Tiers de maturidade (
stable,beta,preview,internal) são uma propriedade de cada pacote — o quanto você pode se apoiar nele hoje.
Seja honesto com você mesmo: nada é tier stable ainda. O Fayz é pré-1.0, e enquanto um pacote está em 0.x, um bump menor (0.4.0 → 0.5.0) pode conter mudanças que quebram — e nós usamos essa margem. O core e os plugins que já rodam no dia a dia são tier beta. Fixe versões exatas em produção e leia o changelog antes de atualizar.
A tabela completa de tiers, com garantias de versionamento e resposta a bugs, está em Referência → versões e canais.
6. Plugins incubator
Nem toda capacidade precisa virar um pacote publicado. Um plugin incubator é um plugin que mora dentro do seu próprio app (em src/plugins/), seguindo o mesmo contrato dos plugins oficiais — mesmo manifesto, mesmas rotas, migrações e providers. É onde você põe a lógica específica do seu produto, ou incuba um plugin novo antes de eventualmente graduá-lo para o catálogo.
fayz create plugin meu-plugin
Como o contrato é idêntico, um incubator injeta na UI da SDK do mesmo jeito que um plugin oficial — a diferença é só quem é dono do código. Os padrões para escrever um estão em Plugins próprios → incubator.