WallpaperMachine
당신이 사랑하는 배경화면, 맥에서 새롭게 만나보세요
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기[FatecDSM-2026/2] Nova versão do Busca Bus, refeita em React
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Originalmente projetado para uso interno na Fatec Zona Leste, o projeto cresceu e agora atende qualquer instituição do município de São Paulo, em toda localidade onde os ônibus da SPTrans atuam. O sistema consulta a API Olho Vivo da SPTrans e mostra, em uma "exibição" (um painel pensado para ficar aberto numa tela), os ônibus que estão chegando a uma ou mais paradas, com o status de cada um (Normal, Atrasado ou Adiantado).
Este repositório é a versão refeita em React/Next.js do projeto original (Sistema-Monitoramento-Linhas-Onibus, feito com Jekyll, JavaScript puro e Supabase). A atualização das exibições agora é feita por WebSocket (Socket.IO), não mais por consultas repetidas do navegador.
https://www.sptrans.com.br/itinerarios/linha/?numero=<letreiro>, substituindo <letreiro> pelo letreiro completo de algum ônibus que passa pelo ponto (ex.: 273D-10).Parada&PID=. Navegador (apps/web) Servidor (apps/server) SPTrans
┌──────────────────────┐ WebSocket ┌──────────────────────────┐ HTTPS ┌────────────┐
│ Next.js + React 19 │◄──────────►│ Express + Socket.IO │──────────►│ Olho Vivo │
│ Exibição, mapa, etc. │ (REST só │ - poller (1 consulta por│ (token │ API v2.1 │
└──────────────────────┘ fallback) │ parada, compartilhada)│ no └────────────┘
│ - salas por exibição │ servidor)
│ - MongoDB (opcional) │
└──────────────────────────┘
COALESCING_MS)./v1/exibicoes/:codigo/radar como contingência (a cada 10 s, respondida do cache do servidor).tempoAtraso min → Atrasado; ≤ −tempoAdiantado min → Adiantado; senão Normal.Monorepo com npm workspaces (apps/* e packages/*).
.
├── apps/
│ ├── web/ # Site (Next.js 16, App Router, React 19, Tailwind CSS v4, Leaflet)
│ │ └── src/
│ │ ├── app/
│ │ │ ├── (site)/ # Páginas públicas: início, exibição, mapa, configuração, favoritos, sobre...
│ │ │ └── (auth)/ # login, cadastro, reset-senha (sem o cabeçalho do site)
│ │ ├── components/ # Por domínio: layout, ui, home, exibicao, configuracao, listas, mapa, auth
│ │ ├── contexts/ # Auth (mock), acessibilidade, loading, cabeçalho
│ │ ├── hooks/ # useExibicao, useRadarOnibus (conexão Socket.IO + fallback REST)
│ │ ├── lib/fixtures/ # Dados fictícios temporários (exibições, instituições, usuário, mapa)
│ │ └── store/ # Favoritos (Zustand)
│ ├── server/ # API REST + Socket.IO (Node.js, Express 5, MongoDB)
│ │ └── src/
│ │ ├── index.js # Ponto de entrada
│ │ ├── config.js # Leitura e validação das variáveis de ambiente
│ │ ├── db.js # Conexão e índices do MongoDB
│ │ ├── http/ # app.js + routes/ (health, auth, exibicoes, me)
│ │ ├── realtime/ # socket.js (salas, snapshots) e poller.js (consulta à SPTrans)
│ │ ├── sptrans/ # cliente.js (login/cookie/renovação), normalizar.js, simulador.js
│ │ └── repos/ # Acesso ao banco (exibições, usuários)
│ └── mobile/ # React Native (em preparação, ainda não executável)
├── packages/
│ └── core/ # Código compartilhado e sem dependência de plataforma:
│ # eventos do socket, cálculo de status, tempo, DTOs, validações, cliente da API, stores
├── render.yaml # Blueprint de hospedagem no Render (site estático + servidor)
├── CLAUDE.md / AGENTS.md # Convenções do projeto para agentes de IA
└── package.json # Scripts do monorepo
Regra de organização: código de navegador/Next.js fica em apps/web, código React Native em apps/mobile e lógica sem plataforma em packages/core.
git clone https://github.com/Mateus-SR/Busca-Bus-React.git e entre na pasta.npm install
.env* são ignorados pelo Git; nunca coloque credenciais no repositório)
.env na raiz do projeto:
# Token da API Olho Vivo (suficiente para o teste local)
SPTRANS_DEFAULT_TOKEN="<seu token da API Olho Vivo>"
apps/web/.env.local para o site falar com o servidor:
NEXT_PUBLIC_API_URL="http://localhost:4000"
Sem essa variável, o site funciona apenas com dados fictícios (fixtures), sem WebSocket.npm run dev:server
http://localhost:4000.JWT_SECRET e MONGODB_URI, o servidor sobe mesmo assim e avisa no console que login e banco estão desabilitados.npm run dev
http://localhost:3000.http://localhost:4000/v1/health deve responder {"ok":true,...}.http://localhost:3000/exibicao?codigo=dev para ver a exibição de teste local, que usa a parada 650004840. Ela só existe enquanto o MONGODB_URI não estiver configurado (o alias testes também é aceito pelo servidor). Digite a URL direto no navegador: o campo da tela inicial exige 6 caracteres.GET http://localhost:4000/v1/paradas/650004840/validar
GET http://localhost:4000/v1/exibicoes/dev/radar
Com
NEXT_PUBLIC_API_URLdefinida, a exibiçãodevusa a SPTrans real. As exibiçõesUpilXc,Busca1eFatec2(dados de demonstração do site) usam as paradas definidas emapps/web/src/lib/fixtures/exibicoesFixture.js, e a SPTrans pode não reconhecer todos esses códigos. Se existirem no MongoDB, os dados do banco substituem os da fixture.
Para ter exibições próprias e contas de usuário, acrescente ao .env da raiz:
MONGODB_URI="<sua string de conexão do MongoDB>"
MONGODB_DB="<nome do banco, ex.: Bus>"
JWT_SECRET="<um segredo longo e aleatório>"
O servidor cria os índices necessários ao iniciar. Veja o formato das exibições.
.env na raiz do repositório)| Variável | Obrigatória | Padrão | Descrição |
|---|---|---|---|
SPTRANS_DEFAULT_TOKEN | Para ônibus reais | — | Token da API Olho Vivo. Usado só pelo servidor. |
MONGODB_URI | Sim, em produção | — | String de conexão do MongoDB. Sem ela, as rotas de banco respondem 503 e só a exibição de teste local funciona. |
MONGODB_DB | Recomendada | (banco da MONGODB_URI; se não houver, test) | Nome do banco. Tem prioridade sobre o nome na MONGODB_URI. Sem ela e sem banco na URI, tudo é gravado no banco padrão test (o servidor avisa no log). O nome diferencia maiúsculas de minúsculas. |
JWT_SECRET | Sim, em produção | — | Segredo de assinatura dos tokens de login. Sem ele, a autenticação fica desabilitada. |
ALLOWED_ORIGINS | Sim, em produção | (qualquer origem) | Origens permitidas pelo CORS, separadas por vírgula, sem barra final (ex.: https://meu-site.onrender.com). |
NODE_ENV | Não | development | Em production, as três variáveis acima passam a ser obrigatórias. |
PORT / HOST | Não | 4000 / 0.0.0.0 | Porta e endereço do servidor. |
SPTRANS_BASE_URL | Não | https://api.olhovivo.sptrans.com.br/v2.1 | Endereço base da API Olho Vivo. |
SPTRANS_TIMEOUT_MS | Não | 10000 | Tempo limite das chamadas à SPTrans. |
POLL_INTERVALO_MS | Não | 5000 | Intervalo entre consultas por parada. |
COALESCING_MS | Não | 500 | Janela para juntar as paradas de uma exibição em um único snapshot. |
apps/web/.env.local, ou variável do ambiente de build)| Variável | Obrigatória | Descrição |
|---|---|---|
NEXT_PUBLIC_API_URL | Para tempo real | URL do servidor (ex.: http://localhost:4000). É embutida no build: depois de alterá-la, é preciso gerar o site de novo. |
Em qualquer exibição, o painel oculto "Detalhes técnicos" abre pelo botão abaixo do código da exibição ou com Ctrl + Shift + D. Ele só coleta diagnóstico enquanto está aberto, guarda os últimos 30 snapshots, nunca mostra o token ou o cookie da SPTrans e permite limpar o histórico ou forçar uma atualização. Com o Socket.IO conectado, mostra também clientes conectados, salas ativas, entradas/saídas, snapshots enviados e o histórico de quedas e reconexões.
Com o simulador de falhas habilitado (padrão fora de produção), o painel também permite injetar problemas entre o servidor e a SPTrans, que expiram sozinhos (padrão 60 s, máximo 10 min):
| Cenário | O que simula |
|---|---|
rede | Sem internet |
timeout | SPTrans não responde |
erro500 | SPTrans com erro 500 |
lenta | SPTrans lenta (+3 s) |
vazia | Resposta sem previsões |
json_invalido | HTML no lugar de JSON |
| queda do socket | Derruba só o WebSocket, para testar a reconexão |
O simulador afeta todas as salas do servidor. Em produção deixe-o desligado (não defina
SIMULACAO_FALHAS=1).
O repositório já traz um Blueprint do Render (render.yaml, na raiz) com dois serviços: o site estático (busca-bus-web) e o servidor (busca-bus-server, plano gratuito).
MONGODB_URI). Em Network Access, permita a conexão do Render: no plano gratuito os IPs de saída mudam, então costuma-se liberar 0.0.0.0/0. Nesse caso, use um usuário de banco com senha forte.render.yaml.sync: false:
MONGODB_URI: a string do passo 1, sem aspas.MONGODB_DB: já vem com o valor Bus pelo Blueprint; altere se o seu banco tiver outro nome (diferencia maiúsculas de minúsculas).SPTRANS_DEFAULT_TOKEN: seu token do Olho Vivo.ALLOWED_ORIGINS: a URL do site estático (ex.: https://busca-bus-web.onrender.com, sem barra final).ENCRYPTION_KEY, APP_URL, EMAIL_API_KEY: podem ficar em branco por enquanto (reservadas).JWT_SECRET é gerada automaticamente pelo Render.https://busca-bus-server.onrender.com) e, no serviço busca-bus-web, defina NEXT_PUBLIC_API_URL com essa URL.https://<seu-servidor>/v1/health (é o mesmo endereço usado pelo health check do Render).Observações do Blueprint:
rootDir: os serviços dependem de packages/core e do package-lock.json da raiz. O buildFilter evita deploys desnecessários.next.config.mjs usa output: "export", ou seja, gera um site 100% estático. Rode npm ci && npm run build com NEXT_PUBLIC_API_URL definida e publique a pasta apps/web/out em qualquer hospedagem estática (Netlify, Cloudflare Pages, Vercel, GitHub Pages...). Para publicar em um subcaminho (ex.: GitHub Pages de projeto) é preciso configurar basePath no next.config.mjs.npm ci e npm run start:server, com as variáveis de ambiente definidas e NODE_ENV=production.npx serve apps/web/out. npm run start não funciona neste projeto, porque o next start não aceita output: "export".| Quero mudar... | Onde mexer |
|---|---|
| Uma tela ou rota do site | apps/web/src/app/(site)/... (públicas) ou (auth)/... (login/cadastro) |
| Layout e componentes visuais | apps/web/src/components/<domínio>/ |
| Cores, fontes e animações | apps/web/src/app/globals.css (Tailwind v4 configurado via @theme; a cor da marca é sptrans) |
| Como o site recebe os ônibus (WebSocket e fallback REST) | apps/web/src/hooks/useRadarOnibus.js |
| Exibições de demonstração do site | apps/web/src/lib/fixtures/exibicoesFixture.js |
| Regras de status (atrasado/adiantado) | packages/core/src/status.js |
| Nomes dos eventos do socket | packages/core/src/eventos.js (usados por site e servidor) |
| Intervalo padrão de coleta | packages/core/src/intervalos.js (ou POLL_INTERVALO_MS) |
| Integração com a SPTrans | apps/server/src/sptrans/ |
| Consulta e cache por parada | apps/server/src/realtime/poller.js |
| Salas, limites e snapshots do WebSocket | apps/server/src/realtime/socket.js |
| Rotas REST | apps/server/src/http/routes/ |
Convenções (mais detalhes em CLAUDE.md):
codigo, erro, estaLogado, handleAcessar)."use client"; os demais são Server Components.@/* para importar de apps/web/src/*.next/dynamic e ssr: false..prettierrc: tabs, aspas simples, prettier-plugin-tailwindcss).As exibições ficam na coleção exibicoes (o banco é o definido em MONGODB_DB ou, se ela estiver vazia, na MONGODB_URI). Ainda não existe rota para criá-las: por enquanto, insira o documento manualmente (mongosh, Compass ou Atlas):
{
"codigo": "UpilXc",
"nome": "Fatec Zona Leste",
"paradas": ["650004840", "650004841"],
"config": {
"tempoAtraso": 2,
"tempoAdiantado": 2,
"distanciaMaxMin": 20,
"permitirMultiplosPorLinha": false
},
"ativo": true,
"criadoEm": "2026-01-01T00:00:00.000Z"
}
| Campo | Significado |
|---|---|
codigo | Código de acesso (letras, números, _ ou -; a tela inicial exige 6 caracteres) |
paradas | Códigos de parada da SPTrans (7 a 9 dígitos; no máximo 8 por exibição) |
tempoAtraso / tempoAdiantado | Minutos de diferença para marcar o ônibus como Atrasado / Adiantado (0 a 120) |
distanciaMaxMin | Só mostra ônibus que chegam em até X minutos (0 a 180) |
permitirMultiplosPorLinha | false: mostra só o próximo ônibus de cada linha; true: mostra todos |
ativo | false esconde a exibição sem apagá-la |
Para a exibição aparecer no site hospedado, o código também precisa estar em apps/web/src/lib/fixtures/exibicoesFixture.js (veja as limitações).
/v1)Limite geral de 120 requisições por minuto por IP; as rotas de autenticação têm limite próprio.
| Método e rota | Descrição |
|---|---|
GET /v1/health | Estado do servidor (versão, ambiente, banco, memória) |
GET /v1/paradas/:codigo/validar | Confere se a SPTrans responde para o código da parada |
GET /v1/exibicoes/:codigo | Dados de uma exibição |
GET /v1/exibicoes/:codigo/radar | Snapshot atual (contingência do WebSocket). Aceita ?diagnostico=1 e ?permitirMultiplosPorLinha=true|false |
POST /v1/auth/cadastro, POST /v1/auth/login | Criar conta e entrar (exigem MONGODB_URI e JWT_SECRET) |
/v1/auth/refresh, /v1/auth/reset-senha, /v1/me/* | Ainda não implementados (respondem 501) |
Os nomes dos eventos ficam em packages/core/src/eventos.js.
| Evento | Direção | Uso |
|---|---|---|
exibicao:entrar | cliente → servidor | Entra na sala: { codigo, paradas, config, diagnostico } |
exibicao:configurar | cliente → servidor | Altera a configuração da sala |
exibicao:diagnostico | cliente → servidor | Liga/desliga o bloco de diagnóstico para aquele navegador |
exibicao:simular | cliente → servidor | Aciona um cenário de falha (só com o painel aberto e o simulador ligado) |
exibicao:sair | cliente → servidor | Sai da sala |
heartbeat | cliente → servidor | Confirma que a conexão está viva |
exibicao:snapshot | servidor → cliente | Lista atual de ônibus, ponto(s), configuração e estado da conexão |
servidor:aviso | servidor → cliente | Avisos do servidor (ex.: reiniciando) |
Limites por conexão: 30 eventos a cada 10 s e mensagens de até 64 KB.
output: "export"), então qualquer código de exibição funciona sem gerar página nova: /exibicao?codigo=XXXXXX, /mapa?codigo=XXXXXX e /configuracao?editar=XXXXXX. As páginas leem o parâmetro com useSearchParams dentro de <Suspense>.AuthContext usa um usuário de mentira guardado no localStorage. A API de login existe no servidor, mas o site ainda não a usa.apps/web/src/lib/fixtures/). Sem NEXT_PUBLIC_API_URL, a exibição também mostra ônibus fictícios.apps/mobile é só um esqueleto (componentes e stores iniciais); ainda não há app para executar.Todos rodam a partir da raiz do repositório.
| Comando | O que faz |
|---|---|
npm install | Instala as dependências de todo o monorepo |
npm run dev | Site em modo de desenvolvimento (http://localhost:3000) |
npm run dev:server | Servidor em modo de desenvolvimento, com reinício automático (http://localhost:4000) |
npm run build | Gera o site estático em apps/web/out |
npm run build:server | Verifica a sintaxe do servidor (node --check; não há etapa de compilação) |
npm run start:server | Inicia o servidor (produção) |
npm run lint | ESLint do site |
Antes de abrir um pull request, rode npm run lint, npm run build e npm run build:server.
SIMULACAO_FALHAS |
| Não |
| ligada fora de produção |
1 liga e 0 desliga o simulador de falhas (veja abaixo). Em produção só liga se for 1. |
TEST_DISPLAY_CODE | Não | dev | Código da exibição de teste local (sem MongoDB). |
TEST_STOP_CODE / TEST_STOP_CODES | Não | 650004840 | Parada(s) da exibição de teste local; TEST_STOP_CODES aceita vários códigos separados por vírgula. |
ENCRYPTION_KEY, APP_URL | Não | — | Reservadas para recursos futuros; o servidor atual lê, mas ainda não usa. |