Contribuicao
Adicionando Features
End-to-end — da migration ate a navegacao
Guia passo a passo para adicionar uma feature completa ao Vendee.
Crie a migration no Supabase
Adicione as tabelas/colunas necessarias no banco:
CREATE TABLE my_entity (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
workspace_id uuid NOT NULL REFERENCES workspaces(id),
name text NOT NULL,
created_at timestamptz DEFAULT now()
);
ALTER TABLE my_entity ENABLE ROW LEVEL SECURITY;
CREATE POLICY "workspace_isolation" ON my_entity
FOR ALL USING (workspace_id IN (SELECT get_user_workspace_ids()));Regenere os tipos
bunx supabase gen types typescript --project-id <id> > packages/supabase/src/types.tsCrie o hook
Em src/hooks/use-my-entity.ts:
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { supabase } from "@/lib/supabase";
import { useWorkspaceStore } from "@/stores/workspace-store";
export function useMyEntities() {
const workspace = useWorkspaceStore((s) => s.workspace);
return useQuery({
queryKey: ["my-entities", workspace?.id],
queryFn: async () => {
const { data, error } = await supabase
.from("my_entity")
.select("*")
.eq("workspace_id", workspace!.id);
if (error) throw error;
return data;
},
enabled: !!workspace,
});
}Crie a feature
Em src/features/my-entity/:
src/features/my-entity/
├── MyEntityPage.tsx # Pagina principal
└── components/
└── MyEntityForm.tsx # Formulario de criacao/edicaoAdicione a rota
Em src/routes/router.tsx:
const MyEntityPage = lazy(() => import("@/features/my-entity/MyEntityPage"));
// Dentro de AppLayout children:
{
path: "my-entity",
element: <SuspenseWrapper><MyEntityPage /></SuspenseWrapper>,
}Adicione a navegacao
Em src/lib/navigation.ts:
import { MyIcon } from "lucide-react";
export const mainNavItems: NavItem[] = [
// ... items existentes
{ title: "Minha Entidade", url: "/my-entity", icon: MyIcon },
];Verifique
bun run check-types
bun run lint
bun run build --filter=appSempre siga o padrao existente: hook por tabela, feature-based structure, e lazy loading nas rotas.