Documentação / Feature Flags & Remote Config — Frontend (SPA)

Feature Flags & Remote Config — Frontend (SPA)

Entrar

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.tsBOOLEAN_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.tsREMOTE_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)

  1. Pricing remote config — 14 valores hardcodeados → remote config. Impacto: mudar preços sem deploy.
  2. Landing section flags — 8 flags para seções da landing. Impacto: rollout gradual.
  3. Query cache remote config — 12 valores de staleTime. Impacto: ajustar performance por ambiente.
  4. landing_receive_message_button_enabled — Flag já existe no backend, basta expor ao SPA.
  5. numbers_dual_link_enabled — Já gateado por flag no backend, expor ao SPA para controle fino.
  6. login_whatsapp_otp_enabled — Já gateado por waEnabled, flag adiciona controle sem API call.