Feature Flags & Remote Config — Frontend (SPA)
MCP: Flagsmith já está integrado no projeto (backend + admin UI). Este doc cataloga tudo no frontend SPA que poderia ser controlado via feature flag ou remote config, com justificativa e prioridade.
Contexto Atual
| Camada | Status |
|---|---|
| Flagsmith backend (src/lib/flagsmith.ts) | ✅ Ativo — getConfig() para remote config, isFlagEnabled() para boolean flags |
| Admin UI (src/spa/pages/Admin.tsx) | ✅ Tabs "Feature Flags" + "Remote Config" com toggle inline |
| Public Config API (src/app/api/public-config/route.ts) | ✅ Expose pilot_status_number_raw ao frontend |
| SPA consumption | ⚠️ Mínimo — SPA consome flags apenas via Admin UI; não usa flags para comportamento condicional |
Gap: As flags/configs existentes são 100% backend/worker. O SPA ainda não usa Flagsmith para controlar comportamento ou UI.
1. Feature Flags — UI Features
Features que podem ser ligadas/desligadas sem deploy.
1.1 Landing Page Sections
Cada seção da landing pode ter seu próprio flag para rollouts graduais:
| Flag Suggested | UI Element | File | Justificativa |
|---|---|---|---|
| landing_hero_section_enabled | Hero Section | components/landing/HeroSection.tsx | Seção principal — testar visibilidade |
| landing_trusted_by_enabled | Trusted By Section | components/landing/TrustedBySection.tsx | Social proof — fácil de A/B testar |
| landing_use_cases_enabled | Use Cases Section | components/landing/UseCasesSection.tsx | Feature showcase |
| landing_pricing_enabled | Pricing Section | components/landing/PricingSection.tsx | Preços — testar antes de publicar |
| landing_final_cta_enabled | Final CTA Section | components/landing/FinalCSection.tsx | CTA final |
| landing_receive_message_button_enabled | Receive Message Button | components/landing/ReceiveMessageButton.tsx | Já existe no backend — usar no SPA |
| landing_live_demo_enabled | Live Demo (logs mock) | pages/Landing.tsx | Demo interativa — pesado, pode ser opcional |
| landing_docs_chat_enabled | Docs Chat widget | components/DocsChat.tsx | AI chat — testar adoção |
1.2 Sidebar Navigation Items
Controle quais links aparecem no sidebar por segmento de usuário:
| Flag Suggested | Nav Item | File | Justificativa |
|---|---|---|---|
| sidebar_analytics_enabled | Analytics | components/AppSidebar.tsx | Nova feature — rollout gradual |
| sidebar_labels_enabled | Labels | components/AppSidebar.tsx | Feature beta |
| sidebar_docs_enabled | Docs | components/AppSidebar.tsx | Docs chat — pode ser opcional |
| sidebar_messages_enabled | Message | components/AppSidebar.tsx | Nova página de mensagens |
| sidebar_admin_enabled | Admin link | components/AppSidebar.tsx | Já usa isAdmin — flag adiciona controle fino |
| sidebar_keyboard_shortcuts_enabled | KbdShortcut badges | components/AppSidebar.tsx | UX — testar se ajuda |
1.3 Modals & Overlays
| Flag Suggested | Element | File | Justificativa |
|---|---|---|---|
| feedback_modal_enabled | Feedback Modal | components/FeedbackModal.tsx | Coleta feedback — pode ser segmentado |
| logout_confirm_enabled | Logout Confirm | components/AppSidebar.tsx | UX — testar se reduz logouts acidentais |
| delete_confirm_enabled | Delete Confirm Modal | components/DeleteConfirmModal.tsx | Padrão de confirmação |
1.4 Onboarding Flow
| Flag Suggested | Step | File | Justificativa |
|---|---|---|---|
| onboarding_optin_step_enabled | Opt-in validation step | pages/Onboarding.tsx | Testar se o step de opt-in converte |
| onboarding_project_name_step_enabled | Project name step | pages/Onboarding.tsx | Personalização do projeto |
| onboarding_api_key_step_enabled | API Key / cURL step | pages/Onboarding.tsx | Technical onboarding — pode ser opcional |
| onboarding_return_to_enabled | returnTo param | pages/Onboarding.tsx | UX — testar se melhora retenção |
1.5 Admin Tabs
| Flag Suggested | Tab | File | Justificativa |
|---|---|---|---|
| admin_trace_tab_enabled | Trace | pages/Admin.tsx | Debug tool — pode ser interna |
| admin_pilot_numbers_tab_enabled | Pilot Numbers | pages/Admin.tsx | Internal ops |
| admin_feature_flags_tab_enabled | Feature Flags | pages/Admin.tsx | Meta — só admins power-user |
| admin_remote_config_tab_enabled | Remote Config | pages/Admin.tsx | Meta — só admins power-user |
| admin_impersonation_enabled | Tenant switch | pages/Admin.tsx | canSwitchTenant — flag adiciona controle |
1.6 Page-Level Features
| Flag Suggested | Feature | File | Justificativa |
|---|---|---|---|
| templates_ai_composer_enabled | AI Template Composer | pages/Templates.tsx | AI feature — testar adoção |
| templates_media_upload_enabled | Media upload (images/videos) | pages/Templates.tsx | Upload — pode ser pesado |
| templates_whatsapp_preview_enabled | WhatsApp Preview | pages/Templates.tsx | UI — testar valor percebido |
| logs_search_enabled | Log search/filter | pages/Logs.tsx | Search — pode ser pesado em grandes volumes |
| logs_trace_view_enabled | Trace flow view | pages/Logs.tsx | TraceFlowCanvas — feature avançada |
| numbers_remote_pairing_enabled | Remote pairing QR | pages/Numbers.tsx | Pairing flow — testar conversão |
| numbers_dual_link_enabled | Dual Link mode (SINGLE/DUAL) | pages/Numbers.tsx | Já gateado por flag — usar no SPA |
| analytics_charts_enabled | Chart visualizations | pages/Analytics.tsx | Charts — pode ser pesado |
| analytics_ai_chat_enabled | AI chat (Ask AI) | pages/Analytics.tsx | AI — testar adoção |
| webhook_editor_enabled | Webhook form/editor | pages/Webhooks.tsx | Advanced feature |
| messages_marketing_ai_rewrite_enabled | Marketing AI rewrite toggle | pages/Messages.tsx | AI rewrite — rollout gradual |
| login_whatsapp_otp_enabled | WhatsApp OTP login button | pages/Login.tsx | Já gateado (waEnabled) — flag adiciona controle |
| plans_pix_payment_enabled | PIX payment option | pages/Plans.tsx | Regional rollout (só PT) |
| plans_auto_recharge_enabled | Auto-recharge modal | pages/Plans.tsx | Feature de recarga automática |
| profile_production_request_enabled | Production request tab | pages/Profile.tsx | Tab de solicitação de produção |
| profile_social_connections_enabled | Social connections tab | pages/Profile.tsx | Google/GitHub link |
2. Remote Config — Valores Configuráveis
Valores hardcodeados que podem ser ajustados sem deploy.
2.1 Pricing & Plans
| Config Key | Current Value | File | Justificativa |
|---|---|---|---|
| pricing_basic_monthly_brl | "29.90" | components/landing/PricingSection.tsx | Mudar preço sem deploy |
| pricing_pro_monthly_brl | "59.90" | components/landing/PricingSection.tsx | Idem |
| pricing_premium_monthly_brl | "99.90" | components/landing/PricingSection.tsx | Idem |
| pricing_basic_monthly_usd | "5.83" | components/landing/PricingSection.tsx | Preço USD |
| pricing_pro_monthly_usd | "11.68" | components/landing/PricingSection.tsx | Idem |
| pricing_premium_monthly_usd | "19.47" | components/landing/PricingSection.tsx | Idem |
| pricing_annual_discount_pct | "20" | components/landing/PricingSection.tsx | Badge "-20%" |
| pricing_free_monthly_messages | "100" | components/landing/PricingSection.tsx | Limite free |
| pricing_basic_monthly_messages | "700" | components/landing/PricingSection.tsx | Limite basic |
| pricing_pro_monthly_messages | "3600" | components/landing/PricingSection.tsx | Limite pro |
| pricing_premium_monthly_messages | "5000" | components/landing/PricingSection.tsx | Limite premium |
| pricing_annual_messages_multiplier | "12" | components/landing/PricingSection.tsx | Cálculo anual |
2.2 Query Cache & Performance
| Config Key | Current Value | File | Justificativa |
|---|---|---|---|
| query_default_stale_time_ms | "15000" | lib/queryClient.ts | Ajustar freshness sem deploy |
| query_default_gc_time_ms | "300000" | lib/queryClient.ts | GC policy |
| query_default_retry_count | "1" | lib/queryClient.ts | Retry policy |
| dashboard_query_stale_ms | "15000" | hooks/useDashboardQuery.ts | Dashboard refresh |
| logs_query_stale_ms | "10000" | hooks/useLogsQuery.ts | Logs refresh |
| numbers_query_stale_ms | "15000" | hooks/useNumbersQuery.ts | Numbers refresh |
| templates_query_stale_ms | "30000" | hooks/useTemplatesQuery.ts | Templates refresh |
| webhooks_query_stale_ms | "30000" | hooks/useWebhooksQuery.ts | Webhooks refresh |
| analytics_query_stale_ms | "30000" | hooks/useAnalyticsQuery.ts | Analytics refresh |
| profile_query_stale_ms | "60000" | hooks/useProfileData.ts | Profile cache |
| api_keys_query_stale_ms | "30000" | hooks/useApiKeysData.ts | API Keys cache |
| plans_query_stale_ms | "30000" | hooks/usePlansData.ts | Plans cache |
| admin_query_stale_ms | "10000" | hooks/useAdminData.ts | Admin cache |
2.3 UI Behavior
| Config Key | Current Value | File | Justificativa |
|---|---|---|---|
| pilot_status_number_raw | "5585936180633" | lib/whatsapp.ts + Onboarding.tsx | Já existe — número de suporte |
| toast_duration_ms | (Sonner default) | hooks/use-toast.ts | Duração dos toasts |
| landing_live_demo_log_interval_ms | (hardcoded) | pages/Landing.tsx | Intervalo dos logs mock |
| landing_live_demo_statuses | (array) | pages/Landing.tsx | Statuses do demo |
| max_sidebar_items | (implicit) | components/AppSidebar.tsx | Limitar items por plano |
| feedback_modal_timeout_ms | (hardcoded) | components/FeedbackModal.tsx | Auto-close do modal |
2.4 Text & Copy
| Config Key | Current Value | File | Justificativa |
|---|---|---|---|
| landing_hero_title_pt | (hardcoded) | components/landing/HeroSection.tsx | Copy da landing — testar variações |
| landing_hero_title_en | (hardcoded) | components/landing/HeroSection.tsx | Idem |
| landing_hero_subtitle_pt | (hardcoded) | components/landing/HeroSection.tsx | Subtitle |
| landing_hero_subtitle_en | (hardcoded) | components/landing/HeroSection.tsx | Subtitle |
| landing_cta_text_pt | (hardcoded) | components/landing/HeroSection.tsx | CTA copy |
| landing_cta_text_en | (hardcoded) | components/landing/HeroSection.tsx | CTA copy |
| onboarding_welcome_title_pt | (hardcoded) | pages/Onboarding.tsx | Onboarding copy |
| onboarding_welcome_title_en | (hardcoded) | pages/Onboarding.tsx | Idem |
| support_whatsapp_message_pt | (hardcoded) | pages/Onboarding.tsx | Mensagem de suporte |
| support_whatsapp_message_en | (hardcoded) | pages/Onboarding.tsx | Idem |
2.5 URLs & Integrations
| Config Key | Current Value | File | Justificativa |
|---|---|---|---|
| umami_website_id | (env var) | components/UmamiRouteTracker.tsx | Trocar site tracked |
| umapi_enabled | (env var) | lib/track.ts | Toggle tracking |
| docs_chat_ai_model | (hardcoded) | components/DocsChat.tsx | Trocar modelo de AI |
| deepseek_api_url | (hardcoded) | lib/deepseek.ts | Endpoint AI |
| deepseek_model | (hardcoded) | lib/deepseek.ts | Modelo AI |
2.6 Limits & Thresholds
| Config Key | Current Value | File | Justificativa |
|---|---|---|---|
| templates_max_per_page | (hardcoded) | pages/Templates.tsx | Paginação |
| logs_max_per_page | (hardcoded) | pages/Logs.tsx | Paginação |
| messages_max_per_page | (hardcoded) | pages/Messages.tsx | Paginação |
| admin_users_max_per_page | (hardcoded) | pages/Admin.tsx | Paginação |
| admin_templates_max_per_page | (hardcoded) | pages/Admin.tsx | Paginação |
| max_project_count | (hardcoded) | pages/Projects.tsx | Limite de projetos |
| max_api_key_count | (hardcoded) | pages/ApiKeys.tsx | Limite de API Keys |
| max_number_count | (hardcoded) | pages/Numbers.tsx | Limite de números |
| max_webhook_count | (hardcoded) | pages/Webhooks.tsx | Limite de webhooks |
2.7 Plans & Billing (detalhado)
| Config Key | Current Value | File | Justificativa |
|---|---|---|---|
| brl_per_usd_rate | "5.13" | pages/Plans.tsx | Taxa câmbio — muda sem deploy |
| pricing_package_300_brl | "9.90" | pages/Plans.tsx | Preço pacote 300 msgs |
| pricing_package_1000_brl | "19.90" | pages/Plans.tsx | Preço pacote 1000 msgs |
| auto_recharge_triggers | "[50,60,70,80,90]" | pages/Plans.tsx | Thresholds de recarga automática |
| pix_payment_enabled | (hardcoded lang === "pt") | pages/Plans.tsx | PIX — testar por região |
2.8 Messaging & Analytics Behavior
| Config Key | Current Value | File | Justificativa |
|---|---|---|---|
| message_send_concurrency | "3" | pages/Messages.tsx | Concorrência de envio — ajustar performance |
| marketing_ai_rewrite_enabled | (state) | pages/Messages.tsx | AI rewrite — rollout gradual |
| dashboard_chart_period_days | "4" | pages/Dashboard.tsx | Período do gráfico — ajustar |
| analytics_period_options | "7d" | pages/Analytics.tsx | Opções de período (7d/30d/90d) |
| analytics_ai_chat_enabled | (hardcoded) | pages/Analytics.tsx | AI chat — testar adoção |
2.9 Onboarding & Auth
| Config Key | Current Value | File | Justificativa |
|---|---|---|---|
| onboarding_template_id | "onboarding_hello" | pages/Onboarding.tsx | Trocar template sem deploy |
| otp_code_length | "6" | pages/Login.tsx + Onboarding.tsx | Comprimento do código OTP |
| otp_expiry_minutes | "5" | pages/Onboarding.tsx | Expiração do OTP |
| session_check_interval_ms | "1800000" (30min) | components/AppLayout.tsx | Intervalo de verificação de sessão |
| whatsapp_login_enabled | (API check) | pages/Login.tsx | Toggle login WhatsApp |
| onboarding_pilot_number | "5585936180633" | pages/Onboarding.tsx | Número de onboarding |
2.10 Admin & Performance
| Config Key | Current Value | File | Justificativa |
|---|---|---|---|
| admin_polling_interval_ms | "5000" | pages/Admin.tsx | Polling após restart |
| admin_polling_timeout_ms | "30000" | pages/Admin.tsx | Timeout do polling |
| admin_trace_limit | "400" | pages/Admin.tsx | Limite de trace events |
| video_upload_max_size_mb | "16" | pages/Profile.tsx | Tamanho máximo de vídeo |
| video_upload_format | "video/mp4" | pages/Profile.tsx | Formato aceito |
2.11 Landing Page Animations
| Config Key | Current Value | File | Justificativa |
|---|---|---|---|
| landing_frame_rotation_ms | "1600" | pages/Landing.tsx | Rotação de frames do demo |
| landing_log_animation_ms | "1300" | pages/Landing.tsx | Intervalo de animação de logs |
| landing_channel_rotation_ms | "2000" | pages/Landing.tsx | Rotação de canais mobile |
| landing_max_log_entries | "6" | pages/Landing.tsx | Máximo de logs no demo |
| landing_header_scroll_offset_px | "72" | pages/Landing.tsx | Offset do header |
| landing_demo_frames | (3 mock sets) | pages/Landing.tsx | Dados mock do dashboard |
| landing_feature_image_urls | (hardcoded) | pages/Landing.tsx | URLs de imagens de features |
| landing_pain_value_cards | (hardcoded) | pages/Landing.tsx | Cards de dor/valor |
| landing_migration_providers | (hardcoded) | pages/Landing.tsx | Lista de provedores de migração |
| landing_ddi_country_list | 190+ países | data/ddi-options.ts | Lista de países para DDI |
3. Padrão de Implementação Sugerido
3.1 Arquitetura
Flagsmith (cloud)
↓ (REST API, polling)
public-config API (/api/public-config)
↓ (JSON, cache 5min)
SPA Client (useFlagsmith hook)
↓ (context)
Components (if (flag) { ... })
3.2 Hook Sugerido
// hooks/useFeatureFlags.ts
import { useEffect, useState } from "react";
export type FeatureFlags = {
landing_hero_section_enabled: boolean;
sidebar_analytics_enabled: boolean;
// ... outras flags
};
export type RemoteConfigMap = {
pricing_basic_monthly_brl: string;
query_default_stale_time_ms: string;
// ... outros configs
};
export function useFeatureFlags() {
const [flags, setFlags] = useState<FeatureFlags>({} as FeatureFlags);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch("/api/public-config")
.then((r) => r.json())
.then((data) => { setFlags(data.flags ?? {}); })
.finally(() => setLoading(false));
}, []);
return { flags, loading };
}
3.3 Uso nos Componentes
// Exemplo: HeroSection
import { useFeatureFlags } from "@spa/hooks/useFeatureFlags";
export default function HeroSection() {
const { flags } = useFeatureFlags();
if (!flags.landing_hero_section_enabled) return null;
return (
<section>
{/* Hero content */}
</section>
);
}
3.4 Priorização de Implementação
| Prioridade | Categoria | Flags/Configs | Impacto | |---|---|---|---| | P0 — Alto | Pricing (remote config) | 11 configs | Mudar preços sem deploy | | P0 — Alto | Landing sections (flags) | 8 flags | Rollout gradual da landing | | P1 — Médio | Sidebar items (flags) | 5 flags | Personalizar navegação | | P1 — Médio | Query cache (remote config) | 12 configs | Ajustar performance | | P2 — Baixo | Text/Copy (remote config) | 10 configs | A/B testar textos | | P2 — Baixo | Modals (flags) | 3 flags | Controlar UX | | P2 — Baixo | Onboarding (flags) | 4 flags | Testar fluxo | | P3 — Nice | Admin tabs (flags) | 5 flags | Controle fino de admin | | P3 — Nice | Limits (remote config) | 9 configs | Ajustar limites | | P3 — Nice | URLs/Integrations (remote config) | 5 configs | Trocar integrações |
4. Flags Existentes vs Novas
4.1 Flags Existentes (backend-only, não usadas no SPA)
De src/app/api/admin/flagsmith.utils.ts — BOOLEAN_FLAG_NAMES:
| Flag | Categoria | Uso no SPA? |
|---|---|---|
| evolution_go_enabled | WhatsApp Provider | Não |
| evolution_proxy_enabled | WhatsApp Provider | Não |
| whatsapp_optin_validation_enabled | WhatsApp Provider | Não |
| webhook_disconnect_alert_enabled | WhatsApp Provider | Não |
| dual_ingestion_enabled | WhatsApp Provider | Não |
| rabbitmq_go_consumer_enabled | RabbitMQ | Não |
| rabbitmq_consumer_enabled | RabbitMQ | Não |
| rabbitmq_forward_to_webhook_enabled | RabbitMQ | Não |
| upstat_heartbeat_enabled | Monitoring | Não |
| pilot_status_only_alerts | Monitoring | Não |
| marketing_text_guardrails_enabled | Marketing | Não |
| marketing_irregular_batch_enabled | Marketing | Não |
| message_reconciler_per_type_locks | Worker / Reconciler | Não |
| message_reconciler_log_lock_misses | Worker / Reconciler | Não |
| ps_cache_metrics | Fullstack | Não |
4.2 Remote Configs Existentes (backend-only)
De src/app/api/admin/flagsmith.utils.ts — REMOTE_CONFIG_NAMES:
| Config | Categoria | Uso no SPA? |
|---|---|---|
| pilot_status_number_raw | Fullstack | ✅ Sim (public-config) |
| admin_emails | Fullstack | Não |
| video_upload_provider | Fullstack | Não |
| video_upload_dir | Fullstack | Não |
| evolution_* | WhatsApp Provider | Não |
| marketing_* | Marketing | Não |
| message_reconciler_* | Worker / Reconciler | Não |
| whatsapp_queue_* | Queue / Delays | Não |
| worker_* | Worker / Reconciler | Não |
| upstat_* | Monitoring | Não |
| rabbitmq_* | RabbitMQ | Não |
| log_level | Monitoring | Não |
5. Resumo de Oportunidades
| Tipo | Count | Prioridade | |---|---|---| | Feature Flags — Landing | 8 flags | P0 | | Feature Flags — Sidebar | 6 flags | P1 | | Feature Flags — Modals | 3 flags | P2 | | Feature Flags — Onboarding | 4 flags | P2 | | Feature Flags — Admin | 5 flags | P3 | | Feature Flags — Page Features | 15 flags | P0-P2 | | Remote Config — Pricing | 14 configs | P0 | | Remote Config — Cache | 12 configs | P1 | | Remote Config — Text | 10 configs | P2 | | Remote Config — Limits | 9 configs | P3 | | Remote Config — URLs | 5 configs | P3 | | Remote Config — Behavior | 6 configs | P1-P2 | | Remote Config — Plans/Billing | 5 configs | P0 | | Remote Config — Messaging | 5 configs | P1 | | Remote Config — Onboarding/Auth | 7 configs | P1-P2 | | Remote Config — Admin/Perf | 5 configs | P2 | | Remote Config — Landing Animations | 9 configs | P3 | | Total | ~139 | — |
Quick Wins (maior impacto, menor esforço)
- Pricing remote config — 14 valores hardcodeados → remote config. Impacto: mudar preços sem deploy.
- Landing section flags — 8 flags para seções da landing. Impacto: rollout gradual.
- Query cache remote config — 12 valores de
staleTime. Impacto: ajustar performance por ambiente. landing_receive_message_button_enabled— Flag já existe no backend, basta expor ao SPA.numbers_dual_link_enabled— Já gateado por flag no backend, expor ao SPA para controle fino.login_whatsapp_otp_enabled— Já gateado porwaEnabled, flag adiciona controle sem API call.