Skip to content

Arquitetura

AldemirLucas edited this page Oct 16, 2026 · 1 revision

Arquitetura

Visão geral de como o website é montado e de onde vêm os dados. Para rodar o projeto, veja Setup local.

Visão geral

                    ┌────────────────────────── website (Next.js 12) ──────────────────────────┐
 navegador ───────► │ pages/*.js  ── getStaticProps / getServerSideProps                       │
 (basedosdados.org, │      │                                                                   │
  data-basis.org,   │      ├── importa funções de pages/api/* (no servidor, sem HTTP)          │
  basedelosdatos)   │      │                                                                   │
                    │ componentes ── fetch("/api/...") ──► pages/api/* (rotas Next)            │
                    └──────────────────────────────────────┬───────────────────────────────────┘
                                                           │
                       ┌───────────────────────────────────┼─────────────────────────┐
                       ▼                                   ▼                         ▼
             backend (Django/GraphQL)              API do chatbot             Google Cloud Storage
   ${NEXT_PUBLIC_API_URL}/api/v1/graphql            ${CHATBOT_URL}         (download de tabelas)
  • Front-end: Next.js 12 com pages router, React 17 e Chakra UI v1. O build usa output: "standalone" e roda num container Node 20.
  • Dados: quase tudo vem do backend, via GraphQL em ${NEXT_PUBLIC_API_URL}/api/v1/graphql.
  • Conteúdo estático: blog (next/blog/{pt,en,es}), documentação, FAQ, termos e guias de uso (next/content/) ficam no próprio repositório.

Camadas do código (next/)

Pasta O que tem
pages/ Páginas (uma rota por arquivo) e as rotas de API em pages/api/
pages/api/ Rotas Next que falam com o backend, o chatbot ou o GCS. Organizadas por domínio: user, datasets, tables, stripe, chatbot, blog, team, etc.
components/ Componentes em atomic design: atoms, molecules, organisms, templates
hooks/ Hooks React (chatbot, testes A/B, checkout, detecção de mobile)
context/ Contextos React (ChatbotContext)
lib/ Autenticação no servidor (authCookie.js, requireChatbotAuth.js)
content/ Conteúdo em JS/markdown: docs, FAQ, termos, guias, case studies, BD Pro
blog/ Posts do blog em markdown, um diretório por idioma
public/ Imagens, ícones e as traduções em public/locales/{pt,en,es}
styles/ globals.css e CSS modules
utils.js Funções compartilhadas (domínio atual, cookie do usuário, campanhas)

Como as páginas buscam dados

Existem dois caminhos, e ambos passam por pages/api/:

  1. No servidor (build ou request): a página importa a função exportada pelo arquivo de pages/api/ e chama direto, sem HTTP. Exemplo: pages/dataset/[dataset].js importa getUserGuide de pages/api/datasets/getUserGuide.
  2. No navegador: o componente faz fetch("/api/...") e a rota Next repassa ao backend, anexando o token do cookie.

As rotas montam a query GraphQL e chamam o backend com axios ou graphql-request. Por exemplo, pages/api/stripe/createSubscription.js chama a mutation createStripeSubscription.

Renderização

Estratégia Páginas
ISR (revalidate: 30) index, dataset/[dataset] (com fallback: "blocking"), case-studies/[id], bdpro, services, faq, chatbot-lp
SSG blog/*, docs/[slug], search, prices, contact, terms, user/login, user/register, entre outras
SSR (getServerSideProps) user/index, user/[username], user/activate-account, user/password-recovery, about-us, invited-researchers

Todas as páginas chamam serverSideTranslations para carregar as traduções. Veja Internacionalização.

Estado no cliente

O padrão é useState/useEffect com fetch. O React Query (@tanstack/react-query, configurado em pages/_app.js com staleTime de 5 min) hoje só é usado pelo chatbot (useThreads, useChatbotAuth).

Autenticação

O backend emite um JWT. O website guarda esse token num cookie httpOnly e todas as chamadas autenticadas passam pelas rotas pages/api/.

login ──► /api/user/getToken ──► mutation authToken ──► Set-Cookie: token (httpOnly, 7 dias)
                                                         + cookie userBD (dados do usuário, legível no JS)

requisição autenticada ──► /api/... ──► getTokenFromRequest(req) ──► Authorization: Bearer <token> ──► backend
  • lib/authCookie.js: cria e limpa o cookie token (httpOnly, sameSite: lax, secure em produção). getTokenFromRequest lê o token, nesta ordem, do header Authorization: Bearer, do cookie token ou do corpo da requisição.
  • Rotas de sessão: getToken (login), refreshToken, setSession, clearSession e validateToken, em pages/api/user/.
  • validateToken: valida o token com a mutation verifyToken do backend e devolve has_chatbot_access.
  • Páginas protegidas: as páginas SSR, como user/index.js, leem req.cookies, chamam /api/user/validateToken e redirecionam para o login se o token for inválido.
  • Chatbot: as rotas pages/api/chatbot/* usam requireChatbotAuth(req), que retorna 401 sem token válido e 403 sem has_chatbot_access.
  • No cliente: getUserFromCookie() e clearClientSession(), em utils.js, leem e limpam o cookie userBD.

middlewares/authUser.js e context/user.js não são importados por nenhuma página. São código legado.

Internacionalização

  • next-i18next, com a configuração em next-i18next.config.js. Os locales são pt (padrão), en e es, e cada idioma tem seu próprio domínio (i18n.domains).
  • As traduções ficam em public/locales/<idioma>/<namespace>.json.
  • Cada imagem Docker é construída com um NEXT_PUBLIC_DOMAIN. getDomain() e isBasedosdadosDomain(), em utils.js, usam esse valor para mostrar conteúdo específico de cada domínio. Por exemplo, consultoria só aparece em basedosdados.org.
  • Em next.config.js, o produto Pro se chama /bdpro em pt/es e /dbpro em en, por meio de rewrite e redirect.

Integrações externas

Serviço Onde Variável
Backend GraphQL quase todas as rotas de pages/api/ NEXT_PUBLIC_API_URL
Stripe components/organisms/PaymentSystem.js + pages/api/stripe/* NEXT_PUBLIC_KEY_STRIPE
API do chatbot pages/api/chatbot/* CHATBOT_URL
Google Cloud Storage pages/api/tables/downloadTable.js URL_DOWNLOAD_OPEN, URL_DOWNLOAD_CLOSED
Google Tag Manager / Meta Pixel pages/_app.js, carregados conforme o ambiente —

A lista completa de variáveis está no README.

Clone this wiki locally