diff --git a/src/routes/bem-vindo.tsx b/src/routes/bem-vindo.tsx
new file mode 100644
index 0000000..efb495a
--- /dev/null
+++ b/src/routes/bem-vindo.tsx
@@ -0,0 +1,401 @@
+"use client";
+
+import { createFileRoute, useNavigate } from "@tanstack/react-router";
+import { useEffect, useMemo, useState } from "react";
+import { motion, AnimatePresence } from "framer-motion";
+import {
+ ArrowRight,
+ CheckCircle2,
+ ExternalLink,
+ Loader2,
+ Sparkles,
+} from "lucide-react";
+import { useQueryClient } from "@tanstack/react-query";
+import { toast } from "sonner";
+
+import { useAuth } from "@/hooks/use-auth";
+import { useProfile } from "@/hooks/use-profile";
+import { useAgentInstance } from "@/hooks/use-agent-instance";
+import { supabase } from "@/integrations/supabase/client";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Logo } from "@/components/mika/Logo";
+import { TelegramIcon } from "@/components/mika/telegram/TelegramIcon";
+import { TelegramOnboardingWizard } from "@/components/mika/telegram/TelegramOnboardingWizard";
+import { cn } from "@/lib/utils";
+
+const WELCOME_DONE_KEY = "mika-welcome-done";
+
+export const Route = createFileRoute("/bem-vindo")({
+ component: WelcomePage,
+});
+
+function WelcomePage() {
+ const { user, loading: authLoading } = useAuth();
+ const { data: profile } = useProfile();
+ const { data: agent } = useAgentInstance();
+ const navigate = useNavigate();
+ const queryClient = useQueryClient();
+
+ const [step, setStep] = useState<1 | 2 | 3>(1);
+ const [agentName, setAgentName] = useState("");
+ const [saving, setSaving] = useState(false);
+ const [wizardOpen, setWizardOpen] = useState(false);
+
+ const fullName = (profile?.full_name || "").trim();
+ const firstName = useMemo(
+ () => (fullName.split(" ")[0] || "você").trim(),
+ [fullName],
+ );
+
+ // Auth guard
+ useEffect(() => {
+ if (!authLoading && !user) {
+ navigate({ to: "/login", search: { redirect: "/bem-vindo" } });
+ }
+ }, [authLoading, user, navigate]);
+
+ // Pré-preenche o input com o default
+ useEffect(() => {
+ if (agentName) return;
+ if (agent?.agent_name) {
+ setAgentName(agent.agent_name);
+ } else if (firstName && firstName !== "você") {
+ setAgentName(`Mika de ${firstName}`);
+ }
+ }, [agent?.agent_name, firstName, agentName]);
+
+ // Etapa 1 → 2 automático em 3s
+ useEffect(() => {
+ if (step !== 1) return;
+ const t = setTimeout(() => setStep(2), 3000);
+ return () => clearTimeout(t);
+ }, [step]);
+
+ // Se já completou o onboarding, vai direto para /painel
+ useEffect(() => {
+ if (!agent) return;
+ if (agent.onboarding_completed) {
+ navigate({ to: "/painel", search: {} });
+ }
+ }, [agent, navigate]);
+
+ async function handleSaveName() {
+ const trimmed = agentName.trim();
+ if (trimmed.length < 2) {
+ toast.error("O nome precisa ter pelo menos 2 caracteres.");
+ return;
+ }
+ if (!agent) {
+ toast.error("Aguarde, ainda estamos preparando seu agente…");
+ return;
+ }
+ setSaving(true);
+ const { error } = await supabase
+ .from("agent_instances")
+ .update({ agent_name: trimmed })
+ .eq("id", agent.id);
+ setSaving(false);
+ if (error) {
+ toast.error("Não foi possível salvar o nome. Tente novamente.");
+ return;
+ }
+ if (user) {
+ await queryClient.invalidateQueries({ queryKey: ["agent-instance", user.id] });
+ }
+ setStep(3);
+ }
+
+ async function markWelcomeDone() {
+ if (typeof window !== "undefined") {
+ window.localStorage.setItem(WELCOME_DONE_KEY, "1");
+ }
+ if (agent) {
+ await supabase
+ .from("agent_instances")
+ .update({ onboarding_completed: true })
+ .eq("id", agent.id);
+ if (user) {
+ await queryClient.invalidateQueries({ queryKey: ["agent-instance", user.id] });
+ }
+ }
+ }
+
+ async function handleConnectTelegram() {
+ await markWelcomeDone();
+ setWizardOpen(true);
+ }
+
+ async function handleSkip() {
+ await markWelcomeDone();
+ navigate({ to: "/painel", search: {} });
+ }
+
+ if (authLoading || !user) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+ {/* Header */}
+
+
+
+
+
+ {step === 1 && (
+
+
+
+
+
+
+ Bem-vindo à Mika! 🎉
+
+
+ Seu assistente pessoal de IA está sendo preparado.
+
+
+
+ {[
+ { icon: "✅", text: "Pagamento confirmado" },
+ { icon: "✅", text: "Sua conta está ativa" },
+ { icon: "⏳", text: "Configurando seu agente..." },
+ ].map((item, i) => (
+
+ {item.icon}
+ {item.text}
+
+ ))}
+
+
+ )}
+
+ {step === 2 && (
+
+
+ Como você quer chamar seu assistente?
+
+
+ Este será o nome que aparecerá nas conversas.
+
+
+
+
setAgentName(e.target.value)}
+ placeholder="Ex: Mika de João, Maya, Assistente..."
+ className="h-12 text-center text-lg bg-white/5 border-white/20 text-white placeholder:text-white/40 focus-visible:ring-primary"
+ />
+
+
+ {agentName.trim().length < 2
+ ? "Mínimo 2 caracteres"
+ : "\u00A0"}
+
+ {agentName.length}/40
+
+
+
+
+ {[
+ `Mika de ${firstName}`,
+ "Maya",
+ "Alex",
+ "Assistente",
+ ].map((sugg) => (
+ setAgentName(sugg.slice(0, 40))}
+ className={cn(
+ "px-3 py-1.5 rounded-full text-xs font-medium border transition-colors",
+ agentName === sugg
+ ? "bg-primary text-primary-foreground border-primary"
+ : "bg-white/5 text-white/80 border-white/15 hover:bg-white/10",
+ )}
+ >
+ {sugg}
+
+ ))}
+
+
+
+ {saving ? (
+
+ ) : null}
+ Continuar
+
+
+ )}
+
+ {step === 3 && (
+
+
+ Quase lá! Conecte seu Telegram.
+
+
+ Para conversar com{" "}
+
+ {agentName || "seu agente"}
+
+ , você precisa conectar seu Telegram. Leva menos de 2 minutos.
+
+
+
+
+
+
+
+
+
+ Abrir BotFather
+
+
+ }
+ />
+
+
+
+
+
+
+ Conectar meu Telegram
+
+
+ Fazer isso depois
+
+
+
+ )}
+
+
+
+
+
{
+ setWizardOpen(open);
+ // Quando fechar o wizard, leva ao painel
+ if (!open) {
+ navigate({ to: "/painel", search: {} });
+ }
+ }}
+ />
+
+ );
+}
+
+function StepRow({
+ number,
+ title,
+ hint,
+ extra,
+}: {
+ number: number;
+ title: string;
+ hint?: string;
+ extra?: React.ReactNode;
+}) {
+ return (
+
+
+ {number}
+
+
+
{title}
+ {hint &&
{hint}
}
+ {extra}
+
+
+ );
+}
+
+// Marker no componente para cumprir contrato de "marcar como visitada"
+// (também usado pelo redirect do /painel)
+export function isWelcomeDone(): boolean {
+ if (typeof window === "undefined") return false;
+ return window.localStorage.getItem(WELCOME_DONE_KEY) === "1";
+}