Sobre este projeto
it-programming / web-development
Aberto
Contexto Geral do Projeto
1. Visão Geral da Arquitetura Tecnologias Principais Frontend: v0.dev (Vercel AI) para geração de componentes React/Next.js Backend/Banco de Dados: Supabase (PostgreSQL + APIs RESTful) Autenticação: Supabase Auth Armazenamento: Supabase Storage Estilo: Design inspirado na Apple com paleta azul Estrutura de Páginas Landing Page (pública) Login/Cadastro (pública) Dashboard (autenticada) Gerador de Posts (autenticada) Meus Posts (autenticada) Minha Marca (autenticada) Configurações (autenticada) Planos e Pagamentos (pública/autenticada) 2. Design System Inspirado na Apple Paleta de Cores Azul Principal: #0071E3 (Apple Blue) Azul Secundário: #147CE5 Azul Escuro: #0A4DA6 Cinza Claro: #F5F5F7 (Apple Light Gray - fundo) Branco: #FFFFFF (componentes, cards) Cinza Texto: #86868B (texto secundário) Preto Texto: #1D1D1F (texto principal) Verde Sucesso: #34C759 (Apple Green) Tipografia Fonte Principal: SF Pro Display (ou Inter como alternativa open-source) Pesos: Regular (400), Medium (500), Semibold (600) Tamanhos: Título Principal: 40px/2.5rem Subtítulo: 28px/1.75rem Título de Seção: 20px/1.25rem Texto Regular: 16px/1rem Texto Pequeno: 14px/0.875rem Componentes de UI Botões: Cantos arredondados (8px), sem borda, com sombra sutil Cards: Fundo branco, cantos arredondados (12px), sombra suave Inputs: Altura consistente, cantos arredondados (8px), borda leve Ícones: Estilo outline, consistentes, tamanho 20-24px 3. Landing Page Detalhada Hero Section Estrutura: Fundo gradiente azul suave para branco, imagem de mockup do app à direita Conteúdo: Título principal: "Posts profissionais para dentistas em minutos" Subtítulo: "Crie posts para redes sociais com sua logo e legendas otimizadas usando ia" cta primário: "comece grátis por 7 dias" (botão azul principal) cta secundário: "ver como funciona" (link/botão outline) prompt v0.dev: A hero section for a dental social media post generator called OdontoPost. Apple-inspired design with blue color scheme (#0071E3). Left side has headline "Posts profissionais para dentistas em minutos" and subheading "Crie posts para redes sociais com sua logo e legendas otimizadas usando IA". Two buttons: primary blue "Comece grátis por 7 dias" and secondary outline "Ver como funciona". Right side shows a mockup of the app interface with dental-themed social media posts. Clean, minimal design with ample white space. Seção "Como Funciona" Estrutura: 3-4 cards horizontais com ícones, numerados sequencialmente Conteúdo: "Escolha um template ou tema" (ícone de galeria) "Adicione sua logo automaticamente" (ícone de imagem) "Personalize e edite facilmente" (ícone de edição) "Publique ou agende seu post" (ícone de calendário) Prompt v0.dev: A "How It Works" section for OdontoPost with Apple-inspired design. Four horizontal steps with numbers, icons, and text. Step 1: "Escolha um template ou tema" with gallery icon. Step 2: "Adicione sua logo automaticamente" with image icon. Step 3: "Personalize e edite facilmente" with edit icon. Step 4: "Publique ou agende seu post" with calendar icon. Clean layout with subtle shadows and blue accents (#0071E3). Seção "Benefícios" Estrutura: Grid de 6 cards com ícones e texto curto Conteúdo: "Economize tempo" - "Crie posts em minutos, não horas" "Pareça profissional" - "Templates de alta qualidade para sua clínica" "Mantenha consistência" - "Sua identidade visual em todos os posts" "Aumente engajamento" - "Legendas otimizadas para seu público" "Conforme com CFO" - "Conteúdo dentro das normas éticas" "Atraia pacientes" - "Converta seguidores em clientes" Prompt v0.dev: A benefits section for OdontoPost with Apple-inspired design. Six cards in a 3x2 or 2x3 grid, each with an icon and short text. Cards include: "Economize tempo" with clock icon, "Pareça profissional" with badge icon, "Mantenha consistência" with repeat icon, "Aumente engajamento" with chart icon, "Conforme com CFO" with shield icon, and "Atraia pacientes" with magnet icon. Clean white cards with subtle shadows on light gray background. Blue accent color (#0071E3) for icons. Seção "Planos e Preços" Estrutura: Card único destacando o plano principal Conteúdo: Título: "Plano Profissional" Preço: "R$35/mês" Recursos: Lista de 5-7 funcionalidades principais CTA: "Comece seu teste grátis" Nota: "7 dias grátis, cancele quando quiser" Prompt v0.dev: A pricing section for OdontoPost with Apple-inspired design. Single featured plan card with "Plano Profissional" title. Price "R$35/mês" in large blue font. Features list including: "Posts ilimitados", "Integração de logo", "Legendas otimizadas", "Agendamento avançado", "Biblioteca de mídia", "Suporte prioritário". Blue CTA button "Comece seu teste grátis". Small text below "7 dias grátis, cancele quando quiser". Clean white card with subtle shadow on light gray background. Seção "Depoimentos" Estrutura: Slider/carrossel com 3 depoimentos visíveis Conteúdo: Foto do dentista, nome, especialidade, texto do depoimento Prompt v0.dev: A testimonials carousel for OdontoPost with Apple-inspired design. Three visible testimonial cards from dentists. Each card has a small circular avatar, name, specialty, and quote. Example: "Dra. Ana Silva, Ortodontista" with quote "O OdontoPost revolucionou minha presença nas redes sociais. Economizo horas toda semana!". Clean white cards with subtle shadows, blue accents, and quote marks. Navigation dots or arrows below. Seção "FAQ" Estrutura: Acordeão/expansível com 5-6 perguntas frequentes Conteúdo: Perguntas relevantes sobre o serviço, preço, cancelamento Prompt v0.dev: An FAQ accordion section for OdontoPost with Apple-inspired design. 5-6 expandable questions with clean borders and plus/minus icons. Questions include: "Como funciona o período de teste?", "Posso cancelar quando quiser?", "Como adiciono minha logo?", "Quantos posts posso criar?", "O conteúdo está de acordo com as normas do CFO?". Blue accent color (#0071E3) for expanded items. Clean, minimal design on light background. Footer Estrutura: Logo, links de navegação, links legais, copyright Conteúdo: Links para Sobre, Contato, Termos, Privacidade Prompt v0.dev: A footer for OdontoPost with Apple-inspired design. Logo on left, navigation links in center (Sobre, Como Funciona, Preços, Contato), legal links (Termos de Uso, Política de Privacidade) and copyright "© 2025 OdontoPost. Todos os direitos reservados." Clean, minimal design with subtle top border. 4. Fluxo de Login/Cadastro Página de Login Estrutura: Card centralizado com logo, formulário, links auxiliares Campos: Email Senha Checkbox "Lembrar de mim" Botão "Entrar" Link "Esqueci minha senha" Separador Botão "Continuar com Google" (opcional) Link "Criar uma conta" Prompt v0.dev: A login page for OdontoPost with Apple-inspired design. Centered white card with logo at top. Form with email and password fields, "Lembrar de mim" checkbox, and blue "Entrar" button. "Esqueci minha senha" link below. Optional divider with "ou" text, followed by "Continuar com Google" button with Google icon. "Criar uma conta" link at bottom. Clean, minimal design with subtle shadows on light gray background. Página de Cadastro Estrutura: Card centralizado com logo, formulário em etapas Etapa 1 - Informações Básicas: Nome completo Email Senha Confirmar senha Botão "Continuar" Etapa 2 - Informações Profissionais: Nome da clínica Especialidade (dropdown) Telefone Botão "Criar conta" Prompt v0.dev para Etapa 1: A signup page (step 1) for OdontoPost with Apple-inspired design. Centered white card with logo at top and progress indicator showing step 1 of 2. Form with fields for "Nome completo", "Email", "Senha", and "Confirmar senha". Blue "Continuar" button at bottom. "Já tem uma conta? Entrar" link below. Clean, minimal design with subtle shadows on light gray background. Fluxo de Onboarding Estrutura: Série de 3 telas após cadastro bem-sucedido Etapa 1 - Upload de Logo: Área de arrastar e soltar para upload Botão alternativo "Selecionar arquivo" Botão "Continuar" e "Pular por enquanto" Etapa 2 - Preferências de Conteúdo: Seleção de especialidades de interesse (múltipla escolha) Seleção de tipos de conteúdo preferidos (múltipla escolha) Botão "Continuar" e "Pular por enquanto" Etapa 3 - Conclusão: Mensagem de boas-vindas Resumo das próximas etapas Botão "Começar a criar posts" Prompt v0.dev para Etapa 1: An onboarding screen (step 1) for OdontoPost with Apple-inspired design. Progress indicator showing step 1 of 3. Title "Adicione sua logo" with subtitle "Sua logo será aplicada automaticamente nos posts". Large dashed border upload area with cloud icon and "Arraste e solte sua logo aqui" text. "Selecionar arquivo" button below. Blue "Continuar" button and gray "Pular por enquanto" link at bottom. Clean, minimal design with subtle shadows on light background. 5. Páginas Internas e Funcionalidades Dashboard (Página Inicial após Login) Estrutura: Layout com sidebar à esquerda, header no topo, conteúdo principal Componentes: Sidebar: Logo, navegação principal, status do plano Header: Barra de pesquisa, notificações, perfil do usuário Conteúdo: Widgets de resumo e ações rápidas Widgets: "Criar Novo Post" (CTA principal) "Posts Recentes" (últimos 3-4 posts criados) "Atividade" (estatísticas básicas) "Dicas e Sugestões" (recomendações de conteúdo) Prompt v0.dev: A dashboard for OdontoPost with Apple-inspired design. Left sidebar with logo at top, navigation menu items (Dashboard, Criar Post, Meus Posts, Minha Marca, Configurações) with icons, and plan status at bottom. Top header with search bar, notification bell, and user profile. Main content area with 4 widgets: 1) Large blue "Criar Novo Post" CTA card, 2) "Posts Recentes" card showing 3 recent post thumbnails with dates, 3) "Atividade" card with basic stats and small charts, 4) "Dicas e Sugestões" card with content recommendations. Clean white cards with subtle shadows on light gray background (#F5F5F7). Blue accent color (#0071E3) for interactive elements. Gerador de Posts (Fluxo Principal) Etapa 1: Escolha de Template Estrutura: Galeria de templates com filtros e categorias Componentes: Filtros por categoria (Educativo, Promocional, Datas, etc.) Grid de templates com miniaturas Paginação ou scroll infinito Botão "Próximo" no rodapé Prompt v0.dev: A template selection page for OdontoPost with Apple-inspired design. Top section has filter tabs (Todos, Educativo, Promocional, Datas Especiais, Antes/Depois). Below is a grid of 8-12 template thumbnails, each showing a dental-themed social media post design. Each thumbnail has hover effect with "Selecionar" button. Templates show various dental content like smiles, dental procedures, and educational graphics. Bottom has blue "Próximo" button. Clean, minimal design with white cards on light gray background (#F5F5F7). Etapa 2: Personalização Visual Estrutura: Layout de duas colunas - preview à esquerda, controles à direita Componentes: Preview grande do post em tempo real Seção "Logo" com upload/seleção Seção "Texto" com campos editáveis Seção "Cores" com opções limitadas Botões "Voltar" e "Próximo" Prompt v0.dev: A post customization page for OdontoPost with Apple-inspired design. Two-column layout: left shows large preview of dental social media post with logo applied, right has customization controls. Control sections include: 1) "Logo" with current logo thumbnail and "Alterar" button, 2) "Texto" with editable text fields that correspond to text in the preview, 3) "Cores" with limited color options showing blue circles. Bottom has "Voltar" link and blue "Próximo" button. Clean interface with real-time preview updating as changes are made. Etapa 3: Criação de Legenda Estrutura: Preview do post no topo, editor de legenda abaixo Componentes: Miniatura do post finalizado Abas "Sugestões da IA" e "Escrever Manualmente" Cards de sugestões de legenda (3-4) Editor de texto com formatação básica Contador de caracteres Botões "Voltar" e "Próximo" Prompt v0.dev: A caption creation page for OdontoPost with Apple-inspired design. Top shows the finalized post thumbnail. Below are two tabs: "Sugestões da IA" (selected) and "Escrever Manualmente". Under the selected tab are 3 suggestion cards, each with a different caption for the dental post, including emojis and hashtags. Each card has a "Usar esta legenda" button. At bottom is a character counter showing "0/2200" and navigation buttons: "Voltar" link and blue "Próximo" button. Clean, minimal design with white cards on light background. Etapa 4: Agendamento e Publicação Estrutura: Resumo do post no topo, opções de publicação abaixo Componentes: Preview final do post com legenda Seleção de redes sociais (Instagram, Facebook, etc.) Opções "Publicar agora" ou "Agendar" Seletor de data e hora para agendamento Botões "Voltar" e "Finalizar" Prompt v0.dev: A scheduling page for OdontoPost with Apple-inspired design. Top shows final preview of dental post with caption. Below are social media platform checkboxes (Instagram, Facebook, Twitter) with platform icons. Publication options include radio buttons for "Publicar agora" and "Agendar para depois" (selected). When "Agendar" is selected, date and time pickers appear with calendar interface showing current month. Bottom has "Voltar" link and blue "Finalizar" button. Clean, minimal design with subtle animations for selection states. Meus Posts (Gerenciamento) Estrutura: Lista/grid de posts com filtros e ações Componentes: Filtros por status (Agendado, Publicado, Rascunho) Barra de pesquisa Grid de posts com miniaturas Menu de ações por post (Editar, Duplicar, Excluir) Paginação Prompt v0.dev: A "My Posts" management page for OdontoPost with Apple-inspired design. Top has filter tabs (Todos, Agendados, Publicados, Rascunhos) and search bar. Main content shows a grid of post cards, each with post thumbnail, publication date/status, and platform icons. Each card has a three-dot menu for actions (Editar, Duplicar, Excluir). Empty states show helpful messages like "Nenhum post agendado" with illustration. Pagination controls at bottom. Clean, minimal design with white cards on light gray background. Minha Marca (Configurações de Identidade) Estrutura: Formulário com seções para elementos de marca Componentes: Seção "Logo" com upload e visualização Seção "Cores" com seleção de paleta Seção "Informações da Clínica" com campos de texto Botão "Salvar Alterações" Prompt v0.dev: A "My Brand" settings page for OdontoPost with Apple-inspired design. Page has sections: 1) "Logo" with current logo display, upload area, and tips for best results, 2) "Cores" with color picker for primary and secondary brand colors showing blue swatches, 3) "Informações da Clínica" with form fields for clinic name, address, phone, and website. Bottom has blue "Salvar Alterações" button. Clean, organized layout with section dividers and helpful tooltips. White card sections on light gray background. Configurações (Conta e Preferências) Estrutura: Tabs/abas para diferentes categorias de configurações Componentes: Aba "Perfil" com informações pessoais Aba "Notificações" com toggles Aba "Assinatura" com detalhes do plano Aba "Segurança" com senha e 2FA Prompt v0.dev: A settings page for OdontoPost with Apple-inspired design. Left side has vertical tabs: "Perfil" (selected), "Notificações", "Assinatura", "Segurança". Right side shows content for selected tab. For "Perfil" tab: form with user information fields (Nome, Email, Telefone, Especialidade) and profile picture upload. Each section has "Editar" and "Salvar" buttons. Clean, organized layout with clear section headings and subtle dividers. Blue accent color (#0071E3) for buttons and interactive elements. 6. Integrações com Supabase Estrutura de Banco de Dados Tabelas Principais users id (pk) email name phone specialty created_at clinics id (pk) user_id (fk) name address phone website created_at brand_assets id (pk) user_id (fk) logo_url primary_color secondary_color created_at updated_at posts id (pk) user_id (fk) template_id (fk) title image_url caption status (draft, scheduled, published) scheduled_for published_at platforms (array) created_at updated_at templates id (pk) name category image_url editable_fields (json) created_at configuração do supabase javascript // exemplo de configuração do supabase no frontend import { createclient } from '@supabase/supabase-js' const supabaseurl = 'https://seu-projeto.supabase.co' const supabaseKey = 'sua-chave-publica' const supabase = createClient(supabaseUrl, supabaseKey ) // Exemplo de autenticação const signUp = async (email, password, userData) => { const { user, error } = await supabase.auth.signUp({ email, password, options: { data: userData } }) return { user, error } } Armazenamento de Arquivos javascript // Exemplo de upload de logo const uploadLogo = async (file, userId) => { const fileExt = file.name.split('.').Pop() const fileName = `${userId}/logo.${FileExt}` const { data, error } = await supabase.storage .from('logos') .upload(fileName, file, { upsert: true }) return { data, error } } 7. APIs Públicas e Integrações APIs Recomendadas para Geração de Conteúdo 1. Openai api (dall-e e gpt) funcionalidade: geração de imagens e textos com ia uso no odontopost: geração de variações de templates com dall-e criação de legendas personalizadas com gpt implementação: javascript // exemplo de integração com openai via edge function no supabase // arquivo: /supabase/functions/generate-caption/index.ts import { serve } from 'https://deno.land/std@0.168.0/http/server.ts' import { createClient } from 'https://esm.sh/@supabase/supabase-js@2' import { Configuration, OpenAIApi } from 'https://esm.sh/openai@3.2.1' serve(async (req ) => { const { templateId, clinicInfo } = await req.json() // Inicializar OpenAI const configuration = new Configuration({ apiKey: Deno.env.get('OPENAI_API_KEY'), }) const openai = new OpenAIApi(configuration) // Buscar informações do template const supabase = createClient( Deno.env.get('SUPABASE_URL') ?? '', Deno.env.get('SUPABASE_ANON_KEY') ?? '' ) const { data: template } = await supabase .from('templates') .select('*') .eq('id', templateId) .single() // Gerar legenda com GPT const prompt = `Crie uma legenda para post de Instagram para uma clínica odontológica sobre ${template.topic}. Nome da clínica: ${clinicInfo.name}. Especialidade: ${clinicInfo.specialty}. Inclua 3-5 hashtags relevantes e um call-to-action. Limite: 200 caracteres.` Const completion = await openai.createCompletion({ model: "gpt-3.5-turbo-instruct", prompt, max_tokens: 200, temperature: 0.7, }) return new Response( JSON.stringify({ caption: completion.data.choices[0].text }), { headers: { 'Content-Type': 'application/json' } }, ) }) 2. Shotstack API Funcionalidade: Geração e edição de imagens programaticamente Uso no OdontoPost: Aplicação automática de logo em templates Personalização de cores e textos em templates Implementação: javascript // Exemplo de integração com Shotstack via Edge Function // Arquivo: /supabase/functions/generate-post/index.ts import { serve } from 'https://deno.land/std@0.168.0/http/server.ts' import { createClient } from 'https://esm.sh/@supabase/supabase-js@2' serve(async (req ) => { const { templateId, logoUrl, text, colors } = await req.json() // Configuração Shotstack const apiKey = Deno.env.get('SHOTSTACK_API_KEY') const endpoint = 'https://api.shotstack.io/stage' // Montar payload para Shotstack const payload = { timeline: { background: colors.background || "#FFFFFF", tracks: [ { clips: [ { asset: { type: "image", src: templateId // URL do template base }, start: 0, length: 1 }, { asset: { type: "image", src: logoUrl // URL da logo do usuário }, start: 0, length: 1, position: "bottomRight", scale: 0.2 }, { asset: { type: "html", html: `<p style="color:${colors.text || "#000000"}">${text}</p>` }, start: 0, length: 1, position: "center" } ] } ] }, output: { format: "png", resolution: "1080x1080" } } // Chamar API Shotstack const response = await fetch(`${endpoint}/render`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }, body: JSON.stringify(payload ) }) const result = await response.json() return new Response( JSON.stringify({ id: result.response.id }), { headers: { 'Content-Type': 'application/json' } }, ) }) 3. Predis.ai API Funcionalidade: API especializada em geração de conteúdo para redes sociais Uso no OdontoPost: Geração de posts completos (imagem + legenda) Sugestões de hashtags relevantes Implementação: javascript // Exemplo de integração com Predis.ai // Arquivo: /pages/api/generate-social-post.js (Next.js) export default async function handler(req, res) { const { topic, brand } = req.body const response = await fetch('https://api.predis.ai/v1/generate/social-post', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.PREDIS_API_KEY}` }, body: JSON.stringify({ topic, brand, platform: 'instagram', industry: 'dental', tone: 'professional' } ) }) const data = await response.json() res.status(200).json(data) } 4. Unsplash API Funcionalidade: Acesso a banco de imagens gratuitas de alta qualidade Uso no OdontoPost: Imagens de fundo para templates Elementos visuais complementares Implementação: javascript // Exemplo de busca de imagens odontológicas no Unsplash // Arquivo: /lib/unsplash.js export async function searchDentalImages(query = 'dental smile', count = 10) { const response = await fetch( `https://api.unsplash.com/search/photos?query=${query}&per_page=${count}&orientation=square`, { headers: { 'Authorization': `Client-ID ${process.env.UNSPLASH_ACCESS_KEY}` } } ) const data = await response.json() return data.results.map(image => ({ id: image.id, url: image.urls.regular, thumb: image.urls.thumb, credit: { name: image.user.name, link: image.user.links.html } })) } Fluxo Completo de Integração com Supabase Autenticação e Gerenciamento de Usuários javascript // Configuração do Auth no Supabase // Arquivo: /lib/supabase.js import { createClient } from '@supabase/supabase-js' const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY export const supabase = createClient(supabaseUrl, supabaseAnonKey) // Funções de autenticação export async function signUp(email, password, userData) { return await supabase.auth.signUp({ email, password, options: { data: userData } }) } export async function signIn(email, password) { return await supabase.auth.signInWithPassword({ email, password }) } export async function signOut() { return await supabase.auth.signOut() } // Configurar gatilhos para criar perfil de usuário após cadastro // No Supabase SQL Editor: /* create function public.handle_new_user() returns trigger as $$ begin insert into public.profiles (id, email, name) values (new.id, new.email, new.raw_user_meta_data->>'name'); insert into public.brand_assets (user_id) values (new.id); return new; end; $$ language plpgsql security definer; create trigger on_auth_user_created after insert on auth.users for each row execute procedure public.handle_new_user(); */ Gerenciamento de Posts e Templates javascript // Funções para gerenciar posts // Arquivo: /lib/posts.js import { supabase } from './Supabase' // Buscar templates disponíveis export async function getTemplates(category = null) { let query = supabase.from('templates').select('*') if (category) { query = query.eq('category', category) } const { data, error } = await query.order('created_at', { ascending: false }) if (error) throw error return data } // Criar novo post export async function createPost(postData) { const { data, error } = await supabase .from('posts') .insert([postData]) .select() if (error) throw error return data[0] } // Buscar posts do usuário export async function getUserPosts(userId, status = null) { let query = supabase .from('posts') .select('*, templates(*)') .eq('user_id', userId) if (status) { query = query.eq('status', status) } const { data, error } = await query.order('created_at', { ascending: false }) if (error) throw error return data } // Atualizar post export async function updatePost(postId, updates) { const { data, error } = await supabase .from('posts') .update(updates) .eq('id', postId) .select() if (error) throw error return data[0] } Upload e Gerenciamento de Arquivos javascript // Funções para gerenciar arquivos // Arquivo: /lib/storage.js import { supabase } from './Supabase' import { v4 as uuidv4 } from 'uuid' // Upload de logo export async function uploadLogo(file, userId) { const fileExt = file.name.split('.').Pop() const fileName = `${userId}/${uuidv4()}.${FileExt}` const filePath = `${fileName}` const { data, error } = await supabase.storage .from('logos') .upload(filePath, file, { cacheControl: '3600', upsert: false }) if (error) throw error // Atualizar URL da logo no perfil do usuário const { publicURL } = supabase.storage .from('logos') .getPublicUrl(filePath) await supabase .from('brand_assets') .update({ logo_url: publicURL }) .eq('user_id', userId) return publicURL } // Upload de post gerado export async function uploadGeneratedPost(imageBlob, userId, postId) { const fileName = `${userId}/${postId}.png` const { data, error } = await supabase.storage .from('posts') .upload(fileName, imageBlob, { cacheControl: '3600', upsert: true, contentType: 'image/png' }) if (error) throw error const { publicURL } = supabase.storage .from('posts') .getPublicUrl(fileName) // Atualizar URL da imagem no post await supabase .from('posts') .update({ image_url: publicURL }) .eq('id', postId) return publicURL } Políticas de Segurança do Supabase Para garantir a segurança dos dados, configure as seguintes políticas no Supabase: sql -- Políticas para tabela 'profiles' create policy "usuários podem ver apenas seu próprio perfil" on profiles for select using (auth.Uid() = id); create policy "usuários podem atualizar apenas seu próprio perfil" on profiles for update using (auth.uid() = id); -- Políticas para tabela 'posts' create policy "usuários podem ver apenas seus próprios posts" on posts for select using (auth.Uid() = user_id); create policy "usuários podem criar seus próprios posts" on posts for insert with check (auth.Uid() = user_id); create policy "usuários podem atualizar apenas seus próprios posts" on posts for update using (auth.Uid() = user_id); create policy "usuários podem excluir apenas seus próprios posts" on posts for delete using (auth.uid() = user_id); -- Políticas para storage create policy "arquivos de logo acessíveis publicamente" on storage.Objects for select using (bucket_id = 'logos'); create policy "usuários podem fazer upload apenas em sua pasta" on storage.Objects for insert with check (bucket_id in ('logos', 'posts') and (storage.foldername(name))[1] = auth.uid()::text); 8. APIs Específicas para Funções Essenciais do OdontoPost 1. Geração de Posts com Logo Replicate API (Stable Diffusion) Funcionalidade: Geração de imagens de alta qualidade com IA Vantagens: Mais acessível que OpenAI, permite controle fino de parâmetros Implementação: javascript // Exemplo de integração com Replicate para geração de imagens odontológicas // Arquivo: /lib/replicate.js export async function generateDentalImage(prompt, logoUrl) { const response = await fetch("https://api.replicate.com/v1/predictions", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Token ${process.env.REPLICATE_API_KEY}`, }, body: JSON.stringify({ version: "a9758cbfbd5f3c2094457d996681af52552901775aa2d6dd0b17fd15df959bef", input: { prompt: `Professional dental clinic image, ${prompt}, clean, modern, high quality`, negative_prompt: "low quality, blurry, amateur", width: 1080, height: 1080, num_inference_steps: 50 }, } ), }); const prediction = await response.json(); const imageUrl = prediction.urls.get; // Agora podemos usar Shotstack para adicionar a logo return await addLogoToImage(imageUrl, logoUrl); } async function addLogoToImage(imageUrl, logoUrl) { // Implementação com Shotstack ou outra API de composição de imagens // ... } Cloudinary API Funcionalidade: Manipulação e transformação de imagens Uso no OdontoPost: Aplicação de logo em templates Redimensionamento e otimização de imagens Aplicação de filtros e efeitos Implementação: javascript // Exemplo de integração com Cloudinary // Arquivo: /lib/cloudinary.js import { v2 as cloudinary } from 'cloudinary'; cloudinary.config({ cloud_name: process.env.CLOUDINARY_CLOUD_NAME, api_key: process.env.CLOUDINARY_API_KEY, api_secret: process.env.CLOUDINARY_API_SECRET }); export async function overlayLogoOnTemplate(templateUrl, logoUrl, position = "south_east") { // Primeiro, fazemos upload da logo para Cloudinary (se ainda não estiver lá) const logoUpload = await cloudinary.uploader.upload(logoUrl, { folder: "logos", transformation: [ {width: 200, height: 200, crop: "fit"}, {background: "transparent"} ] }); // Agora criamos uma transformação que sobrepõe a logo no template const publicId = templateUrl.split('/').pop().split('.')[0]; const result = await cloudinary.uploader.explicit(publicId, { type: "upload", eager: [ { overlay: `logos:${logoUpload.public_id.split('/').pop()}`, width: 150, gravity: position, x: 20, y: 20 } ] }); return result.eager[0].url; } 2. Geração de Legendas Otimizadas Openai api (gpt-4) funcionalidade: geração de texto natural e contextual uso no odontopost: criação de legendas personalizadas para posts sugestões de hashtags relevantes adaptação de tom de voz conforme preferência implementação: javascript // exemplo de integração com openai para legendas // arquivo: /lib/openai.js import OpenAI from 'openai'; const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); export async function generateCaption(templateInfo, clinicInfo, tone = "professional") { const systemPrompt = `Você é um especialista em marketing digital para clínicas odontológicas. Crie uma legenda para Instagram que seja envolvente, profissional e conforme as normas do CFO (sem preços, sem promessas de resultados, sem "antes e depois"). Use um tom ${tone === "professional" ? "profissional e informativo" : tone === "friendly" ? "amigável e acolhedor" : "educativo e explicativo"}. Inclua 3-5 hashtags relevantes e um call-to-action sutil no final.`; Const userPrompt = `Crie uma legenda para um post sobre ${templateInfo.topic} para a clínica ${clinicInfo.name}, especializada em ${clinicInfo.specialty}.`; Const completion = await openai.chat.completions.create({ model: "gpt-4", messages: [ { role: "system", content: systemPrompt }, { role: "user", content: userPrompt } ], max_tokens: 300, temperature: 0.7, }); return completion.choices[0].message.content; } Cohere API Funcionalidade: Alternativa ao OpenAI para geração de texto Vantagens: Preços mais acessíveis, bom desempenho em português Implementação: javascript // Exemplo de integração com Cohere // Arquivo: /lib/cohere.js export async function generateCaption(topic, clinicInfo) { const response = await fetch('https://api.cohere.ai/v1/generate', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.COHERE_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'command', prompt: `Crie uma legenda profissional para Instagram sobre ${topic} para uma clínica odontológica chamada ${clinicInfo.name}, especializada em ${clinicInfo.specialty}. Inclua 3-5 hashtags relevantes e um call-to-action sutil no final.`, Max_tokens: 300, temperature: 0.7, k: 0, stop_sequences: [], return_likelihoods: 'NONE' } ) }); const data = await response.json(); return data.generations[0].text; } 3. Agendamento e Publicação de Posts Buffer API Funcionalidade: Agendamento e publicação em redes sociais Uso no OdontoPost: Agendamento de posts para múltiplas plataformas Análise de melhores horários Monitoramento de publicações Implementação: javascript // Exemplo de integração com Buffer // Arquivo: /lib/buffer.js export async function schedulePost(imageUrl, caption, platforms, scheduleTime) { // Primeiro, obter perfis conectados const profilesResponse = await fetch('https://api.bufferapp.com/1/profiles.json', { headers: { 'Authorization': `Bearer ${process.env.BUFFER_ACCESS_TOKEN}` } } ); const profiles = await profilesResponse.json(); // Filtrar perfis pelas plataformas selecionadas const selectedProfiles = profiles.filter(profile => platforms.includes(profile.service.toLowerCase()) ); // Agendar post para cada perfil selecionado const results = await Promise.all(selectedProfiles.map(async (profile) => { const response = await fetch('https://api.bufferapp.com/1/updates/create.json', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.BUFFER_ACCESS_TOKEN}`, 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ 'profile_ids[]': profile.id, 'text': caption, 'media[photo]': imageUrl, 'scheduled_at': scheduleTime ? new Date(scheduleTime ).toISOString() : '' }) }); return response.json(); })); return results; } Zapier Integration Alternativa: Para usuários sem acesso direto à API do Buffer Implementação: Webhook para Zapier que aciona fluxos de publicação javascript // Exemplo de integração com Zapier via webhook // Arquivo: /pages/api/schedule-post.js export default async function handler(req, res) { const { imageUrl, caption, platforms, scheduleTime, userId } = req.body; // Salvar no Supabase const { data, error } = await supabase .from('posts') .insert({ user_id: userId, image_url: imageUrl, caption, platforms, scheduled_for: scheduleTime, status: 'scheduled' }) .select(); if (error) { return res.status(500).json({ error }); } // Enviar para Zapier webhook const zapierResponse = await fetch(process.env.ZAPIER_WEBHOOK_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ imageUrl, caption, platforms, scheduleTime, postId: data[0].id }) }); return res.status(200).json({ success: true, post: data[0] }); } 4. Biblioteca de Templates e Imagens Pexels API Funcionalidade: Acesso a banco de imagens gratuitas de alta qualidade Vantagens: Foco em fotos profissionais, API gratuita com limites generosos Implementação: javascript // Exemplo de integração com Pexels // Arquivo: /lib/pexels.js export async function searchDentalImages(query = 'dental smile', perPage = 20) { const response = await fetch( `https://api.pexels.com/v1/search?query=${query}&per_page=${perPage}`, { headers: { Authorization: process.env.PEXELS_API_KEY } } ); const data = await response.json(); return data.photos.map(photo => ({ id: photo.id, url: photo.src.large, thumb: photo.src.medium, width: photo.width, height: photo.height, photographer: photo.photographer, photographerUrl: photo.photographer_url })); } Pixabay API Funcionalidade: Alternativa para banco de imagens gratuitas Vantagens: Grande volume de imagens, incluindo ilustrações e vetores Implementação: javascript // Exemplo de integração com Pixabay // Arquivo: /lib/pixabay.js export async function searchDentalImages(query = 'dental', perPage = 20) { const response = await fetch( `https://pixabay.com/api/?key=${process.env.PIXABAY_API_KEY}&q=${query}&image_type=photo&per_page=${perPage}`, { headers: { 'Content-Type': 'application/json' } } ); const data = await response.json(); return data.hits.map(image => ({ id: image.id, url: image.largeImageURL, thumb: image.webformatURL, width: image.imageWidth, height: image.imageHeight, user: image.user, userUrl: `https://pixabay.com/users/${image.user}-${image.user_id}/` } )); } 5. Análise e Métricas Google Analytics API Funcionalidade: Rastreamento e análise de tráfego e conversões Uso no OdontoPost: Monitoramento de desempenho de links em posts Análise de conversões de pacientes Relatórios de crescimento Implementação: javascript // Exemplo de integração com Google Analytics // Arquivo: /lib/analytics.js import { BetaAnalyticsDataClient } from '@google-analytics/data'; const analyticsDataClient = new BetaAnalyticsDataClient({ credentials: JSON.parse(process.env.GOOGLE_ANALYTICS_CREDENTIALS) }); export async function getPostPerformance(userId, startDate, endDate) { const propertyId = process.env.GA_PROPERTY_ID; // Buscar UTMs específicos do usuário const [response] = await analyticsDataClient.runReport({ property: `properties/${propertyId}`, dateRanges: [ { startDate, endDate, }, ], dimensions: [ { name: 'customEvent:post_id', }, ], metrics: [ { name: 'eventCount', }, { name: 'conversions', }, ], dimensionFilter: { filter: { fieldName: 'customEvent:user_id', stringFilter: { matchType: 'EXACT', value: userId, }, }, }, }); return response.rows.map(row => ({ postId: row.dimensionValues[0].value, views: parseInt(row.metricValues[0].value), conversions: parseInt(row.metricValues[1].value) })); } Simple Analytics API Funcionalidade: Alternativa mais simples para análise de tráfego Vantagens: Fácil implementação, sem cookies, respeita privacidade Implementação: javascript // Exemplo de integração com Simple Analytics // Arquivo: /lib/simple-analytics.js export async function getPostStats(websiteId, path, startDate, endDate) { const response = await fetch( `https://api.simpleanalytics.io/v1/websites/${websiteId}/stats?start=${startDate}&end=${endDate}&path=${path}`, { headers: { 'Content-Type': 'application/json', 'Api-Key': process.env.SIMPLE_ANALYTICS_API_KEY } } ); const data = await response.json(); return { pageviews: data.pageviews, visitors: data.visitors, bounceRate: data.bounce_rate, referrers: data.referrers }; } 9. Guia Passo a Passo para Implementação com v0.dev Etapa 1: Configuração Inicial Criar projeto Supabase Acesse https://supabase.com e crie uma nova conta/projeto Anote a URL e a chave anônima do projeto Configure as tabelas conforme estrutura definida na seção 6 Configurar v0.dev para gerar componentes Acesse https://v0.dev e autentique-se Prepare-se para usar os prompts detalhados nas seções anteriores Configurar variáveis de ambiente Crie um arquivo .env.local com as seguintes variáveis: NEXT_PUBLIC_SUPABASE_URL=sua_url_supabase NEXT_PUBLIC_SUPABASE_ANON_KEY=sua_chave_anonima OPENAI_API_KEY=sua_chave_openai CLOUDINARY_CLOUD_NAME=seu_cloud_name CLOUDINARY_API_KEY=sua_api_key CLOUDINARY_API_SECRET=seu_api_secret PEXELS_API_KEY=sua_chave_pexels Etapa 2: Desenvolvimento da Landing Page Gerar componentes com v0.dev Use os prompts da seção 3 para gerar cada seção da landing page Copie o código gerado para arquivos separados em /components/landing/ Montar a página inicial Crie /app/page.tsx importando os componentes gerados Adicione estilos globais em /app/globals.css Implementar responsividade Ajuste os componentes para diferentes tamanhos de tela Teste em dispositivos móveis e desktop Etapa 3: Implementação do Sistema de Autenticação Gerar componentes de login/cadastro Use os prompts da seção 4 para gerar os formulários Salve em /components/auth/ Integrar com Supabase Auth Implemente as funções de autenticação conforme seção 7 Crie páginas de login e cadastro em /app/(auth )/ Configurar proteção de rotas Implemente middleware para proteger rotas autenticadas Configure redirecionamentos apropriados Etapa 4: Desenvolvimento do Dashboard Gerar componentes do dashboard Use os prompts da seção 5 para gerar layout e widgets Organize em /components/dashboard/ Implementar sidebar e navegação Crie componente de layout em /app/dashboard/layout.tsx Configure rotas para todas as seções internas Integrar com Supabase para dados do usuário Busque informações do perfil e estatísticas Exiba dados dinâmicos nos widgets Etapa 5: Implementação do Gerador de Posts Gerar componentes do fluxo de criação Use os prompts da seção 5 para cada etapa do fluxo Organize em /components/post-generator/ Implementar seleção de templates Integre com Supabase para buscar templates Implemente filtros e paginação Implementar personalização visual Integre com Cloudinary para manipulação de imagens Implemente upload e posicionamento de logo Implementar geração de legendas Integre com OpenAI ou Cohere para sugestões Implemente editor de texto para personalização Implementar agendamento Integre com Buffer ou webhook para Zapier Salve informações de agendamento no Supabase Etapa 6: Implementação da Biblioteca de Posts Gerar componentes de gerenciamento Use os prompts da seção 5 para a página "Meus Posts" Organize em /components/posts-library/ Implementar listagem e filtros Busque posts do usuário no Supabase Implemente filtros por status e busca Implementar ações de gerenciamento Adicione funcionalidades de editar, duplicar e excluir Implemente visualização detalhada de cada post Etapa 7: Configurações e Perfil Gerar componentes de configurações Use os prompts da seção 5 para páginas de configuração Organize em /components/settings/ Implementar gerenciamento de marca Integre upload de logo com Supabase Storage Implemente seleção de cores e informações da clínica Implementar configurações de conta Adicione formulários para atualização de perfil Implemente gerenciamento de assinatura Etapa 8: Testes e Otimizações Testar fluxos completos Verifique todo o processo de criação e agendamento Teste em diferentes dispositivos e navegadores Otimizar desempenho Implemente carregamento lazy de componentes Otimize consultas ao Supabase Implementar análise e rastreamento Adicione Google Analytics ou Simple Analytics Configure eventos para monitorar conversões Etapa 9: Implantação Preparar para produção Verifique variáveis de ambiente Otimize assets e imagens Implantar na Vercel ou similar Configure domínio personalizado Configure integrações contínuas Monitorar e iterar Acompanhe métricas de uso Colete feedback e implemente melhorias 10. APIs Adicionais para Funcionalidades Avançadas 1. APIs para Análise de Métricas do Instagram Meta Graph API (Instagram Insights) Funcionalidade: API oficial do Instagram para métricas e insights Uso no OdontoPost: Análise de desempenho de posts Monitoramento de crescimento de seguidores Métricas de engajamento (curtidas, comentários, salvamentos) Implementação: javascript // Exemplo de integração com Meta Graph API para Instagram Insights // Arquivo: /lib/instagram.js export async function getInstagramInsights(accessToken, instagramBusinessAccountId) { // Obter métricas da conta const accountResponse = await fetch( `https://graph.facebook.com/v18.0/${instagramBusinessAccountId}?fields=followers_count,media_count&access_token=${accessToken}` ); const accountData = await accountResponse.json(); // Obter métricas dos últimos posts const postsResponse = await fetch( `https://graph.facebook.com/v18.0/${instagramBusinessAccountId}/media?fields=id,caption,media_type,media_url,permalink,thumbnail_url,timestamp,username,insights.metric(impressions,reach,engagement,saved )&limit=10&access_token=${accessToken}` ); const postsData = await postsResponse.json(); return { account: accountData, posts: postsData.data }; } // Função para autenticar usuário com Instagram export async function authenticateInstagram() { // Redirecionar para autenticação do Facebook/Instagram const appId = process.env.FACEBOOK_APP_ID; const redirectUri = encodeURIComponent(`${process.env.NEXT_PUBLIC_BASE_URL}/api/auth/instagram/callback`); const scope = encodeURIComponent('instagram_basic,instagram_content_publish,pages_read_engagement'); const authUrl = `https://www.facebook.com/v18.0/dialog/oauth?client_id=${appId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code`; window.location.href = authUrl; } // Callback para processar token após autenticação // Arquivo: /pages/api/auth/instagram/callback.js export default async function handler(req, res ) { const { code } = req.query; // Trocar código por token de acesso const tokenResponse = await fetch( `https://graph.facebook.com/v18.0/oauth/access_token?client_id=${process.env.FACEBOOK_APP_ID}&redirect_uri=${encodeURIComponent(`${process.env.NEXT_PUBLIC_BASE_URL}/api/auth/instagram/callback` )}&client_secret=${process.env.FACEBOOK_APP_SECRET}&code=${code}` ); const tokenData = await tokenResponse.json(); const accessToken = tokenData.access_token; // Obter contas do Instagram associadas const accountsResponse = await fetch( `https://graph.facebook.com/v18.0/me/accounts?access_token=${accessToken}` ); const accountsData = await accountsResponse.json(); // Para cada página, obter conta de Instagram associada const instagramAccounts = await Promise.all( accountsData.data.map(async (page) => { const igResponse = await fetch( `https://graph.facebook.com/v18.0/${page.id}?fields=instagram_business_account&access_token=${accessToken}` ); const igData = await igResponse.json(); if (igData.instagram_business_account) { return { pageId: page.id, pageName: page.name, instagramBusinessAccountId: igData.instagram_business_account.id }; } return null; }) ); // Filtrar contas nulas const validInstagramAccounts = instagramAccounts.filter(account => account !== null); // Salvar tokens e IDs no Supabase // ... Res.redirect('/dashboard/instagram-connected'); } Iconosquare API Funcionalidade: API de terceiros para análise avançada do Instagram Vantagens: Métricas mais detalhadas, análise de concorrentes, relatórios Implementação: javascript // Exemplo de integração com Iconosquare // Arquivo: /lib/iconosquare.js export async function getIconosquareInsights(mediaId) { const response = await fetch( `https://api.iconosquare.com/v2/media/${mediaId}/insights`, { headers: { 'Authorization': `Bearer ${process.env.ICONOSQUARE_ACCESS_TOKEN}` } } ); const data = await response.json(); return { impressions: data.impressions, reach: data.reach, engagement: data.engagement, saves: data.saves, comments: data.comments, likes: data.likes, shares: data.shares, storyReplies: data.story_replies, storyTaps: data.story_taps, storyExits: data.story_exits }; } export async function getCompetitorAnalysis(competitorUsername) { const response = await fetch( `https://api.iconosquare.com/v2/users/search?q=${competitorUsername}`, { headers: { 'Authorization': `Bearer ${process.env.ICONOSQUARE_ACCESS_TOKEN}` } } ); const searchData = await response.json(); const userId = searchData.data[0]?.id; if (!userId) { return null; } const profileResponse = await fetch( `https://api.iconosquare.com/v2/users/${userId}/profile`, { headers: { 'Authorization': `Bearer ${process.env.ICONOSQUARE_ACCESS_TOKEN}` } } ); return await profileResponse.json(); } Not Just Analytics API Funcionalidade: API especializada em análise de seguidores e engajamento Vantagens: Foco em análise de audiência e comportamento de seguidores Implementação: javascript // Exemplo de integração com Not Just Analytics // Arquivo: /lib/not-just-analytics.js export async function getFollowerInsights(instagramUsername) { const response = await fetch( `https://api.notjustanalytics.com/v1/accounts/${instagramUsername}/followers`, { headers: { 'Authorization': `Bearer ${process.env.NJA_API_KEY}` } } ); const data = await response.json(); return { totalFollowers: data.total_followers, growthRate: data.growth_rate, demographics: data.demographics, topLocations: data.top_locations, activeHours: data.active_hours, engagementRate: data.engagement_rate }; } export async function getContentPerformance(instagramUsername) {
Categoria TI e Programação
Subcategoria Programação
Qual é o alcance do projeto? Alteração média
Isso é um projeto ou uma posição de trabalho? Um projeto
Tenho, atualmente Não se aplica
Disponibilidade requerida Conforme necessário
Integrações de API Payment Processor (Paypal, Stripe, etc), Outros (Outras APIs), Cloud Storage (Dropbox, Google Drive, etc)
Funções necessárias Desenvolvedor
Prazo de Entrega: Não estabelecido
Habilidades necessárias