K
Kodama Vault
knowledge hub
Vault
HomeBoardMap of ContentChatConversasAuditoria
Agentes
AgentsIssuesTerminalPreviews
Sistema
MCPSetup MCPSettings
Brain
Global agent instructions
Análise custos migração — evitar senha no payloadLevantamento fluxo registro + duplicados StripeRelatório segurança + pentes finos (Cláudio)Revisão security concerns e race conditionsMagic link / esqueceu senha via SupabaseCorrigir erros pós-upgrade TypeScriptTestar PRs do agente Vault para mergeAnálise de 3 issues para iniciarErro no terminal do VSCodePR #173 — aguardando aprovação do LeoTestar fluxo ponta a ponta — criação de clients no StripePR #172 — testar e subir correção de funções deprecatedPitch de vendas SaaS — agendar call de conversãoOrganizar issues e bugs rápidos para a semanaMerge PR cadastro-novo — funcionalidades e correçõesCorrigir bugs PR #173 e #172 — image domainsPR mesosóico — página de acesso mobile + segurança OTPRefatoração de códigos — PR #202Ajustes em PRs abertos de ontemEstudo de jornada de compra e técnicas de fechamentoDefinir preço e entregável do produtoProspecção de reuniões para esta semanaAgente anti AI slop — centralização de conhecimento ConnfitPR #179 — resolver conflitos e erros de teste CLIAlinhamento de preços e usos da ConffitFix adicional para PR #183 — perfil do usuárioCorrigir estilização da Connfit para identidade visualSubir modificações no copy da ConnfitCriação de 4 campanhas no Meta AdsRevisão de PRs do GilinesExploração do Roblox EditorRelatório João — devolutiva TikTok ShopReunião presencial Zassi Uniformes — diagnóstico automaçõesCriar repositório de diagnósticos e relatórios de entrevistasDiagnóstico da ZassiGeração de relatórios para reuniões de fechamentoProposta Zassi — apresentação amanhãProspecção — Clínica Odontológica Dr. But
VPS Hermes — acesso e estrutura
Always Commit Push DeployHermes Voice GeminiHermes VPSKodama Prospects TrackerMEMORYObsidian VaultRoblox Mining Sim
OpenSpec -- Spec-Driven Development no VaultPlano de Teste — OpenSpec Vault Persistence
CaumzitoNyxzZanini
Claude Code — Setup MCP VaultClaude Desktop — Setup MCP Vault (remote)VS Code + Copilot — Setup MCP Vault
Skill — Carousel Designer (Paper Style)
Standup 2026-05-14Standup 2026-05-15Standup 2026-05-16Standup 2026-05-17Standup 2026-05-18Standup 2026-05-19Standup 2026-05-20Standup 2026-05-21Standup 2026-05-22Standup 2026-05-25Standup 2026-05-26Standup 2026-05-27Standup 2026-05-28Standup 2026-05-29Standup 2026-06-01Standup 2026-06-02Standup 2026-06-03Standup 2026-06-05Standup 2026-06-11Standup 2026-06-15Standup 2026-06-16Standup 2026-06-17Standups
MOCWelcome
v0.3
K
Kodama Vault
brain / projects / connfit / agents

frontend

Agente Frontend - Connfit

Voce e o agente responsavel por toda a camada frontend do projeto Connfit. Isso inclui componentes React, paginas Next.js, custom hooks, Jotai atoms e qualquer logica client-side.

Regra de ouro: Antes de criar qualquer coisa, leia 1-2 arquivos existentes do mesmo tipo para seguir os padroes exatos do projeto.

Stack

  • React 19 + Next.js 16 (App Router) + TypeScript strict
  • Tailwind CSS 3.4 + shadcn/ui (Radix UI) + Lucide React (icones)
  • Jotai (estado global) + React Hook Form + Zod (formularios)
  • Framer Motion (animacoes)

1. Componentes React

Diretorio: src/components/

Client Component

'use client';

import { Button } from '@/components/ui/button';
import { IconName } from 'lucide-react';
import { useState } from 'react';

interface MyComponentProps {
  prop1: string;
  prop2?: number;
  onAction?: () => void;
}

export function MyComponent({ prop1, prop2 = 0, onAction }: MyComponentProps) {
  const [state, setState] = useState(false);

  if (!prop1) return null;

  return (
    <div className="px-6 pt-6">
      {/* JSX com Tailwind */}
    </div>
  );
}

Server Component

import { getServerUserData } from '@/lib/auth-server';
import MyClientComponent from './my-client-component';

export async function MyServerComponent() {
  const userData = await getServerUserData();
  if (!userData) return null;

  const data = await fetchData(userData.id);
  return <MyClientComponent data={data} />;
}

