Plataforma web para baixar, refinar, avaliar e publicar resultados do IDECICLO por cidade, com autenticação por magic link, controle de permissões por escopo territorial e painel administrativo.
O projeto combina:
- portal público com apresentação da metodologia, ranking e páginas de detalhe;
- fluxo protegido de avaliação por cidade;
- persistência em PostgreSQL;
- rotas server-side locais em
/api/auth/*e/api/db/*; - autenticação por link mágico enviado por e-mail;
- gestão administrativa de usuários, permissões e solicitações de acesso.
O IDECICLO é uma metodologia de avaliação qualitativa da infraestrutura cicloviária urbana. Em vez de medir apenas extensão de ciclovias e ciclofaixas, a plataforma trabalha com qualidade da infraestrutura, segurança e contexto viário.
A metodologia considera 23 parâmetros organizados em 5 eixos:
- Planejamento cicloviário
- Projeto cicloviário ao longo da quadra
- Projeto cicloviário nas interseções
- Urbanidade
- Manutenção da infraestrutura
O projeto é mantido no contexto da Ameciclo e foi estruturado para apoiar avaliação técnica, incidência pública e comparação entre cidades.
Hoje a página inicial oferece três materiais principais:
Manualempublic/manual_ideciclo.pdf;Formulárioem link externo;Cálculo do IDECICLOempublic/resumo_ideciclo.pdf.
/página inicial com apresentação, materiais e navegação para a metodologia./sobreexplicação do IDECICLO./apoiadoresparceiros e apoiadores./rankingranking nacional das cidades publicadas./detalhes-cidades/:cityIdpágina pública de resultados por cidade./detalhes-cidades/:cityId/estruturas/:segmentIddetalhe público de um trecho avaliado.
/avaliacaoescolha da cidade ativa e entrada para o fluxo protegido./avaliacao/refinar-dadosrefinamento da malha cicloviária da cidade./avaliacao/escolher-estruturaseleção do trecho a ser avaliado./avaliacao/avaliar-estruturaapoio à avaliação do trecho./avaliacao/formulario-ideciclo/:segmentIdformulário IDECICLO./avaliacao/resultadosconsolidação da nota, visualização e liberação para ranking.
/loginenvio de magic link./solicitar-acessosolicitação de acesso com verificação de e-mail./auth/verifyconsumo do magic link de login./auth/logoutencerramento de sessão./adminpainel administrativo de usuários e solicitações.
- Entrar em
/avaliacao. - Selecionar estado e cidade.
- Ativar a cidade na sessão atual.
- Refinar os segmentos em
/avaliacao/refinar-dados. - Escolher um trecho e preencher o formulário IDECICLO.
- Consultar os resultados em
/avaliacao/resultados. - Se fizer sentido, liberar a cidade para aparecer no ranking.
- A pessoa preenche
/solicitar-acesso. - O sistema envia um e-mail de verificação.
- Após a confirmação do e-mail, a solicitação fica
pending_review. - Um admin revisa no painel
/admin. - Se aprovada, as permissões são criadas conforme o tipo de interesse e o escopo informado.
- A pessoa informa o e-mail em
/login. - Se o e-mail já tiver acesso, o sistema envia um magic link.
- O link leva para
/auth/verifye cria a sessão autenticada.
admin_globaladmin_estadoadmin_cidadeavaliador_estrutura_cicloviariarefinador_dados_cidadevisualizador
adminavaliacao_estrutura_cicloviariarefinamento_dados_cidade
As permissões podem ser:
- globais;
- por estado;
- por cidade.
O acesso é calculado com base em role, module, state e city.
admin_globaltem acesso total.admin_estadoeadmin_cidadeacessam o painel admin dentro do próprio escopo.- Admin regional pode revisar solicitações de acesso da própria jurisdição.
- Admin regional só pode conceder
visualizador,avaliador_estrutura_cicloviariaerefinador_dados_cidade. - Admin regional não pode conceder novos papéis de admin.
- Usuário não pode alterar o próprio status nem as próprias permissões.
Uma cidade só aparece em /ranking quando as duas condições abaixo são verdadeiras:
show_in_ranking !== false- existe pelo menos um formulário salvo em
public.formspara a cidade
Na tela /avaliacao/resultados, a ação de liberação para ranking abre um modal com:
- pendências obrigatórias;
- pendências não obrigatórias;
- aviso explícito de que sem formulário salvo a cidade não entra no ranking.
- React
- TypeScript
- Vite
- React Router
- Tailwind CSS
- shadcn/ui
- PostgreSQL
- rotas Node locais em
/api/auth/*e/api/db/* - OpenStreetMap / Overpass para malha cicloviária
- IBGE para estados e municípios
- Mapbox para mapas interativos no frontend
No desenvolvimento normal, npm run dev já sobe o Vite e injeta middleware para atender:
/api/auth/*/api/db/*
Ou seja, para desenvolvimento local comum não é necessário subir um servidor HTTP separado para a API.
O comando npm run auth:dev existe para rodar o servidor de autenticação isoladamente, mas ele não é obrigatório para o fluxo padrão do projeto.
- Node.js 18 ou superior
- npm
- Docker e Docker Compose
- acesso à internet para IBGE e Overpass
- token do Mapbox para visualizar mapas interativos
npm installUse .env.example como base:
cp .env.example .env.localExemplo mínimo:
DATABASE_URL=postgresql://ideciclo:change_me_local_password@127.0.0.1:54322/ideciclo
APP_URL=http://127.0.0.1:8080
EMAIL_FROM=no-reply@ideciclo.local
MAGIC_LINK_SECRET=change_me_magic_link_secret
AUTH_COOKIE_SECURE=false
SMTP_HOST=
SMTP_PORT=587
SMTP_USER=
SMTP_PASS=
SMTP_SECURE=false
AUTH_MAGIC_LINK_RATE_LIMIT_WINDOW_MINUTES=15
AUTH_MAGIC_LINK_RATE_LIMIT_EMAIL_MAX=5
AUTH_MAGIC_LINK_RATE_LIMIT_IP_MAX=20
AUTH_MAGIC_LINK_RATE_LIMIT_EMAIL_COOLDOWN_SECONDS=60
POSTGRES_DATABASE=ideciclo
POSTGRES_USER=ideciclo
POSTGRES_PASSWORD=change_me_local_password
POSTGRES_PORT=54322
VITE_MAPBOX_ACCESS_TOKEN=your_mapbox_access_token_herenpm run db:upO container ideciclo-postgres expõe o banco em 127.0.0.1:54322 por padrão.
Na primeira subida com volume novo, o docker-compose.yml já monta supabase/bootstrap_full_schema.sql como script de inicialização do Postgres.
Para bancos externos, bancos já existentes ou reaplicação manual da estrutura:
npm run db:bootstrapnpm run db:seedsudoOu passando o e-mail diretamente:
npm run db:seedsudo -- admin@exemplo.orgnpm run devAplicação local:
- frontend + rotas locais:
http://127.0.0.1:8080 - auth server isolado, se usado:
http://127.0.0.1:3001
# desenvolvimento
npm run dev
# auth server isolado
npm run auth:dev
# subir banco local
npm run db:up
# derrubar banco local
npm run db:down
# logs do banco
npm run db:logs
# aplicar bootstrap manualmente
npm run db:bootstrap
# criar primeiro admin global
npm run db:seedsudo
# build de produção
npm run build
# build em modo development
npm run build:dev
# preview da build
npm run preview
# lint
npm run lintDATABASE_URLconexão principal com o PostgreSQL.APP_URLURL pública da aplicação.POSTGRES_DATABASE,POSTGRES_USER,POSTGRES_PASSWORD,POSTGRES_PORTusados no ambiente Docker local.
MAGIC_LINK_SECRETsegredo para hash dos tokens.AUTH_COOKIE_SECUREforça cookie seguro.AUTH_SESSION_COOKIE_NAMEnome do cookie de sessão, opcional.
EMAIL_FROMremetente dos e-mails.SMTP_HOSTSMTP_PORTSMTP_USERSMTP_PASSSMTP_SECUREACCESS_REQUEST_NOTIFICATION_EMAILe-mail que recebe notificação de novas solicitações.
AUTH_MAGIC_LINK_RATE_LIMIT_WINDOW_MINUTESAUTH_MAGIC_LINK_RATE_LIMIT_EMAIL_MAXAUTH_MAGIC_LINK_RATE_LIMIT_IP_MAXAUTH_MAGIC_LINK_RATE_LIMIT_EMAIL_COOLDOWN_SECONDSAUTH_ACCESS_REQUEST_VERIFICATION_TTL_MINUTESAUTH_ACCESS_REQUEST_PENDING_TTL_DAYSAUTH_ACCESS_REQUEST_RATE_LIMIT_WINDOW_MINUTESAUTH_ACCESS_REQUEST_RATE_LIMIT_EMAIL_MAXAUTH_ACCESS_REQUEST_RATE_LIMIT_IP_MAXAUTH_ACCESS_REQUEST_RATE_LIMIT_EMAIL_COOLDOWN_SECONDS
VITE_MAPBOX_ACCESS_TOKENhabilita a renderização dos mapas Mapbox no frontend.
Sem esse token, a aplicação continua funcionando, mas os componentes de mapa exibem aviso em vez do mapa interativo.
Se SMTP_HOST não estiver configurado, o servidor usa jsonTransport.
Na prática:
- magic links não são enviados de fato;
- e-mails de verificação de solicitação não são enviados de fato;
- o conteúdo do e-mail é registrado no terminal do processo.
Logs esperados:
Magic link gerado em modo local: ...Verificação de solicitação de acesso gerada em modo local: ...Notificação de solicitação de acesso gerada em modo local: ...
Isso é suficiente para desenvolvimento local, mas para testes reais de e-mail você deve configurar SMTP.
Para rodar uma instância equivalente em outro ambiente, você precisa reproduzir:
- PostgreSQL com a estrutura de
supabase/bootstrap_full_schema.sql; - frontend Vite;
- runtime Node capaz de servir
/api/auth/*e/api/db/*; - SMTP para produção;
- acesso aos endpoints do IBGE;
- acesso aos endpoints Overpass do OpenStreetMap;
- token do Mapbox, se quiser mapas interativos.
api/ adaptadores das rotas /api no ambiente Vite/Node
public/ PDFs, imagens e assets públicos
scripts/ bootstrap e seed do banco
server/ lógica das APIs locais de auth e leitura do banco
src/components/ componentes reutilizáveis
src/pages/ páginas públicas, avaliação e admin
src/services/ acesso a APIs, banco e integrações
src/lib/ regras de permissão e helpers de acesso
supabase/ schema SQL usado no bootstrap
O deploy de produção atual assume:
- frontend Vite;
- funções Node em
/api/auth/*e/api/db/*; - PostgreSQL acessível por
DATABASE_URL.
APP_URLcomhttpsMAGIC_LINK_SECRETforte, com pelo menos 32 caracteresEMAIL_FROMrealSMTP_HOSTconfiguradoAUTH_COOKIE_SECURE=true
Depois de provisionar o banco:
- aplicar a estrutura com
npm run db:bootstrapou equivalente; - executar
npm run db:seedsudouma única vez para criar o primeiroadmin_global.
- O ranking depende de formulários persistidos no banco, não só da flag de liberação.
- O refinamento de dados usa persistência local e remota; snapshots antigos com
lengthcomo string já são normalizados pela aplicação. - Admin regional revisa solicitações apenas do próprio estado ou cidade.
- A página inicial não expõe mais os atalhos antigos de
Aprimorar os dadoseAvaliar infraestrutura; o fluxo parte da página/avaliacao.
Veja LICENSE.md.