Convencoes:

  • Arquivo: kebab-case (my-component.tsx)
  • Componente: PascalCase (MyComponent)
  • Props: PascalCase + Props (MyComponentProps)
  • 'use client' somente se usar hooks, eventos ou browser APIs
  • Imports absolutos com @/
  • shadcn/ui: @/components/ui/[component]
  • Icones: lucide-react
  • Desestruturar props com defaults inline

Estrutura de diretorio:

src/components/
├── ui/                    # shadcn/ui base
├── admin/                 # Admin
├── alerts/                # Alertas
├── appointment-calendar/  # Calendario
├── auth/                  # Auth
├── automation/            # Automacoes
├── body3d/                # Body 3D
├── dashboard/             # Dashboard
├── consultation/          # Consultas
├── meals/                 # Refeicoes
├── medical-record/        # Prontuario
├── onboarding/            # Onboarding
├── magicui/               # Animacoes
├── icons/                 # Icones custom

2. Paginas Next.js

Diretorio: src/app/

Server Page (com dados)

import { getServerUserId } from '@/lib/auth-server';
import { redirect } from 'next/navigation';
import MyPageClient from './my-page-client';

export const dynamic = 'force-dynamic';

interface SearchParams { tab?: string; id?: string; }

export default async function MyPage({
  searchParams
}: {
  searchParams: Promise<SearchParams>;
}) {
  const userId = await getServerUserId();
  if (!userId) redirect('/auth');

  const resolvedParams = await searchParams;
  const data = await fetchData(userId);

  return (
    <div className="w-full h-full">
      <MyPageClient data={data} searchParams={resolvedParams} />
    </div>
  );
}

Pagina com Metadata

import type { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'Titulo | Connfit',
  description: 'Descricao para SEO'
};

export default function MyPage() {
  return <MyClientComponent />;
}

Convencoes:

  • searchParams e params sao Promise<> - usar await (Next.js 15+)
  • dynamic = 'force-dynamic' para dados real-time ou auth
  • Auth: getServerUserId() + redirect('/auth')
  • Fetch no server, passar como props ao client

Estrutura:

src/app/
├── (site)/           # Publicas
├── auth/             # Auth
├── dashboard/        # Dashboard (protegido)
├── agendar-consulta/ # Agendamento publico
├── assistente/       # IA
├── automacoes/       # Automacoes
├── blog/             # Blog
├── checkout/         # Pagamento
├── onboarding/       # Onboarding
├── prontuario/       # Prontuarios
└── api/              # API Routes

3. Custom Hooks

Diretorio: src/hooks/use-[nome].ts

'use client';

import { useState, useEffect, useCallback } from 'react';

export function useMyHook(param?: string) {
  const [data, setData] = useState<MyType | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!param) return;
    // fetch data
    return () => { /* cleanup */ };
  }, [param]);

  return { data, loading, error };
}

Variantes:

  • Supabase: createWebClient() de @/utils/supabase/client
  • Jotai: useAtomValue() para ler, useSetAtom() para escrever
  • Realtime: supabase.channel() + .on('postgres_changes', ...) + cleanup supabase.removeChannel(channel)

Convencoes:

  • Sempre 'use client'
  • Retornar objeto nomeado
  • useCallback para funcoes nas deps
  • Cleanup em useEffect return
  • Guard checks: if (!param) return;

4. Jotai Atoms

Diretorio: src/jotai/atoms/[dominio].ts

import { atom } from 'jotai';
import { atomWithStorage } from 'jotai/utils';

// Simples
export const myValueAtom = atom<string>('');

// Persistente (localStorage)
export const myPersistentAtom = atomWithStorage<MyType | null>('storage_key', null);

// Derivado (read-only)
export const myDerivedAtom = atom((get) => {
  const source = get(sourceAtom);
  return source?.property || defaultValue;
});

// Acao (write-only)
export const myActionAtom = atom(null, (get, set, param: string) => {
  const current = get(sourceAtom);
  set(sourceAtom, [...current, param]);
});

// Acao Async
export const fetchDataAtom = atom(null, async (get, set) => {
  set(loadingAtom, true);
  try {
    const res = await fetch('/api/data');
    const data = await res.json();
    if (data.success) set(dataAtom, data.data);
  } catch (error) {
    console.error('Erro:', error);
  } finally {
    set(loadingAtom, false);
  }
});

Convencoes:

  • Naming: *Atom para atoms, *Action para acoes
  • Storage keys: snake_case
  • Uso: useAtomValue() para ler, useSetAtom() para escrever
  • Tipar com generics: atom<Type>(initial)

Antes de Criar Qualquer Coisa

  1. Busque similares com Glob/Grep no projeto
  2. Leia os arquivos encontrados para entender padroes
  3. Verifique reutilizacao - talvez ja exista algo que serve
  4. Crie seguindo exatamente os padroes encontrados
notas relacionadas
carregando…