Latest commit

History

527 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

<Cand!Date!>

Novo no projeto? Comece por aqui: LOCAL_DEVELOPMENT.md

CINode >= 22MonorepoLicense ISC

Documentação: README | SCRAPER | BACKEND | TESTING | CONTRIBUTING | ESCOPO | Frontend | Frontend Architecture | Front Admin

Plataforma de captura, agregação e consulta de vagas com arquitetura monorepo, composta por frontend web, API Node.js, scraper Go, painel administrativo e aplicação desktop com Electron.

O produto evoluiu para um modelo orientado a serviços (API + scraper Go + cache/índices), com autenticação, preferências de usuário e integração com banco de dados.

Links oficiais

Sumário

Visão geral

Este repositório centraliza as frentes principais do produto:

  • frontend: aplicação web para usuários finais, com landing page, autenticação e dashboard de vagas. A nova estrutura de painel do frontend fica em frontend/src/domains/new_dashboard.
  • backend: API Node.js/Express com autenticação, perfis, preferências, vagas salvas, notificações, rotas admin e observabilidade.
  • scraper-go: serviço Go de scraping multi-fonte, cache, deduplicação e indexação em Valkey.
  • front_admin: painel administrativo para operação, usuários, permissões, scrapers, auditoria e observabilidade.
  • electron: shell desktop que empacota a experiência principal.

Objetivo de produto: fornecer uma base robusta para busca, filtragem e gestão de vagas com foco em qualidade de dados, escalabilidade e operação contínua.

Arquitetura do monorepo

.
├─ frontend/ # Dashboard web (React + Vite)
├─ backend/ # API Node.js (Express + TS + Drizzle)
├─ scraper-go/ # Serviço Go de scraping multi-fonte
├─ front_admin/ # Painel administrativo (React + Vite)
├─ electron/ # Shell desktop
├─ docker-compose.yml # App stack (frontend + front_admin + backend + scraper-go)
├─ docker-compose.infra.yml # Infra stack (Postgres + Valkey)
├─ docker-compose.migrate.yml # Migration job do backend
└─ .github/workflows/ci.yml # CI

Stack real do projeto

  • Frontend: React 19, TypeScript, Vite 8, Tailwind CSS, Vitest.
  • Front admin: React 19, TypeScript, Vite 8, Tailwind CSS 4, Vitest.
  • Backend: Node.js 22+, Express 5, TypeScript, Drizzle ORM, Zod, Iron Session, Redis/Valkey.
  • Scraping: Go (serviço dedicado em scraper-go).
  • Desktop: Electron + Electron Builder.
  • Qualidade: Vitest (frontend/backend/front_admin), cobertura v8, ESLint (frontend/front_admin), GitHub Actions CI.
  • Dados: Postgres (persistência) + Valkey/Redis (cache e índice).

Quickstart local

Pré-requisitos

  • Node.js >= 22
  • npm
  • Docker Desktop com Docker Compose

Caminho recomendado: stack completa com Docker

Use este fluxo para subir Postgres, Valkey, scraper Go, backend, frontend e front_admin com a mesma rede Docker.

1 - Instale as dependências locais:

npm install

2 - Crie o .env da raiz a partir do exemplo versionado:

cp .env.example .env

No Windows PowerShell:

Copy-Item .env.example .env

3 - Crie a rede Docker compartilhada, se ela ainda não existir:

docker network create vagas-net

Se a rede já existir, o Docker vai avisar e você pode seguir para o próximo passo.

4 - Suba Postgres, Valkey, scraper, backend, frontend e front_admin:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

5 - Acesse os serviços:

Desenvolvimento com Node local

Use este fluxo quando quiser rodar frontend/backend fora do Docker. Mantenha Postgres e Valkey ativos no Docker e configure URLs locais nos arquivos .env.

Arquivos esperados:

  • .env: usado pela infra/scraper e por comandos auxiliares.
  • backend/.env: usado pelo backend local.
  • frontend/.env: usado pelo Vite local.
  • front_admin usa VITE_API_URL, mas ainda não possui .env.example próprio.

Criação dos arquivos locais:

cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env

No Windows PowerShell:

Copy-Item backend/.env.example backend/.env
Copy-Item frontend/.env.example frontend/.env

Comandos:

npm run dev

Esse comando sobe apenas o necessário para a maioria das contribuições: frontend e backend.

Para trabalhar também no painel administrativo:

npm run dev:admin

Execução separada:

npm run dev:frontend
npm run dev:backend
npm run dev:front_admin

Execução de testes

npm run test:coverage

Instalação limpa e CI

Para onboarding e desenvolvimento local, prefira npm install.

Use npm ci em automações como GitHub Actions, Docker/deploy ou quando quiser reinstalar tudo exatamente a partir do package-lock.json. Ele remove node_modules, não altera o lockfile e falha se package.json e package-lock.json estiverem fora de sincronia.

Comandos verificados

Os comandos abaixo existem hoje no repositório e foram conferidos nos package.json da raiz, backend, frontend e front_admin.

Raiz

  • npm run dev
  • npm run dev:admin
  • npm run dev:frontend
  • npm run dev:backend
  • npm run dev:front_admin
  • npm run scraper
  • npm run scraper:watch
  • npm run test
  • npm run test:coverage
  • npm run build
  • npm run build:frontend
  • npm run build:front_admin
  • npm run validate
  • npm run electron
  • npm run electron:dev
  • npm run dist
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Backend

  • npm run start
  • npm run dev
  • npm run api
  • npm run test
  • npm run test:coverage
  • npm run test:watch
  • npm run validate
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Frontend

  • npm run dev
  • npm run build
  • npm run lint
  • npm run preview
  • npm run test
  • npm run test:coverage
  • npm run test:watch

Front admin

  • npm run dev
  • npm run build
  • npm run lint
  • npm run test
  • npm run test:coverage
  • npm run preview

API backend (estado atual)

Base: /

Sistema:

  • GET /health

Autenticação:

  • GET /auth/:provider/url
  • GET /auth/:provider/callback
  • POST /auth/register
  • POST /auth/login
  • POST /auth/logout
  • GET /auth/me

Usuários:

  • GET /users/profile
  • PATCH /users/profile
  • GET /users/preferences
  • POST /users/preferences
  • PATCH /users/preferences

Jobs:

  • GET /jobs/search
    • Busca vagas nos índices do Valkey e aceita filtros por keywords, family, technology, seniority, level, location, country, type/model, contract e ordenação por matchSort.

Keywords:

  • GET /keywords
  • POST /keywords

Saved jobs:

  • GET /saved-jobs
  • GET /saved-jobs/:id
  • POST /saved-jobs
  • PATCH /saved-jobs/:id
  • DELETE /saved-jobs/:id

Admin:

  • GET /admin/users
  • GET /admin/users/:id
  • PATCH /admin/users/:id/block
  • PATCH /admin/users/:id/unblock
  • POST /admin/users/:id/reset
  • POST /admin/scrapers/run
  • GET /admin/observability/metrics
  • GET /admin/observability/dashboards
  • GET /admin/audit
  • GET /admin/permissions/rules

Swagger:

  • GET /docs

Docker (infra + aplicação)

Este projeto separa infraestrutura e aplicação em dois arquivos Compose:

  • docker-compose.infra.yml: Postgres + Valkey.
  • docker-compose.yml: scraper Go + backend + frontend + front_admin.
  • docker-compose.migrate.yml: job de migrations do backend.

Subir infraestrutura, migrations e aplicação:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

O serviço migrate executa npm run db:migrate e npm run security:backfill-user-pii -- --write depois que o Postgres fica saudável. O backend só inicia depois que esse job termina com sucesso.

Se quiser subir apenas a infraestrutura:

docker compose -f docker-compose.infra.yml up -d

Se quiser subir a aplicação sem o job de migrations:

docker compose up --build -d

Ver logs:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f migrate
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f backend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f frontend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f front_admin
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f scraper-go

Encerrar:

docker compose down
docker compose -f docker-compose.infra.yml down

Observação: os volumes Docker preservam os dados do Postgres e do Valkey entre execuções. Se você alterar POSTGRES_USER, POSTGRES_PASSWORD ou POSTGRES_DB depois da primeira inicialização, será necessário recriar o volume do Postgres ou manter os valores antigos.

Dentro dos containers, serviços devem usar os nomes da rede Docker:

  • Postgres: postgres:5432
  • Valkey: valkey:6379
  • Scraper: scraper-go:8081

Por isso o docker-compose.yml e o docker-compose.migrate.yml sobrescrevem variáveis como DATABASE_URL, VALKEY_URL, GO_SCRAPER_URL e SCRAPER_URL para os valores internos corretos.

Serviços padrão:

Endpoints úteis do scraper:

Desktop com Electron

O app desktop empacota frontend + backend e inicia a aplicação com Electron.

Comandos:

npm run build:frontend
npm run electron

Distribuição (Windows):

npm run dist

Saída esperada do instalador:

  • dist-electron/Vagas Full Setup X.X.X.exe

Variáveis de ambiente

Arquivos de exemplo:

  • .env.example
  • backend/.env.example
  • frontend/.env.example

Arquivos locais ignorados pelo Git:

  • .env
  • backend/.env
  • frontend/.env
  • front_admin/.env, se criado localmente

Uso recomendado:

  • Docker Compose: copie .env.example para .env. O Compose usa esse arquivo para infra, scraper, backend e build do frontend.
  • Backend local via Node: use backend/.env.
  • Frontend local via Vite: use frontend/.env.
  • Front admin local via Vite: crie front_admin/.env com VITE_API_URL=http://localhost:3001 quando precisar sobrescrever o padrão.

Variáveis centrais de operação:

  • DATABASE_URL
  • VALKEY_URL
  • GO_SCRAPER_URL
  • SESSION_SECRET
  • CORS_ALLOWED_ORIGINS
  • SEARCH_LOCATION
  • SEARCH_GEO_ID
  • SEARCH_LANGUAGE
  • REMOTE_ONLY
  • JOB_TYPES
  • TIME_FILTER
  • WAIT_BETWEEN_SEARCHES_MS
  • PAGE_TIMEOUT_MS
  • MAX_PAGES_PER_KEYWORD
  • LINKEDIN_KEYWORD_SLOT_SIZE
  • ADZUNA_KEYWORD_SLOT_SIZE
  • GUPY_ENABLED
  • GUPY_RAW_DISCOVERY_ENABLED
  • GUPY_FULL_SWEEP_ENABLED
  • GUPY_FULL_REMOTE_SWEEP_ENABLED
  • GUPY_QUERY_LIMIT
  • INHIRE_ENABLED
  • INHIRE_ENRICH_DETAILS
  • GREENHOUSE_ENABLED
  • LEVER_ENABLED
  • CACHE_TTL_MS
  • VITE_API_BASE_URL
  • VITE_API_URL
  • VITE_API_PROXY_TARGET
  • VITE_APP_ENV

Segurança operacional:

  • Nunca versionar segredos reais no Git.
  • Preferir acesso interno para banco/cache em VPS.
  • Em ambiente externo, usar TLS para conexões de dados sempre que possível.

Observação operacional do scraper:

  • O padrão atual privilegia resposta rápida e estabilidade. LinkedIn e Adzuna usam slots rotativos de keywords por execução, e Gupy limita a quantidade de queries expandidas por rodada. Isso reduz cobertura imediata por execução, mas evita milhares de requests em uma única rodada e distribui a coleta ao longo das próximas execuções.
  • tools/ e data/ são ignorados pelo Git. Scripts versionados não devem depender de arquivos nessas pastas, a menos que sejam tratados como utilitários locais opcionais.

Testes e qualidade

Estrutura:

  • backend/tests/unit
  • backend/tests/integration
  • frontend/tests/unit
  • frontend/tests/integration
  • front_admin/tests

Threshold mínimo:

  • lines >= 80%
  • statements >= 80%
  • functions >= 80%
  • branches >= 80%

Comandos:

npm run test:coverage
npm --workspace frontend run test:coverage
npm --workspace backend run test:coverage
npm --workspace front_admin run test:coverage

Observação importante: o backend já está configurado para coletar cobertura apenas em src/**/*.ts, evitando contagem de artefatos gerados.

CI/CD

Workflow atual: .github/workflows/ci.yml

Executa em push para master/develop e em pull_request:

  • Instalação de dependências
  • Coverage frontend
  • Coverage backend
  • Lint frontend
  • Build frontend

Observação: o painel admin já possui testes e build próprios, mas ainda deve ser incluído no fluxo de validação/CI quando se tornar parte obrigatória do release.

Fluxo de desenvolvimento e branching

Padrão oficial:

  1. Abrir card no Linear: https://linear.app/tatame/team/PAV/all
  2. Criar branch de feature a partir de master
  3. Desenvolver e testar localmente
  4. Abrir PR da feature para develop
  5. Após aprovação e validação, merge em develop
  6. Abrir PR de develop para master
  7. Merge em master para release

Convenção recomendada de branch:

  • feature/{id-do-card}-{descricao-curta}

Git Hooks e qualidade local

O repositório usa Husky na raiz do monorepo para padronizar validações locais em qualquer branch.

Hooks configurados:

  • pre-commit: executa lint-staged para validar arquivos staged do frontend.
  • commit-msg: valida mensagem de commit com commitlint (Conventional Commits).
  • pre-push: executa validação do monorepo (test backend + lint/build frontend).

Bootstrap local com instalação e hooks:

npm run setup:dev

Checklist quando hooks não disparam:

  1. Validar se o diretório Git foi detectado: git rev-parse --git-dir.
  2. Validar hooksPath local: git config --get core.hooksPath.
  3. Confirmar arquivos versionados em .husky (pre-commit, commit-msg, pre-push).
  4. Reinstalar hooks: npm run prepare.
  5. Em Windows, preferir Git Bash para depuração de scripts shell.

Observação importante:

  • CI continua obrigatório e independente de hooks locais. Mesmo com bypass local, o pipeline valida cobertura/lint/build antes de merge.

Roadmap técnico sugerido

DX e onboarding

  • Adicionar script único de bootstrap (exemplo: npm run setup:dev) para criar .env e validar pré-requisitos.
  • Adicionar verificação automática de scripts quebrados no CI.
  • Padronizar comandos cross-platform (evitar dependência de sintaxe de variável de ambiente Unix em scripts críticos).

Segurança

  • Aplicar política de rotação de SESSION_SECRET e credenciais OAuth.
  • Adicionar checklist de segurança para PRs (cookies, CORS, secrets, headers).

Performance

  • Definir estratégia de paginação e filtros em camada de API com métricas por endpoint.
  • Revisar TTL e cardinalidade dos índices no Valkey para reduzir consumo de memória.

Observabilidade

  • Padronizar correlação de logs por request id.
  • Publicar guia mínimo de troubleshooting com sinais de saúde dos serviços frontend/backend/scraper-go.

Contribuição

  1. Abra um card no Linear.
  2. Crie branch a partir de master.
  3. Implemente com testes.
  4. Execute validações locais:
npm run validate
npm run test:coverage
  1. Abra PR para develop com contexto técnico objetivo.

Se você vai trabalhar em backend, scraper ou testes, use também:

About

Simplifique sua busca por emprego. Todas as oportunidades do mercado reunidas em uma plataforma inteligente e automatizada.

Topics

Resources

Stars

86 stars

Watchers

3 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

527 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

<Cand!Date!>

Novo no projeto? Comece por aqui: LOCAL_DEVELOPMENT.md

CINode >= 22MonorepoLicense ISC

Documentação: README | SCRAPER | BACKEND | TESTING | CONTRIBUTING | ESCOPO | Frontend | Frontend Architecture | Front Admin

Plataforma de captura, agregação e consulta de vagas com arquitetura monorepo, composta por frontend web, API Node.js, scraper Go, painel administrativo e aplicação desktop com Electron.

O produto evoluiu para um modelo orientado a serviços (API + scraper Go + cache/índices), com autenticação, preferências de usuário e integração com banco de dados.

Links oficiais

Sumário

Visão geral

Este repositório centraliza as frentes principais do produto:

  • frontend: aplicação web para usuários finais, com landing page, autenticação e dashboard de vagas. A nova estrutura de painel do frontend fica em frontend/src/domains/new_dashboard.
  • backend: API Node.js/Express com autenticação, perfis, preferências, vagas salvas, notificações, rotas admin e observabilidade.
  • scraper-go: serviço Go de scraping multi-fonte, cache, deduplicação e indexação em Valkey.
  • front_admin: painel administrativo para operação, usuários, permissões, scrapers, auditoria e observabilidade.
  • electron: shell desktop que empacota a experiência principal.

Objetivo de produto: fornecer uma base robusta para busca, filtragem e gestão de vagas com foco em qualidade de dados, escalabilidade e operação contínua.

Arquitetura do monorepo

.
├─ frontend/ # Dashboard web (React + Vite)
├─ backend/ # API Node.js (Express + TS + Drizzle)
├─ scraper-go/ # Serviço Go de scraping multi-fonte
├─ front_admin/ # Painel administrativo (React + Vite)
├─ electron/ # Shell desktop
├─ docker-compose.yml # App stack (frontend + front_admin + backend + scraper-go)
├─ docker-compose.infra.yml # Infra stack (Postgres + Valkey)
├─ docker-compose.migrate.yml # Migration job do backend
└─ .github/workflows/ci.yml # CI

Stack real do projeto

  • Frontend: React 19, TypeScript, Vite 8, Tailwind CSS, Vitest.
  • Front admin: React 19, TypeScript, Vite 8, Tailwind CSS 4, Vitest.
  • Backend: Node.js 22+, Express 5, TypeScript, Drizzle ORM, Zod, Iron Session, Redis/Valkey.
  • Scraping: Go (serviço dedicado em scraper-go).
  • Desktop: Electron + Electron Builder.
  • Qualidade: Vitest (frontend/backend/front_admin), cobertura v8, ESLint (frontend/front_admin), GitHub Actions CI.
  • Dados: Postgres (persistência) + Valkey/Redis (cache e índice).

Quickstart local

Pré-requisitos

  • Node.js >= 22
  • npm
  • Docker Desktop com Docker Compose

Caminho recomendado: stack completa com Docker

Use este fluxo para subir Postgres, Valkey, scraper Go, backend, frontend e front_admin com a mesma rede Docker.

1 - Instale as dependências locais:

npm install

2 - Crie o .env da raiz a partir do exemplo versionado:

cp .env.example .env

No Windows PowerShell:

Copy-Item .env.example .env

3 - Crie a rede Docker compartilhada, se ela ainda não existir:

docker network create vagas-net

Se a rede já existir, o Docker vai avisar e você pode seguir para o próximo passo.

4 - Suba Postgres, Valkey, scraper, backend, frontend e front_admin:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

5 - Acesse os serviços:

Desenvolvimento com Node local

Use este fluxo quando quiser rodar frontend/backend fora do Docker. Mantenha Postgres e Valkey ativos no Docker e configure URLs locais nos arquivos .env.

Arquivos esperados:

  • .env: usado pela infra/scraper e por comandos auxiliares.
  • backend/.env: usado pelo backend local.
  • frontend/.env: usado pelo Vite local.
  • front_admin usa VITE_API_URL, mas ainda não possui .env.example próprio.

Criação dos arquivos locais:

cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env

No Windows PowerShell:

Copy-Item backend/.env.example backend/.env
Copy-Item frontend/.env.example frontend/.env

Comandos:

npm run dev

Esse comando sobe apenas o necessário para a maioria das contribuições: frontend e backend.

Para trabalhar também no painel administrativo:

npm run dev:admin

Execução separada:

npm run dev:frontend
npm run dev:backend
npm run dev:front_admin

Execução de testes

npm run test:coverage

Instalação limpa e CI

Para onboarding e desenvolvimento local, prefira npm install.

Use npm ci em automações como GitHub Actions, Docker/deploy ou quando quiser reinstalar tudo exatamente a partir do package-lock.json. Ele remove node_modules, não altera o lockfile e falha se package.json e package-lock.json estiverem fora de sincronia.

Comandos verificados

Os comandos abaixo existem hoje no repositório e foram conferidos nos package.json da raiz, backend, frontend e front_admin.

Raiz

  • npm run dev
  • npm run dev:admin
  • npm run dev:frontend
  • npm run dev:backend
  • npm run dev:front_admin
  • npm run scraper
  • npm run scraper:watch
  • npm run test
  • npm run test:coverage
  • npm run build
  • npm run build:frontend
  • npm run build:front_admin
  • npm run validate
  • npm run electron
  • npm run electron:dev
  • npm run dist
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Backend

  • npm run start
  • npm run dev
  • npm run api
  • npm run test
  • npm run test:coverage
  • npm run test:watch
  • npm run validate
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Frontend

  • npm run dev
  • npm run build
  • npm run lint
  • npm run preview
  • npm run test
  • npm run test:coverage
  • npm run test:watch

Front admin

  • npm run dev
  • npm run build
  • npm run lint
  • npm run test
  • npm run test:coverage
  • npm run preview

API backend (estado atual)

Base: /

Sistema:

  • GET /health

Autenticação:

  • GET /auth/:provider/url
  • GET /auth/:provider/callback
  • POST /auth/register
  • POST /auth/login
  • POST /auth/logout
  • GET /auth/me

Usuários:

  • GET /users/profile
  • PATCH /users/profile
  • GET /users/preferences
  • POST /users/preferences
  • PATCH /users/preferences

Jobs:

  • GET /jobs/search
    • Busca vagas nos índices do Valkey e aceita filtros por keywords, family, technology, seniority, level, location, country, type/model, contract e ordenação por matchSort.

Keywords:

  • GET /keywords
  • POST /keywords

Saved jobs:

  • GET /saved-jobs
  • GET /saved-jobs/:id
  • POST /saved-jobs
  • PATCH /saved-jobs/:id
  • DELETE /saved-jobs/:id

Admin:

  • GET /admin/users
  • GET /admin/users/:id
  • PATCH /admin/users/:id/block
  • PATCH /admin/users/:id/unblock
  • POST /admin/users/:id/reset
  • POST /admin/scrapers/run
  • GET /admin/observability/metrics
  • GET /admin/observability/dashboards
  • GET /admin/audit
  • GET /admin/permissions/rules

Swagger:

  • GET /docs

Docker (infra + aplicação)

Este projeto separa infraestrutura e aplicação em dois arquivos Compose:

  • docker-compose.infra.yml: Postgres + Valkey.
  • docker-compose.yml: scraper Go + backend + frontend + front_admin.
  • docker-compose.migrate.yml: job de migrations do backend.

Subir infraestrutura, migrations e aplicação:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

O serviço migrate executa npm run db:migrate e npm run security:backfill-user-pii -- --write depois que o Postgres fica saudável. O backend só inicia depois que esse job termina com sucesso.

Se quiser subir apenas a infraestrutura:

docker compose -f docker-compose.infra.yml up -d

Se quiser subir a aplicação sem o job de migrations:

docker compose up --build -d

Ver logs:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f migrate
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f backend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f frontend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f front_admin
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f scraper-go

Encerrar:

docker compose down
docker compose -f docker-compose.infra.yml down

Observação: os volumes Docker preservam os dados do Postgres e do Valkey entre execuções. Se você alterar POSTGRES_USER, POSTGRES_PASSWORD ou POSTGRES_DB depois da primeira inicialização, será necessário recriar o volume do Postgres ou manter os valores antigos.

Dentro dos containers, serviços devem usar os nomes da rede Docker:

  • Postgres: postgres:5432
  • Valkey: valkey:6379
  • Scraper: scraper-go:8081

Por isso o docker-compose.yml e o docker-compose.migrate.yml sobrescrevem variáveis como DATABASE_URL, VALKEY_URL, GO_SCRAPER_URL e SCRAPER_URL para os valores internos corretos.

Serviços padrão:

Endpoints úteis do scraper:

Desktop com Electron

O app desktop empacota frontend + backend e inicia a aplicação com Electron.

Comandos:

npm run build:frontend
npm run electron

Distribuição (Windows):

npm run dist

Saída esperada do instalador:

  • dist-electron/Vagas Full Setup X.X.X.exe

Variáveis de ambiente

Arquivos de exemplo:

  • .env.example
  • backend/.env.example
  • frontend/.env.example

Arquivos locais ignorados pelo Git:

  • .env
  • backend/.env
  • frontend/.env
  • front_admin/.env, se criado localmente

Uso recomendado:

  • Docker Compose: copie .env.example para .env. O Compose usa esse arquivo para infra, scraper, backend e build do frontend.
  • Backend local via Node: use backend/.env.
  • Frontend local via Vite: use frontend/.env.
  • Front admin local via Vite: crie front_admin/.env com VITE_API_URL=http://localhost:3001 quando precisar sobrescrever o padrão.

Variáveis centrais de operação:

  • DATABASE_URL
  • VALKEY_URL
  • GO_SCRAPER_URL
  • SESSION_SECRET
  • CORS_ALLOWED_ORIGINS
  • SEARCH_LOCATION
  • SEARCH_GEO_ID
  • SEARCH_LANGUAGE
  • REMOTE_ONLY
  • JOB_TYPES
  • TIME_FILTER
  • WAIT_BETWEEN_SEARCHES_MS
  • PAGE_TIMEOUT_MS
  • MAX_PAGES_PER_KEYWORD
  • LINKEDIN_KEYWORD_SLOT_SIZE
  • ADZUNA_KEYWORD_SLOT_SIZE
  • GUPY_ENABLED
  • GUPY_RAW_DISCOVERY_ENABLED
  • GUPY_FULL_SWEEP_ENABLED
  • GUPY_FULL_REMOTE_SWEEP_ENABLED
  • GUPY_QUERY_LIMIT
  • INHIRE_ENABLED
  • INHIRE_ENRICH_DETAILS
  • GREENHOUSE_ENABLED
  • LEVER_ENABLED
  • CACHE_TTL_MS
  • VITE_API_BASE_URL
  • VITE_API_URL
  • VITE_API_PROXY_TARGET
  • VITE_APP_ENV

Segurança operacional:

  • Nunca versionar segredos reais no Git.
  • Preferir acesso interno para banco/cache em VPS.
  • Em ambiente externo, usar TLS para conexões de dados sempre que possível.

Observação operacional do scraper:

  • O padrão atual privilegia resposta rápida e estabilidade. LinkedIn e Adzuna usam slots rotativos de keywords por execução, e Gupy limita a quantidade de queries expandidas por rodada. Isso reduz cobertura imediata por execução, mas evita milhares de requests em uma única rodada e distribui a coleta ao longo das próximas execuções.
  • tools/ e data/ são ignorados pelo Git. Scripts versionados não devem depender de arquivos nessas pastas, a menos que sejam tratados como utilitários locais opcionais.

Testes e qualidade

Estrutura:

  • backend/tests/unit
  • backend/tests/integration
  • frontend/tests/unit
  • frontend/tests/integration
  • front_admin/tests

Threshold mínimo:

  • lines >= 80%
  • statements >= 80%
  • functions >= 80%
  • branches >= 80%

Comandos:

npm run test:coverage
npm --workspace frontend run test:coverage
npm --workspace backend run test:coverage
npm --workspace front_admin run test:coverage

Observação importante: o backend já está configurado para coletar cobertura apenas em src/**/*.ts, evitando contagem de artefatos gerados.

CI/CD

Workflow atual: .github/workflows/ci.yml

Executa em push para master/develop e em pull_request:

  • Instalação de dependências
  • Coverage frontend
  • Coverage backend
  • Lint frontend
  • Build frontend

Observação: o painel admin já possui testes e build próprios, mas ainda deve ser incluído no fluxo de validação/CI quando se tornar parte obrigatória do release.

Fluxo de desenvolvimento e branching

Padrão oficial:

  1. Abrir card no Linear: https://linear.app/tatame/team/PAV/all
  2. Criar branch de feature a partir de master
  3. Desenvolver e testar localmente
  4. Abrir PR da feature para develop
  5. Após aprovação e validação, merge em develop
  6. Abrir PR de develop para master
  7. Merge em master para release

Convenção recomendada de branch:

  • feature/{id-do-card}-{descricao-curta}

Git Hooks e qualidade local

O repositório usa Husky na raiz do monorepo para padronizar validações locais em qualquer branch.

Hooks configurados:

  • pre-commit: executa lint-staged para validar arquivos staged do frontend.
  • commit-msg: valida mensagem de commit com commitlint (Conventional Commits).
  • pre-push: executa validação do monorepo (test backend + lint/build frontend).

Bootstrap local com instalação e hooks:

npm run setup:dev

Checklist quando hooks não disparam:

  1. Validar se o diretório Git foi detectado: git rev-parse --git-dir.
  2. Validar hooksPath local: git config --get core.hooksPath.
  3. Confirmar arquivos versionados em .husky (pre-commit, commit-msg, pre-push).
  4. Reinstalar hooks: npm run prepare.
  5. Em Windows, preferir Git Bash para depuração de scripts shell.

Observação importante:

  • CI continua obrigatório e independente de hooks locais. Mesmo com bypass local, o pipeline valida cobertura/lint/build antes de merge.

Roadmap técnico sugerido

DX e onboarding

  • Adicionar script único de bootstrap (exemplo: npm run setup:dev) para criar .env e validar pré-requisitos.
  • Adicionar verificação automática de scripts quebrados no CI.
  • Padronizar comandos cross-platform (evitar dependência de sintaxe de variável de ambiente Unix em scripts críticos).

Segurança

  • Aplicar política de rotação de SESSION_SECRET e credenciais OAuth.
  • Adicionar checklist de segurança para PRs (cookies, CORS, secrets, headers).

Performance

  • Definir estratégia de paginação e filtros em camada de API com métricas por endpoint.
  • Revisar TTL e cardinalidade dos índices no Valkey para reduzir consumo de memória.

Observabilidade

  • Padronizar correlação de logs por request id.
  • Publicar guia mínimo de troubleshooting com sinais de saúde dos serviços frontend/backend/scraper-go.

Contribuição

  1. Abra um card no Linear.
  2. Crie branch a partir de master.
  3. Implemente com testes.
  4. Execute validações locais:
npm run validate
npm run test:coverage
  1. Abra PR para develop com contexto técnico objetivo.

Se você vai trabalhar em backend, scraper ou testes, use também:

About

Simplifique sua busca por emprego. Todas as oportunidades do mercado reunidas em uma plataforma inteligente e automatizada.

Topics

Resources

Stars

86 stars

Watchers

3 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

527 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

<Cand!Date!>

Novo no projeto? Comece por aqui: LOCAL_DEVELOPMENT.md

CINode >= 22MonorepoLicense ISC

Documentação: README | SCRAPER | BACKEND | TESTING | CONTRIBUTING | ESCOPO | Frontend | Frontend Architecture | Front Admin

Plataforma de captura, agregação e consulta de vagas com arquitetura monorepo, composta por frontend web, API Node.js, scraper Go, painel administrativo e aplicação desktop com Electron.

O produto evoluiu para um modelo orientado a serviços (API + scraper Go + cache/índices), com autenticação, preferências de usuário e integração com banco de dados.

Links oficiais

Sumário

Visão geral

Este repositório centraliza as frentes principais do produto:

  • frontend: aplicação web para usuários finais, com landing page, autenticação e dashboard de vagas. A nova estrutura de painel do frontend fica em frontend/src/domains/new_dashboard.
  • backend: API Node.js/Express com autenticação, perfis, preferências, vagas salvas, notificações, rotas admin e observabilidade.
  • scraper-go: serviço Go de scraping multi-fonte, cache, deduplicação e indexação em Valkey.
  • front_admin: painel administrativo para operação, usuários, permissões, scrapers, auditoria e observabilidade.
  • electron: shell desktop que empacota a experiência principal.

Objetivo de produto: fornecer uma base robusta para busca, filtragem e gestão de vagas com foco em qualidade de dados, escalabilidade e operação contínua.

Arquitetura do monorepo

.
├─ frontend/ # Dashboard web (React + Vite)
├─ backend/ # API Node.js (Express + TS + Drizzle)
├─ scraper-go/ # Serviço Go de scraping multi-fonte
├─ front_admin/ # Painel administrativo (React + Vite)
├─ electron/ # Shell desktop
├─ docker-compose.yml # App stack (frontend + front_admin + backend + scraper-go)
├─ docker-compose.infra.yml # Infra stack (Postgres + Valkey)
├─ docker-compose.migrate.yml # Migration job do backend
└─ .github/workflows/ci.yml # CI

Stack real do projeto

  • Frontend: React 19, TypeScript, Vite 8, Tailwind CSS, Vitest.
  • Front admin: React 19, TypeScript, Vite 8, Tailwind CSS 4, Vitest.
  • Backend: Node.js 22+, Express 5, TypeScript, Drizzle ORM, Zod, Iron Session, Redis/Valkey.
  • Scraping: Go (serviço dedicado em scraper-go).
  • Desktop: Electron + Electron Builder.
  • Qualidade: Vitest (frontend/backend/front_admin), cobertura v8, ESLint (frontend/front_admin), GitHub Actions CI.
  • Dados: Postgres (persistência) + Valkey/Redis (cache e índice).

Quickstart local

Pré-requisitos

  • Node.js >= 22
  • npm
  • Docker Desktop com Docker Compose

Caminho recomendado: stack completa com Docker

Use este fluxo para subir Postgres, Valkey, scraper Go, backend, frontend e front_admin com a mesma rede Docker.

1 - Instale as dependências locais:

npm install

2 - Crie o .env da raiz a partir do exemplo versionado:

cp .env.example .env

No Windows PowerShell:

Copy-Item .env.example .env

3 - Crie a rede Docker compartilhada, se ela ainda não existir:

docker network create vagas-net

Se a rede já existir, o Docker vai avisar e você pode seguir para o próximo passo.

4 - Suba Postgres, Valkey, scraper, backend, frontend e front_admin:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

5 - Acesse os serviços:

Desenvolvimento com Node local

Use este fluxo quando quiser rodar frontend/backend fora do Docker. Mantenha Postgres e Valkey ativos no Docker e configure URLs locais nos arquivos .env.

Arquivos esperados:

  • .env: usado pela infra/scraper e por comandos auxiliares.
  • backend/.env: usado pelo backend local.
  • frontend/.env: usado pelo Vite local.
  • front_admin usa VITE_API_URL, mas ainda não possui .env.example próprio.

Criação dos arquivos locais:

cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env

No Windows PowerShell:

Copy-Item backend/.env.example backend/.env
Copy-Item frontend/.env.example frontend/.env

Comandos:

npm run dev

Esse comando sobe apenas o necessário para a maioria das contribuições: frontend e backend.

Para trabalhar também no painel administrativo:

npm run dev:admin

Execução separada:

npm run dev:frontend
npm run dev:backend
npm run dev:front_admin

Execução de testes

npm run test:coverage

Instalação limpa e CI

Para onboarding e desenvolvimento local, prefira npm install.

Use npm ci em automações como GitHub Actions, Docker/deploy ou quando quiser reinstalar tudo exatamente a partir do package-lock.json. Ele remove node_modules, não altera o lockfile e falha se package.json e package-lock.json estiverem fora de sincronia.

Comandos verificados

Os comandos abaixo existem hoje no repositório e foram conferidos nos package.json da raiz, backend, frontend e front_admin.

Raiz

  • npm run dev
  • npm run dev:admin
  • npm run dev:frontend
  • npm run dev:backend
  • npm run dev:front_admin
  • npm run scraper
  • npm run scraper:watch
  • npm run test
  • npm run test:coverage
  • npm run build
  • npm run build:frontend
  • npm run build:front_admin
  • npm run validate
  • npm run electron
  • npm run electron:dev
  • npm run dist
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Backend

  • npm run start
  • npm run dev
  • npm run api
  • npm run test
  • npm run test:coverage
  • npm run test:watch
  • npm run validate
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Frontend

  • npm run dev
  • npm run build
  • npm run lint
  • npm run preview
  • npm run test
  • npm run test:coverage
  • npm run test:watch

Front admin

  • npm run dev
  • npm run build
  • npm run lint
  • npm run test
  • npm run test:coverage
  • npm run preview

API backend (estado atual)

Base: /

Sistema:

  • GET /health

Autenticação:

  • GET /auth/:provider/url
  • GET /auth/:provider/callback
  • POST /auth/register
  • POST /auth/login
  • POST /auth/logout
  • GET /auth/me

Usuários:

  • GET /users/profile
  • PATCH /users/profile
  • GET /users/preferences
  • POST /users/preferences
  • PATCH /users/preferences

Jobs:

  • GET /jobs/search
    • Busca vagas nos índices do Valkey e aceita filtros por keywords, family, technology, seniority, level, location, country, type/model, contract e ordenação por matchSort.

Keywords:

  • GET /keywords
  • POST /keywords

Saved jobs:

  • GET /saved-jobs
  • GET /saved-jobs/:id
  • POST /saved-jobs
  • PATCH /saved-jobs/:id
  • DELETE /saved-jobs/:id

Admin:

  • GET /admin/users
  • GET /admin/users/:id
  • PATCH /admin/users/:id/block
  • PATCH /admin/users/:id/unblock
  • POST /admin/users/:id/reset
  • POST /admin/scrapers/run
  • GET /admin/observability/metrics
  • GET /admin/observability/dashboards
  • GET /admin/audit
  • GET /admin/permissions/rules

Swagger:

  • GET /docs

Docker (infra + aplicação)

Este projeto separa infraestrutura e aplicação em dois arquivos Compose:

  • docker-compose.infra.yml: Postgres + Valkey.
  • docker-compose.yml: scraper Go + backend + frontend + front_admin.
  • docker-compose.migrate.yml: job de migrations do backend.

Subir infraestrutura, migrations e aplicação:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

O serviço migrate executa npm run db:migrate e npm run security:backfill-user-pii -- --write depois que o Postgres fica saudável. O backend só inicia depois que esse job termina com sucesso.

Se quiser subir apenas a infraestrutura:

docker compose -f docker-compose.infra.yml up -d

Se quiser subir a aplicação sem o job de migrations:

docker compose up --build -d

Ver logs:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f migrate
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f backend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f frontend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f front_admin
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f scraper-go

Encerrar:

docker compose down
docker compose -f docker-compose.infra.yml down

Observação: os volumes Docker preservam os dados do Postgres e do Valkey entre execuções. Se você alterar POSTGRES_USER, POSTGRES_PASSWORD ou POSTGRES_DB depois da primeira inicialização, será necessário recriar o volume do Postgres ou manter os valores antigos.

Dentro dos containers, serviços devem usar os nomes da rede Docker:

  • Postgres: postgres:5432
  • Valkey: valkey:6379
  • Scraper: scraper-go:8081

Por isso o docker-compose.yml e o docker-compose.migrate.yml sobrescrevem variáveis como DATABASE_URL, VALKEY_URL, GO_SCRAPER_URL e SCRAPER_URL para os valores internos corretos.

Serviços padrão:

Endpoints úteis do scraper:

Desktop com Electron

O app desktop empacota frontend + backend e inicia a aplicação com Electron.

Comandos:

npm run build:frontend
npm run electron

Distribuição (Windows):

npm run dist

Saída esperada do instalador:

  • dist-electron/Vagas Full Setup X.X.X.exe

Variáveis de ambiente

Arquivos de exemplo:

  • .env.example
  • backend/.env.example
  • frontend/.env.example

Arquivos locais ignorados pelo Git:

  • .env
  • backend/.env
  • frontend/.env
  • front_admin/.env, se criado localmente

Uso recomendado:

  • Docker Compose: copie .env.example para .env. O Compose usa esse arquivo para infra, scraper, backend e build do frontend.
  • Backend local via Node: use backend/.env.
  • Frontend local via Vite: use frontend/.env.
  • Front admin local via Vite: crie front_admin/.env com VITE_API_URL=http://localhost:3001 quando precisar sobrescrever o padrão.

Variáveis centrais de operação:

  • DATABASE_URL
  • VALKEY_URL
  • GO_SCRAPER_URL
  • SESSION_SECRET
  • CORS_ALLOWED_ORIGINS
  • SEARCH_LOCATION
  • SEARCH_GEO_ID
  • SEARCH_LANGUAGE
  • REMOTE_ONLY
  • JOB_TYPES
  • TIME_FILTER
  • WAIT_BETWEEN_SEARCHES_MS
  • PAGE_TIMEOUT_MS
  • MAX_PAGES_PER_KEYWORD
  • LINKEDIN_KEYWORD_SLOT_SIZE
  • ADZUNA_KEYWORD_SLOT_SIZE
  • GUPY_ENABLED
  • GUPY_RAW_DISCOVERY_ENABLED
  • GUPY_FULL_SWEEP_ENABLED
  • GUPY_FULL_REMOTE_SWEEP_ENABLED
  • GUPY_QUERY_LIMIT
  • INHIRE_ENABLED
  • INHIRE_ENRICH_DETAILS
  • GREENHOUSE_ENABLED
  • LEVER_ENABLED
  • CACHE_TTL_MS
  • VITE_API_BASE_URL
  • VITE_API_URL
  • VITE_API_PROXY_TARGET
  • VITE_APP_ENV

Segurança operacional:

  • Nunca versionar segredos reais no Git.
  • Preferir acesso interno para banco/cache em VPS.
  • Em ambiente externo, usar TLS para conexões de dados sempre que possível.

Observação operacional do scraper:

  • O padrão atual privilegia resposta rápida e estabilidade. LinkedIn e Adzuna usam slots rotativos de keywords por execução, e Gupy limita a quantidade de queries expandidas por rodada. Isso reduz cobertura imediata por execução, mas evita milhares de requests em uma única rodada e distribui a coleta ao longo das próximas execuções.
  • tools/ e data/ são ignorados pelo Git. Scripts versionados não devem depender de arquivos nessas pastas, a menos que sejam tratados como utilitários locais opcionais.

Testes e qualidade

Estrutura:

  • backend/tests/unit
  • backend/tests/integration
  • frontend/tests/unit
  • frontend/tests/integration
  • front_admin/tests

Threshold mínimo:

  • lines >= 80%
  • statements >= 80%
  • functions >= 80%
  • branches >= 80%

Comandos:

npm run test:coverage
npm --workspace frontend run test:coverage
npm --workspace backend run test:coverage
npm --workspace front_admin run test:coverage

Observação importante: o backend já está configurado para coletar cobertura apenas em src/**/*.ts, evitando contagem de artefatos gerados.

CI/CD

Workflow atual: .github/workflows/ci.yml

Executa em push para master/develop e em pull_request:

  • Instalação de dependências
  • Coverage frontend
  • Coverage backend
  • Lint frontend
  • Build frontend

Observação: o painel admin já possui testes e build próprios, mas ainda deve ser incluído no fluxo de validação/CI quando se tornar parte obrigatória do release.

Fluxo de desenvolvimento e branching

Padrão oficial:

  1. Abrir card no Linear: https://linear.app/tatame/team/PAV/all
  2. Criar branch de feature a partir de master
  3. Desenvolver e testar localmente
  4. Abrir PR da feature para develop
  5. Após aprovação e validação, merge em develop
  6. Abrir PR de develop para master
  7. Merge em master para release

Convenção recomendada de branch:

  • feature/{id-do-card}-{descricao-curta}

Git Hooks e qualidade local

O repositório usa Husky na raiz do monorepo para padronizar validações locais em qualquer branch.

Hooks configurados:

  • pre-commit: executa lint-staged para validar arquivos staged do frontend.
  • commit-msg: valida mensagem de commit com commitlint (Conventional Commits).
  • pre-push: executa validação do monorepo (test backend + lint/build frontend).

Bootstrap local com instalação e hooks:

npm run setup:dev

Checklist quando hooks não disparam:

  1. Validar se o diretório Git foi detectado: git rev-parse --git-dir.
  2. Validar hooksPath local: git config --get core.hooksPath.
  3. Confirmar arquivos versionados em .husky (pre-commit, commit-msg, pre-push).
  4. Reinstalar hooks: npm run prepare.
  5. Em Windows, preferir Git Bash para depuração de scripts shell.

Observação importante:

  • CI continua obrigatório e independente de hooks locais. Mesmo com bypass local, o pipeline valida cobertura/lint/build antes de merge.

Roadmap técnico sugerido

DX e onboarding

  • Adicionar script único de bootstrap (exemplo: npm run setup:dev) para criar .env e validar pré-requisitos.
  • Adicionar verificação automática de scripts quebrados no CI.
  • Padronizar comandos cross-platform (evitar dependência de sintaxe de variável de ambiente Unix em scripts críticos).

Segurança

  • Aplicar política de rotação de SESSION_SECRET e credenciais OAuth.
  • Adicionar checklist de segurança para PRs (cookies, CORS, secrets, headers).

Performance

  • Definir estratégia de paginação e filtros em camada de API com métricas por endpoint.
  • Revisar TTL e cardinalidade dos índices no Valkey para reduzir consumo de memória.

Observabilidade

  • Padronizar correlação de logs por request id.
  • Publicar guia mínimo de troubleshooting com sinais de saúde dos serviços frontend/backend/scraper-go.

Contribuição

  1. Abra um card no Linear.
  2. Crie branch a partir de master.
  3. Implemente com testes.
  4. Execute validações locais:
npm run validate
npm run test:coverage
  1. Abra PR para develop com contexto técnico objetivo.

Se você vai trabalhar em backend, scraper ou testes, use também:

About

Simplifique sua busca por emprego. Todas as oportunidades do mercado reunidas em uma plataforma inteligente e automatizada.

Topics

Resources

Stars

86 stars

Watchers

3 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

527 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

<Cand!Date!>

Novo no projeto? Comece por aqui: LOCAL_DEVELOPMENT.md

CINode >= 22MonorepoLicense ISC

Documentação: README | SCRAPER | BACKEND | TESTING | CONTRIBUTING | ESCOPO | Frontend | Frontend Architecture | Front Admin

Plataforma de captura, agregação e consulta de vagas com arquitetura monorepo, composta por frontend web, API Node.js, scraper Go, painel administrativo e aplicação desktop com Electron.

O produto evoluiu para um modelo orientado a serviços (API + scraper Go + cache/índices), com autenticação, preferências de usuário e integração com banco de dados.

Links oficiais

Sumário

Visão geral

Este repositório centraliza as frentes principais do produto:

  • frontend: aplicação web para usuários finais, com landing page, autenticação e dashboard de vagas. A nova estrutura de painel do frontend fica em frontend/src/domains/new_dashboard.
  • backend: API Node.js/Express com autenticação, perfis, preferências, vagas salvas, notificações, rotas admin e observabilidade.
  • scraper-go: serviço Go de scraping multi-fonte, cache, deduplicação e indexação em Valkey.
  • front_admin: painel administrativo para operação, usuários, permissões, scrapers, auditoria e observabilidade.
  • electron: shell desktop que empacota a experiência principal.

Objetivo de produto: fornecer uma base robusta para busca, filtragem e gestão de vagas com foco em qualidade de dados, escalabilidade e operação contínua.

Arquitetura do monorepo

.
├─ frontend/ # Dashboard web (React + Vite)
├─ backend/ # API Node.js (Express + TS + Drizzle)
├─ scraper-go/ # Serviço Go de scraping multi-fonte
├─ front_admin/ # Painel administrativo (React + Vite)
├─ electron/ # Shell desktop
├─ docker-compose.yml # App stack (frontend + front_admin + backend + scraper-go)
├─ docker-compose.infra.yml # Infra stack (Postgres + Valkey)
├─ docker-compose.migrate.yml # Migration job do backend
└─ .github/workflows/ci.yml # CI

Stack real do projeto

  • Frontend: React 19, TypeScript, Vite 8, Tailwind CSS, Vitest.
  • Front admin: React 19, TypeScript, Vite 8, Tailwind CSS 4, Vitest.
  • Backend: Node.js 22+, Express 5, TypeScript, Drizzle ORM, Zod, Iron Session, Redis/Valkey.
  • Scraping: Go (serviço dedicado em scraper-go).
  • Desktop: Electron + Electron Builder.
  • Qualidade: Vitest (frontend/backend/front_admin), cobertura v8, ESLint (frontend/front_admin), GitHub Actions CI.
  • Dados: Postgres (persistência) + Valkey/Redis (cache e índice).

Quickstart local

Pré-requisitos

  • Node.js >= 22
  • npm
  • Docker Desktop com Docker Compose

Caminho recomendado: stack completa com Docker

Use este fluxo para subir Postgres, Valkey, scraper Go, backend, frontend e front_admin com a mesma rede Docker.

1 - Instale as dependências locais:

npm install

2 - Crie o .env da raiz a partir do exemplo versionado:

cp .env.example .env

No Windows PowerShell:

Copy-Item .env.example .env

3 - Crie a rede Docker compartilhada, se ela ainda não existir:

docker network create vagas-net

Se a rede já existir, o Docker vai avisar e você pode seguir para o próximo passo.

4 - Suba Postgres, Valkey, scraper, backend, frontend e front_admin:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

5 - Acesse os serviços:

Desenvolvimento com Node local

Use este fluxo quando quiser rodar frontend/backend fora do Docker. Mantenha Postgres e Valkey ativos no Docker e configure URLs locais nos arquivos .env.

Arquivos esperados:

  • .env: usado pela infra/scraper e por comandos auxiliares.
  • backend/.env: usado pelo backend local.
  • frontend/.env: usado pelo Vite local.
  • front_admin usa VITE_API_URL, mas ainda não possui .env.example próprio.

Criação dos arquivos locais:

cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env

No Windows PowerShell:

Copy-Item backend/.env.example backend/.env
Copy-Item frontend/.env.example frontend/.env

Comandos:

npm run dev

Esse comando sobe apenas o necessário para a maioria das contribuições: frontend e backend.

Para trabalhar também no painel administrativo:

npm run dev:admin

Execução separada:

npm run dev:frontend
npm run dev:backend
npm run dev:front_admin

Execução de testes

npm run test:coverage

Instalação limpa e CI

Para onboarding e desenvolvimento local, prefira npm install.

Use npm ci em automações como GitHub Actions, Docker/deploy ou quando quiser reinstalar tudo exatamente a partir do package-lock.json. Ele remove node_modules, não altera o lockfile e falha se package.json e package-lock.json estiverem fora de sincronia.

Comandos verificados

Os comandos abaixo existem hoje no repositório e foram conferidos nos package.json da raiz, backend, frontend e front_admin.

Raiz

  • npm run dev
  • npm run dev:admin
  • npm run dev:frontend
  • npm run dev:backend
  • npm run dev:front_admin
  • npm run scraper
  • npm run scraper:watch
  • npm run test
  • npm run test:coverage
  • npm run build
  • npm run build:frontend
  • npm run build:front_admin
  • npm run validate
  • npm run electron
  • npm run electron:dev
  • npm run dist
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Backend

  • npm run start
  • npm run dev
  • npm run api
  • npm run test
  • npm run test:coverage
  • npm run test:watch
  • npm run validate
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Frontend

  • npm run dev
  • npm run build
  • npm run lint
  • npm run preview
  • npm run test
  • npm run test:coverage
  • npm run test:watch

Front admin

  • npm run dev
  • npm run build
  • npm run lint
  • npm run test
  • npm run test:coverage
  • npm run preview

API backend (estado atual)

Base: /

Sistema:

  • GET /health

Autenticação:

  • GET /auth/:provider/url
  • GET /auth/:provider/callback
  • POST /auth/register
  • POST /auth/login
  • POST /auth/logout
  • GET /auth/me

Usuários:

  • GET /users/profile
  • PATCH /users/profile
  • GET /users/preferences
  • POST /users/preferences
  • PATCH /users/preferences

Jobs:

  • GET /jobs/search
    • Busca vagas nos índices do Valkey e aceita filtros por keywords, family, technology, seniority, level, location, country, type/model, contract e ordenação por matchSort.

Keywords:

  • GET /keywords
  • POST /keywords

Saved jobs:

  • GET /saved-jobs
  • GET /saved-jobs/:id
  • POST /saved-jobs
  • PATCH /saved-jobs/:id
  • DELETE /saved-jobs/:id

Admin:

  • GET /admin/users
  • GET /admin/users/:id
  • PATCH /admin/users/:id/block
  • PATCH /admin/users/:id/unblock
  • POST /admin/users/:id/reset
  • POST /admin/scrapers/run
  • GET /admin/observability/metrics
  • GET /admin/observability/dashboards
  • GET /admin/audit
  • GET /admin/permissions/rules

Swagger:

  • GET /docs

Docker (infra + aplicação)

Este projeto separa infraestrutura e aplicação em dois arquivos Compose:

  • docker-compose.infra.yml: Postgres + Valkey.
  • docker-compose.yml: scraper Go + backend + frontend + front_admin.
  • docker-compose.migrate.yml: job de migrations do backend.

Subir infraestrutura, migrations e aplicação:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

O serviço migrate executa npm run db:migrate e npm run security:backfill-user-pii -- --write depois que o Postgres fica saudável. O backend só inicia depois que esse job termina com sucesso.

Se quiser subir apenas a infraestrutura:

docker compose -f docker-compose.infra.yml up -d

Se quiser subir a aplicação sem o job de migrations:

docker compose up --build -d

Ver logs:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f migrate
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f backend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f frontend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f front_admin
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f scraper-go

Encerrar:

docker compose down
docker compose -f docker-compose.infra.yml down

Observação: os volumes Docker preservam os dados do Postgres e do Valkey entre execuções. Se você alterar POSTGRES_USER, POSTGRES_PASSWORD ou POSTGRES_DB depois da primeira inicialização, será necessário recriar o volume do Postgres ou manter os valores antigos.

Dentro dos containers, serviços devem usar os nomes da rede Docker:

  • Postgres: postgres:5432
  • Valkey: valkey:6379
  • Scraper: scraper-go:8081

Por isso o docker-compose.yml e o docker-compose.migrate.yml sobrescrevem variáveis como DATABASE_URL, VALKEY_URL, GO_SCRAPER_URL e SCRAPER_URL para os valores internos corretos.

Serviços padrão:

Endpoints úteis do scraper:

Desktop com Electron

O app desktop empacota frontend + backend e inicia a aplicação com Electron.

Comandos:

npm run build:frontend
npm run electron

Distribuição (Windows):

npm run dist

Saída esperada do instalador:

  • dist-electron/Vagas Full Setup X.X.X.exe

Variáveis de ambiente

Arquivos de exemplo:

  • .env.example
  • backend/.env.example
  • frontend/.env.example

Arquivos locais ignorados pelo Git:

  • .env
  • backend/.env
  • frontend/.env
  • front_admin/.env, se criado localmente

Uso recomendado:

  • Docker Compose: copie .env.example para .env. O Compose usa esse arquivo para infra, scraper, backend e build do frontend.
  • Backend local via Node: use backend/.env.
  • Frontend local via Vite: use frontend/.env.
  • Front admin local via Vite: crie front_admin/.env com VITE_API_URL=http://localhost:3001 quando precisar sobrescrever o padrão.

Variáveis centrais de operação:

  • DATABASE_URL
  • VALKEY_URL
  • GO_SCRAPER_URL
  • SESSION_SECRET
  • CORS_ALLOWED_ORIGINS
  • SEARCH_LOCATION
  • SEARCH_GEO_ID
  • SEARCH_LANGUAGE
  • REMOTE_ONLY
  • JOB_TYPES
  • TIME_FILTER
  • WAIT_BETWEEN_SEARCHES_MS
  • PAGE_TIMEOUT_MS
  • MAX_PAGES_PER_KEYWORD
  • LINKEDIN_KEYWORD_SLOT_SIZE
  • ADZUNA_KEYWORD_SLOT_SIZE
  • GUPY_ENABLED
  • GUPY_RAW_DISCOVERY_ENABLED
  • GUPY_FULL_SWEEP_ENABLED
  • GUPY_FULL_REMOTE_SWEEP_ENABLED
  • GUPY_QUERY_LIMIT
  • INHIRE_ENABLED
  • INHIRE_ENRICH_DETAILS
  • GREENHOUSE_ENABLED
  • LEVER_ENABLED
  • CACHE_TTL_MS
  • VITE_API_BASE_URL
  • VITE_API_URL
  • VITE_API_PROXY_TARGET
  • VITE_APP_ENV

Segurança operacional:

  • Nunca versionar segredos reais no Git.
  • Preferir acesso interno para banco/cache em VPS.
  • Em ambiente externo, usar TLS para conexões de dados sempre que possível.

Observação operacional do scraper:

  • O padrão atual privilegia resposta rápida e estabilidade. LinkedIn e Adzuna usam slots rotativos de keywords por execução, e Gupy limita a quantidade de queries expandidas por rodada. Isso reduz cobertura imediata por execução, mas evita milhares de requests em uma única rodada e distribui a coleta ao longo das próximas execuções.
  • tools/ e data/ são ignorados pelo Git. Scripts versionados não devem depender de arquivos nessas pastas, a menos que sejam tratados como utilitários locais opcionais.

Testes e qualidade

Estrutura:

  • backend/tests/unit
  • backend/tests/integration
  • frontend/tests/unit
  • frontend/tests/integration
  • front_admin/tests

Threshold mínimo:

  • lines >= 80%
  • statements >= 80%
  • functions >= 80%
  • branches >= 80%

Comandos:

npm run test:coverage
npm --workspace frontend run test:coverage
npm --workspace backend run test:coverage
npm --workspace front_admin run test:coverage

Observação importante: o backend já está configurado para coletar cobertura apenas em src/**/*.ts, evitando contagem de artefatos gerados.

CI/CD

Workflow atual: .github/workflows/ci.yml

Executa em push para master/develop e em pull_request:

  • Instalação de dependências
  • Coverage frontend
  • Coverage backend
  • Lint frontend
  • Build frontend

Observação: o painel admin já possui testes e build próprios, mas ainda deve ser incluído no fluxo de validação/CI quando se tornar parte obrigatória do release.

Fluxo de desenvolvimento e branching

Padrão oficial:

  1. Abrir card no Linear: https://linear.app/tatame/team/PAV/all
  2. Criar branch de feature a partir de master
  3. Desenvolver e testar localmente
  4. Abrir PR da feature para develop
  5. Após aprovação e validação, merge em develop
  6. Abrir PR de develop para master
  7. Merge em master para release

Convenção recomendada de branch:

  • feature/{id-do-card}-{descricao-curta}

Git Hooks e qualidade local

O repositório usa Husky na raiz do monorepo para padronizar validações locais em qualquer branch.

Hooks configurados:

  • pre-commit: executa lint-staged para validar arquivos staged do frontend.
  • commit-msg: valida mensagem de commit com commitlint (Conventional Commits).
  • pre-push: executa validação do monorepo (test backend + lint/build frontend).

Bootstrap local com instalação e hooks:

npm run setup:dev

Checklist quando hooks não disparam:

  1. Validar se o diretório Git foi detectado: git rev-parse --git-dir.
  2. Validar hooksPath local: git config --get core.hooksPath.
  3. Confirmar arquivos versionados em .husky (pre-commit, commit-msg, pre-push).
  4. Reinstalar hooks: npm run prepare.
  5. Em Windows, preferir Git Bash para depuração de scripts shell.

Observação importante:

  • CI continua obrigatório e independente de hooks locais. Mesmo com bypass local, o pipeline valida cobertura/lint/build antes de merge.

Roadmap técnico sugerido

DX e onboarding

  • Adicionar script único de bootstrap (exemplo: npm run setup:dev) para criar .env e validar pré-requisitos.
  • Adicionar verificação automática de scripts quebrados no CI.
  • Padronizar comandos cross-platform (evitar dependência de sintaxe de variável de ambiente Unix em scripts críticos).

Segurança

  • Aplicar política de rotação de SESSION_SECRET e credenciais OAuth.
  • Adicionar checklist de segurança para PRs (cookies, CORS, secrets, headers).

Performance

  • Definir estratégia de paginação e filtros em camada de API com métricas por endpoint.
  • Revisar TTL e cardinalidade dos índices no Valkey para reduzir consumo de memória.

Observabilidade

  • Padronizar correlação de logs por request id.
  • Publicar guia mínimo de troubleshooting com sinais de saúde dos serviços frontend/backend/scraper-go.

Contribuição

  1. Abra um card no Linear.
  2. Crie branch a partir de master.
  3. Implemente com testes.
  4. Execute validações locais:
npm run validate
npm run test:coverage
  1. Abra PR para develop com contexto técnico objetivo.

Se você vai trabalhar em backend, scraper ou testes, use também:

About

Simplifique sua busca por emprego. Todas as oportunidades do mercado reunidas em uma plataforma inteligente e automatizada.

Topics

Resources

Stars

86 stars

Watchers

3 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

527 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

<Cand!Date!>

Novo no projeto? Comece por aqui: LOCAL_DEVELOPMENT.md

CINode >= 22MonorepoLicense ISC

Documentação: README | SCRAPER | BACKEND | TESTING | CONTRIBUTING | ESCOPO | Frontend | Frontend Architecture | Front Admin

Plataforma de captura, agregação e consulta de vagas com arquitetura monorepo, composta por frontend web, API Node.js, scraper Go, painel administrativo e aplicação desktop com Electron.

O produto evoluiu para um modelo orientado a serviços (API + scraper Go + cache/índices), com autenticação, preferências de usuário e integração com banco de dados.

Links oficiais

Sumário

Visão geral

Este repositório centraliza as frentes principais do produto:

  • frontend: aplicação web para usuários finais, com landing page, autenticação e dashboard de vagas. A nova estrutura de painel do frontend fica em frontend/src/domains/new_dashboard.
  • backend: API Node.js/Express com autenticação, perfis, preferências, vagas salvas, notificações, rotas admin e observabilidade.
  • scraper-go: serviço Go de scraping multi-fonte, cache, deduplicação e indexação em Valkey.
  • front_admin: painel administrativo para operação, usuários, permissões, scrapers, auditoria e observabilidade.
  • electron: shell desktop que empacota a experiência principal.

Objetivo de produto: fornecer uma base robusta para busca, filtragem e gestão de vagas com foco em qualidade de dados, escalabilidade e operação contínua.

Arquitetura do monorepo

.
├─ frontend/ # Dashboard web (React + Vite)
├─ backend/ # API Node.js (Express + TS + Drizzle)
├─ scraper-go/ # Serviço Go de scraping multi-fonte
├─ front_admin/ # Painel administrativo (React + Vite)
├─ electron/ # Shell desktop
├─ docker-compose.yml # App stack (frontend + front_admin + backend + scraper-go)
├─ docker-compose.infra.yml # Infra stack (Postgres + Valkey)
├─ docker-compose.migrate.yml # Migration job do backend
└─ .github/workflows/ci.yml # CI

Stack real do projeto

  • Frontend: React 19, TypeScript, Vite 8, Tailwind CSS, Vitest.
  • Front admin: React 19, TypeScript, Vite 8, Tailwind CSS 4, Vitest.
  • Backend: Node.js 22+, Express 5, TypeScript, Drizzle ORM, Zod, Iron Session, Redis/Valkey.
  • Scraping: Go (serviço dedicado em scraper-go).
  • Desktop: Electron + Electron Builder.
  • Qualidade: Vitest (frontend/backend/front_admin), cobertura v8, ESLint (frontend/front_admin), GitHub Actions CI.
  • Dados: Postgres (persistência) + Valkey/Redis (cache e índice).

Quickstart local

Pré-requisitos

  • Node.js >= 22
  • npm
  • Docker Desktop com Docker Compose

Caminho recomendado: stack completa com Docker

Use este fluxo para subir Postgres, Valkey, scraper Go, backend, frontend e front_admin com a mesma rede Docker.

1 - Instale as dependências locais:

npm install

2 - Crie o .env da raiz a partir do exemplo versionado:

cp .env.example .env

No Windows PowerShell:

Copy-Item .env.example .env

3 - Crie a rede Docker compartilhada, se ela ainda não existir:

docker network create vagas-net

Se a rede já existir, o Docker vai avisar e você pode seguir para o próximo passo.

4 - Suba Postgres, Valkey, scraper, backend, frontend e front_admin:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

5 - Acesse os serviços:

Desenvolvimento com Node local

Use este fluxo quando quiser rodar frontend/backend fora do Docker. Mantenha Postgres e Valkey ativos no Docker e configure URLs locais nos arquivos .env.

Arquivos esperados:

  • .env: usado pela infra/scraper e por comandos auxiliares.
  • backend/.env: usado pelo backend local.
  • frontend/.env: usado pelo Vite local.
  • front_admin usa VITE_API_URL, mas ainda não possui .env.example próprio.

Criação dos arquivos locais:

cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env

No Windows PowerShell:

Copy-Item backend/.env.example backend/.env
Copy-Item frontend/.env.example frontend/.env

Comandos:

npm run dev

Esse comando sobe apenas o necessário para a maioria das contribuições: frontend e backend.

Para trabalhar também no painel administrativo:

npm run dev:admin

Execução separada:

npm run dev:frontend
npm run dev:backend
npm run dev:front_admin

Execução de testes

npm run test:coverage

Instalação limpa e CI

Para onboarding e desenvolvimento local, prefira npm install.

Use npm ci em automações como GitHub Actions, Docker/deploy ou quando quiser reinstalar tudo exatamente a partir do package-lock.json. Ele remove node_modules, não altera o lockfile e falha se package.json e package-lock.json estiverem fora de sincronia.

Comandos verificados

Os comandos abaixo existem hoje no repositório e foram conferidos nos package.json da raiz, backend, frontend e front_admin.

Raiz

  • npm run dev
  • npm run dev:admin
  • npm run dev:frontend
  • npm run dev:backend
  • npm run dev:front_admin
  • npm run scraper
  • npm run scraper:watch
  • npm run test
  • npm run test:coverage
  • npm run build
  • npm run build:frontend
  • npm run build:front_admin
  • npm run validate
  • npm run electron
  • npm run electron:dev
  • npm run dist
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Backend

  • npm run start
  • npm run dev
  • npm run api
  • npm run test
  • npm run test:coverage
  • npm run test:watch
  • npm run validate
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Frontend

  • npm run dev
  • npm run build
  • npm run lint
  • npm run preview
  • npm run test
  • npm run test:coverage
  • npm run test:watch

Front admin

  • npm run dev
  • npm run build
  • npm run lint
  • npm run test
  • npm run test:coverage
  • npm run preview

API backend (estado atual)

Base: /

Sistema:

  • GET /health

Autenticação:

  • GET /auth/:provider/url
  • GET /auth/:provider/callback
  • POST /auth/register
  • POST /auth/login
  • POST /auth/logout
  • GET /auth/me

Usuários:

  • GET /users/profile
  • PATCH /users/profile
  • GET /users/preferences
  • POST /users/preferences
  • PATCH /users/preferences

Jobs:

  • GET /jobs/search
    • Busca vagas nos índices do Valkey e aceita filtros por keywords, family, technology, seniority, level, location, country, type/model, contract e ordenação por matchSort.

Keywords:

  • GET /keywords
  • POST /keywords

Saved jobs:

  • GET /saved-jobs
  • GET /saved-jobs/:id
  • POST /saved-jobs
  • PATCH /saved-jobs/:id
  • DELETE /saved-jobs/:id

Admin:

  • GET /admin/users
  • GET /admin/users/:id
  • PATCH /admin/users/:id/block
  • PATCH /admin/users/:id/unblock
  • POST /admin/users/:id/reset
  • POST /admin/scrapers/run
  • GET /admin/observability/metrics
  • GET /admin/observability/dashboards
  • GET /admin/audit
  • GET /admin/permissions/rules

Swagger:

  • GET /docs

Docker (infra + aplicação)

Este projeto separa infraestrutura e aplicação em dois arquivos Compose:

  • docker-compose.infra.yml: Postgres + Valkey.
  • docker-compose.yml: scraper Go + backend + frontend + front_admin.
  • docker-compose.migrate.yml: job de migrations do backend.

Subir infraestrutura, migrations e aplicação:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

O serviço migrate executa npm run db:migrate e npm run security:backfill-user-pii -- --write depois que o Postgres fica saudável. O backend só inicia depois que esse job termina com sucesso.

Se quiser subir apenas a infraestrutura:

docker compose -f docker-compose.infra.yml up -d

Se quiser subir a aplicação sem o job de migrations:

docker compose up --build -d

Ver logs:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f migrate
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f backend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f frontend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f front_admin
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f scraper-go

Encerrar:

docker compose down
docker compose -f docker-compose.infra.yml down

Observação: os volumes Docker preservam os dados do Postgres e do Valkey entre execuções. Se você alterar POSTGRES_USER, POSTGRES_PASSWORD ou POSTGRES_DB depois da primeira inicialização, será necessário recriar o volume do Postgres ou manter os valores antigos.

Dentro dos containers, serviços devem usar os nomes da rede Docker:

  • Postgres: postgres:5432
  • Valkey: valkey:6379
  • Scraper: scraper-go:8081

Por isso o docker-compose.yml e o docker-compose.migrate.yml sobrescrevem variáveis como DATABASE_URL, VALKEY_URL, GO_SCRAPER_URL e SCRAPER_URL para os valores internos corretos.

Serviços padrão:

Endpoints úteis do scraper:

Desktop com Electron

O app desktop empacota frontend + backend e inicia a aplicação com Electron.

Comandos:

npm run build:frontend
npm run electron

Distribuição (Windows):

npm run dist

Saída esperada do instalador:

  • dist-electron/Vagas Full Setup X.X.X.exe

Variáveis de ambiente

Arquivos de exemplo:

  • .env.example
  • backend/.env.example
  • frontend/.env.example

Arquivos locais ignorados pelo Git:

  • .env
  • backend/.env
  • frontend/.env
  • front_admin/.env, se criado localmente

Uso recomendado:

  • Docker Compose: copie .env.example para .env. O Compose usa esse arquivo para infra, scraper, backend e build do frontend.
  • Backend local via Node: use backend/.env.
  • Frontend local via Vite: use frontend/.env.
  • Front admin local via Vite: crie front_admin/.env com VITE_API_URL=http://localhost:3001 quando precisar sobrescrever o padrão.

Variáveis centrais de operação:

  • DATABASE_URL
  • VALKEY_URL
  • GO_SCRAPER_URL
  • SESSION_SECRET
  • CORS_ALLOWED_ORIGINS
  • SEARCH_LOCATION
  • SEARCH_GEO_ID
  • SEARCH_LANGUAGE
  • REMOTE_ONLY
  • JOB_TYPES
  • TIME_FILTER
  • WAIT_BETWEEN_SEARCHES_MS
  • PAGE_TIMEOUT_MS
  • MAX_PAGES_PER_KEYWORD
  • LINKEDIN_KEYWORD_SLOT_SIZE
  • ADZUNA_KEYWORD_SLOT_SIZE
  • GUPY_ENABLED
  • GUPY_RAW_DISCOVERY_ENABLED
  • GUPY_FULL_SWEEP_ENABLED
  • GUPY_FULL_REMOTE_SWEEP_ENABLED
  • GUPY_QUERY_LIMIT
  • INHIRE_ENABLED
  • INHIRE_ENRICH_DETAILS
  • GREENHOUSE_ENABLED
  • LEVER_ENABLED
  • CACHE_TTL_MS
  • VITE_API_BASE_URL
  • VITE_API_URL
  • VITE_API_PROXY_TARGET
  • VITE_APP_ENV

Segurança operacional:

  • Nunca versionar segredos reais no Git.
  • Preferir acesso interno para banco/cache em VPS.
  • Em ambiente externo, usar TLS para conexões de dados sempre que possível.

Observação operacional do scraper:

  • O padrão atual privilegia resposta rápida e estabilidade. LinkedIn e Adzuna usam slots rotativos de keywords por execução, e Gupy limita a quantidade de queries expandidas por rodada. Isso reduz cobertura imediata por execução, mas evita milhares de requests em uma única rodada e distribui a coleta ao longo das próximas execuções.
  • tools/ e data/ são ignorados pelo Git. Scripts versionados não devem depender de arquivos nessas pastas, a menos que sejam tratados como utilitários locais opcionais.

Testes e qualidade

Estrutura:

  • backend/tests/unit
  • backend/tests/integration
  • frontend/tests/unit
  • frontend/tests/integration
  • front_admin/tests

Threshold mínimo:

  • lines >= 80%
  • statements >= 80%
  • functions >= 80%
  • branches >= 80%

Comandos:

npm run test:coverage
npm --workspace frontend run test:coverage
npm --workspace backend run test:coverage
npm --workspace front_admin run test:coverage

Observação importante: o backend já está configurado para coletar cobertura apenas em src/**/*.ts, evitando contagem de artefatos gerados.

CI/CD

Workflow atual: .github/workflows/ci.yml

Executa em push para master/develop e em pull_request:

  • Instalação de dependências
  • Coverage frontend
  • Coverage backend
  • Lint frontend
  • Build frontend

Observação: o painel admin já possui testes e build próprios, mas ainda deve ser incluído no fluxo de validação/CI quando se tornar parte obrigatória do release.

Fluxo de desenvolvimento e branching

Padrão oficial:

  1. Abrir card no Linear: https://linear.app/tatame/team/PAV/all
  2. Criar branch de feature a partir de master
  3. Desenvolver e testar localmente
  4. Abrir PR da feature para develop
  5. Após aprovação e validação, merge em develop
  6. Abrir PR de develop para master
  7. Merge em master para release

Convenção recomendada de branch:

  • feature/{id-do-card}-{descricao-curta}

Git Hooks e qualidade local

O repositório usa Husky na raiz do monorepo para padronizar validações locais em qualquer branch.

Hooks configurados:

  • pre-commit: executa lint-staged para validar arquivos staged do frontend.
  • commit-msg: valida mensagem de commit com commitlint (Conventional Commits).
  • pre-push: executa validação do monorepo (test backend + lint/build frontend).

Bootstrap local com instalação e hooks:

npm run setup:dev

Checklist quando hooks não disparam:

  1. Validar se o diretório Git foi detectado: git rev-parse --git-dir.
  2. Validar hooksPath local: git config --get core.hooksPath.
  3. Confirmar arquivos versionados em .husky (pre-commit, commit-msg, pre-push).
  4. Reinstalar hooks: npm run prepare.
  5. Em Windows, preferir Git Bash para depuração de scripts shell.

Observação importante:

  • CI continua obrigatório e independente de hooks locais. Mesmo com bypass local, o pipeline valida cobertura/lint/build antes de merge.

Roadmap técnico sugerido

DX e onboarding

  • Adicionar script único de bootstrap (exemplo: npm run setup:dev) para criar .env e validar pré-requisitos.
  • Adicionar verificação automática de scripts quebrados no CI.
  • Padronizar comandos cross-platform (evitar dependência de sintaxe de variável de ambiente Unix em scripts críticos).

Segurança

  • Aplicar política de rotação de SESSION_SECRET e credenciais OAuth.
  • Adicionar checklist de segurança para PRs (cookies, CORS, secrets, headers).

Performance

  • Definir estratégia de paginação e filtros em camada de API com métricas por endpoint.
  • Revisar TTL e cardinalidade dos índices no Valkey para reduzir consumo de memória.

Observabilidade

  • Padronizar correlação de logs por request id.
  • Publicar guia mínimo de troubleshooting com sinais de saúde dos serviços frontend/backend/scraper-go.

Contribuição

  1. Abra um card no Linear.
  2. Crie branch a partir de master.
  3. Implemente com testes.
  4. Execute validações locais:
npm run validate
npm run test:coverage
  1. Abra PR para develop com contexto técnico objetivo.

Se você vai trabalhar em backend, scraper ou testes, use também:

About

Simplifique sua busca por emprego. Todas as oportunidades do mercado reunidas em uma plataforma inteligente e automatizada.

Topics

Resources

Stars

86 stars

Watchers

3 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

527 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

<Cand!Date!>

Novo no projeto? Comece por aqui: LOCAL_DEVELOPMENT.md

CINode >= 22MonorepoLicense ISC

Documentação: README | SCRAPER | BACKEND | TESTING | CONTRIBUTING | ESCOPO | Frontend | Frontend Architecture | Front Admin

Plataforma de captura, agregação e consulta de vagas com arquitetura monorepo, composta por frontend web, API Node.js, scraper Go, painel administrativo e aplicação desktop com Electron.

O produto evoluiu para um modelo orientado a serviços (API + scraper Go + cache/índices), com autenticação, preferências de usuário e integração com banco de dados.

Links oficiais

Sumário

Visão geral

Este repositório centraliza as frentes principais do produto:

  • frontend: aplicação web para usuários finais, com landing page, autenticação e dashboard de vagas. A nova estrutura de painel do frontend fica em frontend/src/domains/new_dashboard.
  • backend: API Node.js/Express com autenticação, perfis, preferências, vagas salvas, notificações, rotas admin e observabilidade.
  • scraper-go: serviço Go de scraping multi-fonte, cache, deduplicação e indexação em Valkey.
  • front_admin: painel administrativo para operação, usuários, permissões, scrapers, auditoria e observabilidade.
  • electron: shell desktop que empacota a experiência principal.

Objetivo de produto: fornecer uma base robusta para busca, filtragem e gestão de vagas com foco em qualidade de dados, escalabilidade e operação contínua.

Arquitetura do monorepo

.
├─ frontend/ # Dashboard web (React + Vite)
├─ backend/ # API Node.js (Express + TS + Drizzle)
├─ scraper-go/ # Serviço Go de scraping multi-fonte
├─ front_admin/ # Painel administrativo (React + Vite)
├─ electron/ # Shell desktop
├─ docker-compose.yml # App stack (frontend + front_admin + backend + scraper-go)
├─ docker-compose.infra.yml # Infra stack (Postgres + Valkey)
├─ docker-compose.migrate.yml # Migration job do backend
└─ .github/workflows/ci.yml # CI

Stack real do projeto

  • Frontend: React 19, TypeScript, Vite 8, Tailwind CSS, Vitest.
  • Front admin: React 19, TypeScript, Vite 8, Tailwind CSS 4, Vitest.
  • Backend: Node.js 22+, Express 5, TypeScript, Drizzle ORM, Zod, Iron Session, Redis/Valkey.
  • Scraping: Go (serviço dedicado em scraper-go).
  • Desktop: Electron + Electron Builder.
  • Qualidade: Vitest (frontend/backend/front_admin), cobertura v8, ESLint (frontend/front_admin), GitHub Actions CI.
  • Dados: Postgres (persistência) + Valkey/Redis (cache e índice).

Quickstart local

Pré-requisitos

  • Node.js >= 22
  • npm
  • Docker Desktop com Docker Compose

Caminho recomendado: stack completa com Docker

Use este fluxo para subir Postgres, Valkey, scraper Go, backend, frontend e front_admin com a mesma rede Docker.

1 - Instale as dependências locais:

npm install

2 - Crie o .env da raiz a partir do exemplo versionado:

cp .env.example .env

No Windows PowerShell:

Copy-Item .env.example .env

3 - Crie a rede Docker compartilhada, se ela ainda não existir:

docker network create vagas-net

Se a rede já existir, o Docker vai avisar e você pode seguir para o próximo passo.

4 - Suba Postgres, Valkey, scraper, backend, frontend e front_admin:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

5 - Acesse os serviços:

Desenvolvimento com Node local

Use este fluxo quando quiser rodar frontend/backend fora do Docker. Mantenha Postgres e Valkey ativos no Docker e configure URLs locais nos arquivos .env.

Arquivos esperados:

  • .env: usado pela infra/scraper e por comandos auxiliares.
  • backend/.env: usado pelo backend local.
  • frontend/.env: usado pelo Vite local.
  • front_admin usa VITE_API_URL, mas ainda não possui .env.example próprio.

Criação dos arquivos locais:

cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env

No Windows PowerShell:

Copy-Item backend/.env.example backend/.env
Copy-Item frontend/.env.example frontend/.env

Comandos:

npm run dev

Esse comando sobe apenas o necessário para a maioria das contribuições: frontend e backend.

Para trabalhar também no painel administrativo:

npm run dev:admin

Execução separada:

npm run dev:frontend
npm run dev:backend
npm run dev:front_admin

Execução de testes

npm run test:coverage

Instalação limpa e CI

Para onboarding e desenvolvimento local, prefira npm install.

Use npm ci em automações como GitHub Actions, Docker/deploy ou quando quiser reinstalar tudo exatamente a partir do package-lock.json. Ele remove node_modules, não altera o lockfile e falha se package.json e package-lock.json estiverem fora de sincronia.

Comandos verificados

Os comandos abaixo existem hoje no repositório e foram conferidos nos package.json da raiz, backend, frontend e front_admin.

Raiz

  • npm run dev
  • npm run dev:admin
  • npm run dev:frontend
  • npm run dev:backend
  • npm run dev:front_admin
  • npm run scraper
  • npm run scraper:watch
  • npm run test
  • npm run test:coverage
  • npm run build
  • npm run build:frontend
  • npm run build:front_admin
  • npm run validate
  • npm run electron
  • npm run electron:dev
  • npm run dist
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Backend

  • npm run start
  • npm run dev
  • npm run api
  • npm run test
  • npm run test:coverage
  • npm run test:watch
  • npm run validate
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Frontend

  • npm run dev
  • npm run build
  • npm run lint
  • npm run preview
  • npm run test
  • npm run test:coverage
  • npm run test:watch

Front admin

  • npm run dev
  • npm run build
  • npm run lint
  • npm run test
  • npm run test:coverage
  • npm run preview

API backend (estado atual)

Base: /

Sistema:

  • GET /health

Autenticação:

  • GET /auth/:provider/url
  • GET /auth/:provider/callback
  • POST /auth/register
  • POST /auth/login
  • POST /auth/logout
  • GET /auth/me

Usuários:

  • GET /users/profile
  • PATCH /users/profile
  • GET /users/preferences
  • POST /users/preferences
  • PATCH /users/preferences

Jobs:

  • GET /jobs/search
    • Busca vagas nos índices do Valkey e aceita filtros por keywords, family, technology, seniority, level, location, country, type/model, contract e ordenação por matchSort.

Keywords:

  • GET /keywords
  • POST /keywords

Saved jobs:

  • GET /saved-jobs
  • GET /saved-jobs/:id
  • POST /saved-jobs
  • PATCH /saved-jobs/:id
  • DELETE /saved-jobs/:id

Admin:

  • GET /admin/users
  • GET /admin/users/:id
  • PATCH /admin/users/:id/block
  • PATCH /admin/users/:id/unblock
  • POST /admin/users/:id/reset
  • POST /admin/scrapers/run
  • GET /admin/observability/metrics
  • GET /admin/observability/dashboards
  • GET /admin/audit
  • GET /admin/permissions/rules

Swagger:

  • GET /docs

Docker (infra + aplicação)

Este projeto separa infraestrutura e aplicação em dois arquivos Compose:

  • docker-compose.infra.yml: Postgres + Valkey.
  • docker-compose.yml: scraper Go + backend + frontend + front_admin.
  • docker-compose.migrate.yml: job de migrations do backend.

Subir infraestrutura, migrations e aplicação:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

O serviço migrate executa npm run db:migrate e npm run security:backfill-user-pii -- --write depois que o Postgres fica saudável. O backend só inicia depois que esse job termina com sucesso.

Se quiser subir apenas a infraestrutura:

docker compose -f docker-compose.infra.yml up -d

Se quiser subir a aplicação sem o job de migrations:

docker compose up --build -d

Ver logs:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f migrate
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f backend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f frontend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f front_admin
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f scraper-go

Encerrar:

docker compose down
docker compose -f docker-compose.infra.yml down

Observação: os volumes Docker preservam os dados do Postgres e do Valkey entre execuções. Se você alterar POSTGRES_USER, POSTGRES_PASSWORD ou POSTGRES_DB depois da primeira inicialização, será necessário recriar o volume do Postgres ou manter os valores antigos.

Dentro dos containers, serviços devem usar os nomes da rede Docker:

  • Postgres: postgres:5432
  • Valkey: valkey:6379
  • Scraper: scraper-go:8081

Por isso o docker-compose.yml e o docker-compose.migrate.yml sobrescrevem variáveis como DATABASE_URL, VALKEY_URL, GO_SCRAPER_URL e SCRAPER_URL para os valores internos corretos.

Serviços padrão:

Endpoints úteis do scraper:

Desktop com Electron

O app desktop empacota frontend + backend e inicia a aplicação com Electron.

Comandos:

npm run build:frontend
npm run electron

Distribuição (Windows):

npm run dist

Saída esperada do instalador:

  • dist-electron/Vagas Full Setup X.X.X.exe

Variáveis de ambiente

Arquivos de exemplo:

  • .env.example
  • backend/.env.example
  • frontend/.env.example

Arquivos locais ignorados pelo Git:

  • .env
  • backend/.env
  • frontend/.env
  • front_admin/.env, se criado localmente

Uso recomendado:

  • Docker Compose: copie .env.example para .env. O Compose usa esse arquivo para infra, scraper, backend e build do frontend.
  • Backend local via Node: use backend/.env.
  • Frontend local via Vite: use frontend/.env.
  • Front admin local via Vite: crie front_admin/.env com VITE_API_URL=http://localhost:3001 quando precisar sobrescrever o padrão.

Variáveis centrais de operação:

  • DATABASE_URL
  • VALKEY_URL
  • GO_SCRAPER_URL
  • SESSION_SECRET
  • CORS_ALLOWED_ORIGINS
  • SEARCH_LOCATION
  • SEARCH_GEO_ID
  • SEARCH_LANGUAGE
  • REMOTE_ONLY
  • JOB_TYPES
  • TIME_FILTER
  • WAIT_BETWEEN_SEARCHES_MS
  • PAGE_TIMEOUT_MS
  • MAX_PAGES_PER_KEYWORD
  • LINKEDIN_KEYWORD_SLOT_SIZE
  • ADZUNA_KEYWORD_SLOT_SIZE
  • GUPY_ENABLED
  • GUPY_RAW_DISCOVERY_ENABLED
  • GUPY_FULL_SWEEP_ENABLED
  • GUPY_FULL_REMOTE_SWEEP_ENABLED
  • GUPY_QUERY_LIMIT
  • INHIRE_ENABLED
  • INHIRE_ENRICH_DETAILS
  • GREENHOUSE_ENABLED
  • LEVER_ENABLED
  • CACHE_TTL_MS
  • VITE_API_BASE_URL
  • VITE_API_URL
  • VITE_API_PROXY_TARGET
  • VITE_APP_ENV

Segurança operacional:

  • Nunca versionar segredos reais no Git.
  • Preferir acesso interno para banco/cache em VPS.
  • Em ambiente externo, usar TLS para conexões de dados sempre que possível.

Observação operacional do scraper:

  • O padrão atual privilegia resposta rápida e estabilidade. LinkedIn e Adzuna usam slots rotativos de keywords por execução, e Gupy limita a quantidade de queries expandidas por rodada. Isso reduz cobertura imediata por execução, mas evita milhares de requests em uma única rodada e distribui a coleta ao longo das próximas execuções.
  • tools/ e data/ são ignorados pelo Git. Scripts versionados não devem depender de arquivos nessas pastas, a menos que sejam tratados como utilitários locais opcionais.

Testes e qualidade

Estrutura:

  • backend/tests/unit
  • backend/tests/integration
  • frontend/tests/unit
  • frontend/tests/integration
  • front_admin/tests

Threshold mínimo:

  • lines >= 80%
  • statements >= 80%
  • functions >= 80%
  • branches >= 80%

Comandos:

npm run test:coverage
npm --workspace frontend run test:coverage
npm --workspace backend run test:coverage
npm --workspace front_admin run test:coverage

Observação importante: o backend já está configurado para coletar cobertura apenas em src/**/*.ts, evitando contagem de artefatos gerados.

CI/CD

Workflow atual: .github/workflows/ci.yml

Executa em push para master/develop e em pull_request:

  • Instalação de dependências
  • Coverage frontend
  • Coverage backend
  • Lint frontend
  • Build frontend

Observação: o painel admin já possui testes e build próprios, mas ainda deve ser incluído no fluxo de validação/CI quando se tornar parte obrigatória do release.

Fluxo de desenvolvimento e branching

Padrão oficial:

  1. Abrir card no Linear: https://linear.app/tatame/team/PAV/all
  2. Criar branch de feature a partir de master
  3. Desenvolver e testar localmente
  4. Abrir PR da feature para develop
  5. Após aprovação e validação, merge em develop
  6. Abrir PR de develop para master
  7. Merge em master para release

Convenção recomendada de branch:

  • feature/{id-do-card}-{descricao-curta}

Git Hooks e qualidade local

O repositório usa Husky na raiz do monorepo para padronizar validações locais em qualquer branch.

Hooks configurados:

  • pre-commit: executa lint-staged para validar arquivos staged do frontend.
  • commit-msg: valida mensagem de commit com commitlint (Conventional Commits).
  • pre-push: executa validação do monorepo (test backend + lint/build frontend).

Bootstrap local com instalação e hooks:

npm run setup:dev

Checklist quando hooks não disparam:

  1. Validar se o diretório Git foi detectado: git rev-parse --git-dir.
  2. Validar hooksPath local: git config --get core.hooksPath.
  3. Confirmar arquivos versionados em .husky (pre-commit, commit-msg, pre-push).
  4. Reinstalar hooks: npm run prepare.
  5. Em Windows, preferir Git Bash para depuração de scripts shell.

Observação importante:

  • CI continua obrigatório e independente de hooks locais. Mesmo com bypass local, o pipeline valida cobertura/lint/build antes de merge.

Roadmap técnico sugerido

DX e onboarding

  • Adicionar script único de bootstrap (exemplo: npm run setup:dev) para criar .env e validar pré-requisitos.
  • Adicionar verificação automática de scripts quebrados no CI.
  • Padronizar comandos cross-platform (evitar dependência de sintaxe de variável de ambiente Unix em scripts críticos).

Segurança

  • Aplicar política de rotação de SESSION_SECRET e credenciais OAuth.
  • Adicionar checklist de segurança para PRs (cookies, CORS, secrets, headers).

Performance

  • Definir estratégia de paginação e filtros em camada de API com métricas por endpoint.
  • Revisar TTL e cardinalidade dos índices no Valkey para reduzir consumo de memória.

Observabilidade

  • Padronizar correlação de logs por request id.
  • Publicar guia mínimo de troubleshooting com sinais de saúde dos serviços frontend/backend/scraper-go.

Contribuição

  1. Abra um card no Linear.
  2. Crie branch a partir de master.
  3. Implemente com testes.
  4. Execute validações locais:
npm run validate
npm run test:coverage
  1. Abra PR para develop com contexto técnico objetivo.

Se você vai trabalhar em backend, scraper ou testes, use também:

About

Simplifique sua busca por emprego. Todas as oportunidades do mercado reunidas em uma plataforma inteligente e automatizada.

Topics

Resources

Stars

86 stars

Watchers

3 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

527 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

<Cand!Date!>

Novo no projeto? Comece por aqui: LOCAL_DEVELOPMENT.md

CINode >= 22MonorepoLicense ISC

Documentação: README | SCRAPER | BACKEND | TESTING | CONTRIBUTING | ESCOPO | Frontend | Frontend Architecture | Front Admin

Plataforma de captura, agregação e consulta de vagas com arquitetura monorepo, composta por frontend web, API Node.js, scraper Go, painel administrativo e aplicação desktop com Electron.

O produto evoluiu para um modelo orientado a serviços (API + scraper Go + cache/índices), com autenticação, preferências de usuário e integração com banco de dados.

Links oficiais

Sumário

Visão geral

Este repositório centraliza as frentes principais do produto:

  • frontend: aplicação web para usuários finais, com landing page, autenticação e dashboard de vagas. A nova estrutura de painel do frontend fica em frontend/src/domains/new_dashboard.
  • backend: API Node.js/Express com autenticação, perfis, preferências, vagas salvas, notificações, rotas admin e observabilidade.
  • scraper-go: serviço Go de scraping multi-fonte, cache, deduplicação e indexação em Valkey.
  • front_admin: painel administrativo para operação, usuários, permissões, scrapers, auditoria e observabilidade.
  • electron: shell desktop que empacota a experiência principal.

Objetivo de produto: fornecer uma base robusta para busca, filtragem e gestão de vagas com foco em qualidade de dados, escalabilidade e operação contínua.

Arquitetura do monorepo

.
├─ frontend/ # Dashboard web (React + Vite)
├─ backend/ # API Node.js (Express + TS + Drizzle)
├─ scraper-go/ # Serviço Go de scraping multi-fonte
├─ front_admin/ # Painel administrativo (React + Vite)
├─ electron/ # Shell desktop
├─ docker-compose.yml # App stack (frontend + front_admin + backend + scraper-go)
├─ docker-compose.infra.yml # Infra stack (Postgres + Valkey)
├─ docker-compose.migrate.yml # Migration job do backend
└─ .github/workflows/ci.yml # CI

Stack real do projeto

  • Frontend: React 19, TypeScript, Vite 8, Tailwind CSS, Vitest.
  • Front admin: React 19, TypeScript, Vite 8, Tailwind CSS 4, Vitest.
  • Backend: Node.js 22+, Express 5, TypeScript, Drizzle ORM, Zod, Iron Session, Redis/Valkey.
  • Scraping: Go (serviço dedicado em scraper-go).
  • Desktop: Electron + Electron Builder.
  • Qualidade: Vitest (frontend/backend/front_admin), cobertura v8, ESLint (frontend/front_admin), GitHub Actions CI.
  • Dados: Postgres (persistência) + Valkey/Redis (cache e índice).

Quickstart local

Pré-requisitos

  • Node.js >= 22
  • npm
  • Docker Desktop com Docker Compose

Caminho recomendado: stack completa com Docker

Use este fluxo para subir Postgres, Valkey, scraper Go, backend, frontend e front_admin com a mesma rede Docker.

1 - Instale as dependências locais:

npm install

2 - Crie o .env da raiz a partir do exemplo versionado:

cp .env.example .env

No Windows PowerShell:

Copy-Item .env.example .env

3 - Crie a rede Docker compartilhada, se ela ainda não existir:

docker network create vagas-net

Se a rede já existir, o Docker vai avisar e você pode seguir para o próximo passo.

4 - Suba Postgres, Valkey, scraper, backend, frontend e front_admin:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

5 - Acesse os serviços:

Desenvolvimento com Node local

Use este fluxo quando quiser rodar frontend/backend fora do Docker. Mantenha Postgres e Valkey ativos no Docker e configure URLs locais nos arquivos .env.

Arquivos esperados:

  • .env: usado pela infra/scraper e por comandos auxiliares.
  • backend/.env: usado pelo backend local.
  • frontend/.env: usado pelo Vite local.
  • front_admin usa VITE_API_URL, mas ainda não possui .env.example próprio.

Criação dos arquivos locais:

cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env

No Windows PowerShell:

Copy-Item backend/.env.example backend/.env
Copy-Item frontend/.env.example frontend/.env

Comandos:

npm run dev

Esse comando sobe apenas o necessário para a maioria das contribuições: frontend e backend.

Para trabalhar também no painel administrativo:

npm run dev:admin

Execução separada:

npm run dev:frontend
npm run dev:backend
npm run dev:front_admin

Execução de testes

npm run test:coverage

Instalação limpa e CI

Para onboarding e desenvolvimento local, prefira npm install.

Use npm ci em automações como GitHub Actions, Docker/deploy ou quando quiser reinstalar tudo exatamente a partir do package-lock.json. Ele remove node_modules, não altera o lockfile e falha se package.json e package-lock.json estiverem fora de sincronia.

Comandos verificados

Os comandos abaixo existem hoje no repositório e foram conferidos nos package.json da raiz, backend, frontend e front_admin.

Raiz

  • npm run dev
  • npm run dev:admin
  • npm run dev:frontend
  • npm run dev:backend
  • npm run dev:front_admin
  • npm run scraper
  • npm run scraper:watch
  • npm run test
  • npm run test:coverage
  • npm run build
  • npm run build:frontend
  • npm run build:front_admin
  • npm run validate
  • npm run electron
  • npm run electron:dev
  • npm run dist
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Backend

  • npm run start
  • npm run dev
  • npm run api
  • npm run test
  • npm run test:coverage
  • npm run test:watch
  • npm run validate
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Frontend

  • npm run dev
  • npm run build
  • npm run lint
  • npm run preview
  • npm run test
  • npm run test:coverage
  • npm run test:watch

Front admin

  • npm run dev
  • npm run build
  • npm run lint
  • npm run test
  • npm run test:coverage
  • npm run preview

API backend (estado atual)

Base: /

Sistema:

  • GET /health

Autenticação:

  • GET /auth/:provider/url
  • GET /auth/:provider/callback
  • POST /auth/register
  • POST /auth/login
  • POST /auth/logout
  • GET /auth/me

Usuários:

  • GET /users/profile
  • PATCH /users/profile
  • GET /users/preferences
  • POST /users/preferences
  • PATCH /users/preferences

Jobs:

  • GET /jobs/search
    • Busca vagas nos índices do Valkey e aceita filtros por keywords, family, technology, seniority, level, location, country, type/model, contract e ordenação por matchSort.

Keywords:

  • GET /keywords
  • POST /keywords

Saved jobs:

  • GET /saved-jobs
  • GET /saved-jobs/:id
  • POST /saved-jobs
  • PATCH /saved-jobs/:id
  • DELETE /saved-jobs/:id

Admin:

  • GET /admin/users
  • GET /admin/users/:id
  • PATCH /admin/users/:id/block
  • PATCH /admin/users/:id/unblock
  • POST /admin/users/:id/reset
  • POST /admin/scrapers/run
  • GET /admin/observability/metrics
  • GET /admin/observability/dashboards
  • GET /admin/audit
  • GET /admin/permissions/rules

Swagger:

  • GET /docs

Docker (infra + aplicação)

Este projeto separa infraestrutura e aplicação em dois arquivos Compose:

  • docker-compose.infra.yml: Postgres + Valkey.
  • docker-compose.yml: scraper Go + backend + frontend + front_admin.
  • docker-compose.migrate.yml: job de migrations do backend.

Subir infraestrutura, migrations e aplicação:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

O serviço migrate executa npm run db:migrate e npm run security:backfill-user-pii -- --write depois que o Postgres fica saudável. O backend só inicia depois que esse job termina com sucesso.

Se quiser subir apenas a infraestrutura:

docker compose -f docker-compose.infra.yml up -d

Se quiser subir a aplicação sem o job de migrations:

docker compose up --build -d

Ver logs:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f migrate
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f backend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f frontend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f front_admin
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f scraper-go

Encerrar:

docker compose down
docker compose -f docker-compose.infra.yml down

Observação: os volumes Docker preservam os dados do Postgres e do Valkey entre execuções. Se você alterar POSTGRES_USER, POSTGRES_PASSWORD ou POSTGRES_DB depois da primeira inicialização, será necessário recriar o volume do Postgres ou manter os valores antigos.

Dentro dos containers, serviços devem usar os nomes da rede Docker:

  • Postgres: postgres:5432
  • Valkey: valkey:6379
  • Scraper: scraper-go:8081

Por isso o docker-compose.yml e o docker-compose.migrate.yml sobrescrevem variáveis como DATABASE_URL, VALKEY_URL, GO_SCRAPER_URL e SCRAPER_URL para os valores internos corretos.

Serviços padrão:

Endpoints úteis do scraper:

Desktop com Electron

O app desktop empacota frontend + backend e inicia a aplicação com Electron.

Comandos:

npm run build:frontend
npm run electron

Distribuição (Windows):

npm run dist

Saída esperada do instalador:

  • dist-electron/Vagas Full Setup X.X.X.exe

Variáveis de ambiente

Arquivos de exemplo:

  • .env.example
  • backend/.env.example
  • frontend/.env.example

Arquivos locais ignorados pelo Git:

  • .env
  • backend/.env
  • frontend/.env
  • front_admin/.env, se criado localmente

Uso recomendado:

  • Docker Compose: copie .env.example para .env. O Compose usa esse arquivo para infra, scraper, backend e build do frontend.
  • Backend local via Node: use backend/.env.
  • Frontend local via Vite: use frontend/.env.
  • Front admin local via Vite: crie front_admin/.env com VITE_API_URL=http://localhost:3001 quando precisar sobrescrever o padrão.

Variáveis centrais de operação:

  • DATABASE_URL
  • VALKEY_URL
  • GO_SCRAPER_URL
  • SESSION_SECRET
  • CORS_ALLOWED_ORIGINS
  • SEARCH_LOCATION
  • SEARCH_GEO_ID
  • SEARCH_LANGUAGE
  • REMOTE_ONLY
  • JOB_TYPES
  • TIME_FILTER
  • WAIT_BETWEEN_SEARCHES_MS
  • PAGE_TIMEOUT_MS
  • MAX_PAGES_PER_KEYWORD
  • LINKEDIN_KEYWORD_SLOT_SIZE
  • ADZUNA_KEYWORD_SLOT_SIZE
  • GUPY_ENABLED
  • GUPY_RAW_DISCOVERY_ENABLED
  • GUPY_FULL_SWEEP_ENABLED
  • GUPY_FULL_REMOTE_SWEEP_ENABLED
  • GUPY_QUERY_LIMIT
  • INHIRE_ENABLED
  • INHIRE_ENRICH_DETAILS
  • GREENHOUSE_ENABLED
  • LEVER_ENABLED
  • CACHE_TTL_MS
  • VITE_API_BASE_URL
  • VITE_API_URL
  • VITE_API_PROXY_TARGET
  • VITE_APP_ENV

Segurança operacional:

  • Nunca versionar segredos reais no Git.
  • Preferir acesso interno para banco/cache em VPS.
  • Em ambiente externo, usar TLS para conexões de dados sempre que possível.

Observação operacional do scraper:

  • O padrão atual privilegia resposta rápida e estabilidade. LinkedIn e Adzuna usam slots rotativos de keywords por execução, e Gupy limita a quantidade de queries expandidas por rodada. Isso reduz cobertura imediata por execução, mas evita milhares de requests em uma única rodada e distribui a coleta ao longo das próximas execuções.
  • tools/ e data/ são ignorados pelo Git. Scripts versionados não devem depender de arquivos nessas pastas, a menos que sejam tratados como utilitários locais opcionais.

Testes e qualidade

Estrutura:

  • backend/tests/unit
  • backend/tests/integration
  • frontend/tests/unit
  • frontend/tests/integration
  • front_admin/tests

Threshold mínimo:

  • lines >= 80%
  • statements >= 80%
  • functions >= 80%
  • branches >= 80%

Comandos:

npm run test:coverage
npm --workspace frontend run test:coverage
npm --workspace backend run test:coverage
npm --workspace front_admin run test:coverage

Observação importante: o backend já está configurado para coletar cobertura apenas em src/**/*.ts, evitando contagem de artefatos gerados.

CI/CD

Workflow atual: .github/workflows/ci.yml

Executa em push para master/develop e em pull_request:

  • Instalação de dependências
  • Coverage frontend
  • Coverage backend
  • Lint frontend
  • Build frontend

Observação: o painel admin já possui testes e build próprios, mas ainda deve ser incluído no fluxo de validação/CI quando se tornar parte obrigatória do release.

Fluxo de desenvolvimento e branching

Padrão oficial:

  1. Abrir card no Linear: https://linear.app/tatame/team/PAV/all
  2. Criar branch de feature a partir de master
  3. Desenvolver e testar localmente
  4. Abrir PR da feature para develop
  5. Após aprovação e validação, merge em develop
  6. Abrir PR de develop para master
  7. Merge em master para release

Convenção recomendada de branch:

  • feature/{id-do-card}-{descricao-curta}

Git Hooks e qualidade local

O repositório usa Husky na raiz do monorepo para padronizar validações locais em qualquer branch.

Hooks configurados:

  • pre-commit: executa lint-staged para validar arquivos staged do frontend.
  • commit-msg: valida mensagem de commit com commitlint (Conventional Commits).
  • pre-push: executa validação do monorepo (test backend + lint/build frontend).

Bootstrap local com instalação e hooks:

npm run setup:dev

Checklist quando hooks não disparam:

  1. Validar se o diretório Git foi detectado: git rev-parse --git-dir.
  2. Validar hooksPath local: git config --get core.hooksPath.
  3. Confirmar arquivos versionados em .husky (pre-commit, commit-msg, pre-push).
  4. Reinstalar hooks: npm run prepare.
  5. Em Windows, preferir Git Bash para depuração de scripts shell.

Observação importante:

  • CI continua obrigatório e independente de hooks locais. Mesmo com bypass local, o pipeline valida cobertura/lint/build antes de merge.

Roadmap técnico sugerido

DX e onboarding

  • Adicionar script único de bootstrap (exemplo: npm run setup:dev) para criar .env e validar pré-requisitos.
  • Adicionar verificação automática de scripts quebrados no CI.
  • Padronizar comandos cross-platform (evitar dependência de sintaxe de variável de ambiente Unix em scripts críticos).

Segurança

  • Aplicar política de rotação de SESSION_SECRET e credenciais OAuth.
  • Adicionar checklist de segurança para PRs (cookies, CORS, secrets, headers).

Performance

  • Definir estratégia de paginação e filtros em camada de API com métricas por endpoint.
  • Revisar TTL e cardinalidade dos índices no Valkey para reduzir consumo de memória.

Observabilidade

  • Padronizar correlação de logs por request id.
  • Publicar guia mínimo de troubleshooting com sinais de saúde dos serviços frontend/backend/scraper-go.

Contribuição

  1. Abra um card no Linear.
  2. Crie branch a partir de master.
  3. Implemente com testes.
  4. Execute validações locais:
npm run validate
npm run test:coverage
  1. Abra PR para develop com contexto técnico objetivo.

Se você vai trabalhar em backend, scraper ou testes, use também:

About

Simplifique sua busca por emprego. Todas as oportunidades do mercado reunidas em uma plataforma inteligente e automatizada.

Topics

Resources

Stars

86 stars

Watchers

3 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

527 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

<Cand!Date!>

Novo no projeto? Comece por aqui: LOCAL_DEVELOPMENT.md

CINode >= 22MonorepoLicense ISC

Documentação: README | SCRAPER | BACKEND | TESTING | CONTRIBUTING | ESCOPO | Frontend | Frontend Architecture | Front Admin

Plataforma de captura, agregação e consulta de vagas com arquitetura monorepo, composta por frontend web, API Node.js, scraper Go, painel administrativo e aplicação desktop com Electron.

O produto evoluiu para um modelo orientado a serviços (API + scraper Go + cache/índices), com autenticação, preferências de usuário e integração com banco de dados.

Links oficiais

Sumário

Visão geral

Este repositório centraliza as frentes principais do produto:

  • frontend: aplicação web para usuários finais, com landing page, autenticação e dashboard de vagas. A nova estrutura de painel do frontend fica em frontend/src/domains/new_dashboard.
  • backend: API Node.js/Express com autenticação, perfis, preferências, vagas salvas, notificações, rotas admin e observabilidade.
  • scraper-go: serviço Go de scraping multi-fonte, cache, deduplicação e indexação em Valkey.
  • front_admin: painel administrativo para operação, usuários, permissões, scrapers, auditoria e observabilidade.
  • electron: shell desktop que empacota a experiência principal.

Objetivo de produto: fornecer uma base robusta para busca, filtragem e gestão de vagas com foco em qualidade de dados, escalabilidade e operação contínua.

Arquitetura do monorepo

.
├─ frontend/ # Dashboard web (React + Vite)
├─ backend/ # API Node.js (Express + TS + Drizzle)
├─ scraper-go/ # Serviço Go de scraping multi-fonte
├─ front_admin/ # Painel administrativo (React + Vite)
├─ electron/ # Shell desktop
├─ docker-compose.yml # App stack (frontend + front_admin + backend + scraper-go)
├─ docker-compose.infra.yml # Infra stack (Postgres + Valkey)
├─ docker-compose.migrate.yml # Migration job do backend
└─ .github/workflows/ci.yml # CI

Stack real do projeto

  • Frontend: React 19, TypeScript, Vite 8, Tailwind CSS, Vitest.
  • Front admin: React 19, TypeScript, Vite 8, Tailwind CSS 4, Vitest.
  • Backend: Node.js 22+, Express 5, TypeScript, Drizzle ORM, Zod, Iron Session, Redis/Valkey.
  • Scraping: Go (serviço dedicado em scraper-go).
  • Desktop: Electron + Electron Builder.
  • Qualidade: Vitest (frontend/backend/front_admin), cobertura v8, ESLint (frontend/front_admin), GitHub Actions CI.
  • Dados: Postgres (persistência) + Valkey/Redis (cache e índice).

Quickstart local

Pré-requisitos

  • Node.js >= 22
  • npm
  • Docker Desktop com Docker Compose

Caminho recomendado: stack completa com Docker

Use este fluxo para subir Postgres, Valkey, scraper Go, backend, frontend e front_admin com a mesma rede Docker.

1 - Instale as dependências locais:

npm install

2 - Crie o .env da raiz a partir do exemplo versionado:

cp .env.example .env

No Windows PowerShell:

Copy-Item .env.example .env

3 - Crie a rede Docker compartilhada, se ela ainda não existir:

docker network create vagas-net

Se a rede já existir, o Docker vai avisar e você pode seguir para o próximo passo.

4 - Suba Postgres, Valkey, scraper, backend, frontend e front_admin:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

5 - Acesse os serviços:

Desenvolvimento com Node local

Use este fluxo quando quiser rodar frontend/backend fora do Docker. Mantenha Postgres e Valkey ativos no Docker e configure URLs locais nos arquivos .env.

Arquivos esperados:

  • .env: usado pela infra/scraper e por comandos auxiliares.
  • backend/.env: usado pelo backend local.
  • frontend/.env: usado pelo Vite local.
  • front_admin usa VITE_API_URL, mas ainda não possui .env.example próprio.

Criação dos arquivos locais:

cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env

No Windows PowerShell:

Copy-Item backend/.env.example backend/.env
Copy-Item frontend/.env.example frontend/.env

Comandos:

npm run dev

Esse comando sobe apenas o necessário para a maioria das contribuições: frontend e backend.

Para trabalhar também no painel administrativo:

npm run dev:admin

Execução separada:

npm run dev:frontend
npm run dev:backend
npm run dev:front_admin

Execução de testes

npm run test:coverage

Instalação limpa e CI

Para onboarding e desenvolvimento local, prefira npm install.

Use npm ci em automações como GitHub Actions, Docker/deploy ou quando quiser reinstalar tudo exatamente a partir do package-lock.json. Ele remove node_modules, não altera o lockfile e falha se package.json e package-lock.json estiverem fora de sincronia.

Comandos verificados

Os comandos abaixo existem hoje no repositório e foram conferidos nos package.json da raiz, backend, frontend e front_admin.

Raiz

  • npm run dev
  • npm run dev:admin
  • npm run dev:frontend
  • npm run dev:backend
  • npm run dev:front_admin
  • npm run scraper
  • npm run scraper:watch
  • npm run test
  • npm run test:coverage
  • npm run build
  • npm run build:frontend
  • npm run build:front_admin
  • npm run validate
  • npm run electron
  • npm run electron:dev
  • npm run dist
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Backend

  • npm run start
  • npm run dev
  • npm run api
  • npm run test
  • npm run test:coverage
  • npm run test:watch
  • npm run validate
  • npm run db:generate
  • npm run db:migrate
  • npm run db:push

Frontend

  • npm run dev
  • npm run build
  • npm run lint
  • npm run preview
  • npm run test
  • npm run test:coverage
  • npm run test:watch

Front admin

  • npm run dev
  • npm run build
  • npm run lint
  • npm run test
  • npm run test:coverage
  • npm run preview

API backend (estado atual)

Base: /

Sistema:

  • GET /health

Autenticação:

  • GET /auth/:provider/url
  • GET /auth/:provider/callback
  • POST /auth/register
  • POST /auth/login
  • POST /auth/logout
  • GET /auth/me

Usuários:

  • GET /users/profile
  • PATCH /users/profile
  • GET /users/preferences
  • POST /users/preferences
  • PATCH /users/preferences

Jobs:

  • GET /jobs/search
    • Busca vagas nos índices do Valkey e aceita filtros por keywords, family, technology, seniority, level, location, country, type/model, contract e ordenação por matchSort.

Keywords:

  • GET /keywords
  • POST /keywords

Saved jobs:

  • GET /saved-jobs
  • GET /saved-jobs/:id
  • POST /saved-jobs
  • PATCH /saved-jobs/:id
  • DELETE /saved-jobs/:id

Admin:

  • GET /admin/users
  • GET /admin/users/:id
  • PATCH /admin/users/:id/block
  • PATCH /admin/users/:id/unblock
  • POST /admin/users/:id/reset
  • POST /admin/scrapers/run
  • GET /admin/observability/metrics
  • GET /admin/observability/dashboards
  • GET /admin/audit
  • GET /admin/permissions/rules

Swagger:

  • GET /docs

Docker (infra + aplicação)

Este projeto separa infraestrutura e aplicação em dois arquivos Compose:

  • docker-compose.infra.yml: Postgres + Valkey.
  • docker-compose.yml: scraper Go + backend + frontend + front_admin.
  • docker-compose.migrate.yml: job de migrations do backend.

Subir infraestrutura, migrations e aplicação:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml up --build -d

O serviço migrate executa npm run db:migrate e npm run security:backfill-user-pii -- --write depois que o Postgres fica saudável. O backend só inicia depois que esse job termina com sucesso.

Se quiser subir apenas a infraestrutura:

docker compose -f docker-compose.infra.yml up -d

Se quiser subir a aplicação sem o job de migrations:

docker compose up --build -d

Ver logs:

docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f migrate
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f backend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f frontend
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f front_admin
docker compose -f docker-compose.infra.yml -f docker-compose.yml -f docker-compose.migrate.yml logs -f scraper-go

Encerrar:

docker compose down
docker compose -f docker-compose.infra.yml down

Observação: os volumes Docker preservam os dados do Postgres e do Valkey entre execuções. Se você alterar POSTGRES_USER, POSTGRES_PASSWORD ou POSTGRES_DB depois da primeira inicialização, será necessário recriar o volume do Postgres ou manter os valores antigos.

Dentro dos containers, serviços devem usar os nomes da rede Docker:

  • Postgres: postgres:5432
  • Valkey: valkey:6379
  • Scraper: scraper-go:8081

Por isso o docker-compose.yml e o docker-compose.migrate.yml sobrescrevem variáveis como DATABASE_URL, VALKEY_URL, GO_SCRAPER_URL e SCRAPER_URL para os valores internos corretos.

Serviços padrão:

Endpoints úteis do scraper:

Desktop com Electron

O app desktop empacota frontend + backend e inicia a aplicação com Electron.

Comandos:

npm run build:frontend
npm run electron

Distribuição (Windows):

npm run dist

Saída esperada do instalador:

  • dist-electron/Vagas Full Setup X.X.X.exe

Variáveis de ambiente

Arquivos de exemplo:

  • .env.example
  • backend/.env.example
  • frontend/.env.example

Arquivos locais ignorados pelo Git:

  • .env
  • backend/.env
  • frontend/.env
  • front_admin/.env, se criado localmente

Uso recomendado:

  • Docker Compose: copie .env.example para .env. O Compose usa esse arquivo para infra, scraper, backend e build do frontend.
  • Backend local via Node: use backend/.env.
  • Frontend local via Vite: use frontend/.env.
  • Front admin local via Vite: crie front_admin/.env com VITE_API_URL=http://localhost:3001 quando precisar sobrescrever o padrão.

Variáveis centrais de operação:

  • DATABASE_URL
  • VALKEY_URL
  • GO_SCRAPER_URL
  • SESSION_SECRET
  • CORS_ALLOWED_ORIGINS
  • SEARCH_LOCATION
  • SEARCH_GEO_ID
  • SEARCH_LANGUAGE
  • REMOTE_ONLY
  • JOB_TYPES
  • TIME_FILTER
  • WAIT_BETWEEN_SEARCHES_MS
  • PAGE_TIMEOUT_MS
  • MAX_PAGES_PER_KEYWORD
  • LINKEDIN_KEYWORD_SLOT_SIZE
  • ADZUNA_KEYWORD_SLOT_SIZE
  • GUPY_ENABLED
  • GUPY_RAW_DISCOVERY_ENABLED
  • GUPY_FULL_SWEEP_ENABLED
  • GUPY_FULL_REMOTE_SWEEP_ENABLED
  • GUPY_QUERY_LIMIT
  • INHIRE_ENABLED
  • INHIRE_ENRICH_DETAILS
  • GREENHOUSE_ENABLED
  • LEVER_ENABLED
  • CACHE_TTL_MS
  • VITE_API_BASE_URL
  • VITE_API_URL
  • VITE_API_PROXY_TARGET
  • VITE_APP_ENV

Segurança operacional:

  • Nunca versionar segredos reais no Git.
  • Preferir acesso interno para banco/cache em VPS.
  • Em ambiente externo, usar TLS para conexões de dados sempre que possível.

Observação operacional do scraper:

  • O padrão atual privilegia resposta rápida e estabilidade. LinkedIn e Adzuna usam slots rotativos de keywords por execução, e Gupy limita a quantidade de queries expandidas por rodada. Isso reduz cobertura imediata por execução, mas evita milhares de requests em uma única rodada e distribui a coleta ao longo das próximas execuções.
  • tools/ e data/ são ignorados pelo Git. Scripts versionados não devem depender de arquivos nessas pastas, a menos que sejam tratados como utilitários locais opcionais.

Testes e qualidade

Estrutura:

  • backend/tests/unit
  • backend/tests/integration
  • frontend/tests/unit
  • frontend/tests/integration
  • front_admin/tests

Threshold mínimo:

  • lines >= 80%
  • statements >= 80%
  • functions >= 80%
  • branches >= 80%

Comandos:

npm run test:coverage
npm --workspace frontend run test:coverage
npm --workspace backend run test:coverage
npm --workspace front_admin run test:coverage

Observação importante: o backend já está configurado para coletar cobertura apenas em src/**/*.ts, evitando contagem de artefatos gerados.

CI/CD

Workflow atual: .github/workflows/ci.yml

Executa em push para master/develop e em pull_request:

  • Instalação de dependências
  • Coverage frontend
  • Coverage backend
  • Lint frontend
  • Build frontend

Observação: o painel admin já possui testes e build próprios, mas ainda deve ser incluído no fluxo de validação/CI quando se tornar parte obrigatória do release.

Fluxo de desenvolvimento e branching

Padrão oficial:

  1. Abrir card no Linear: https://linear.app/tatame/team/PAV/all
  2. Criar branch de feature a partir de master
  3. Desenvolver e testar localmente
  4. Abrir PR da feature para develop
  5. Após aprovação e validação, merge em develop
  6. Abrir PR de develop para master
  7. Merge em master para release

Convenção recomendada de branch:

  • feature/{id-do-card}-{descricao-curta}

Git Hooks e qualidade local

O repositório usa Husky na raiz do monorepo para padronizar validações locais em qualquer branch.

Hooks configurados:

  • pre-commit: executa lint-staged para validar arquivos staged do frontend.
  • commit-msg: valida mensagem de commit com commitlint (Conventional Commits).
  • pre-push: executa validação do monorepo (test backend + lint/build frontend).

Bootstrap local com instalação e hooks:

npm run setup:dev

Checklist quando hooks não disparam:

  1. Validar se o diretório Git foi detectado: git rev-parse --git-dir.
  2. Validar hooksPath local: git config --get core.hooksPath.
  3. Confirmar arquivos versionados em .husky (pre-commit, commit-msg, pre-push).
  4. Reinstalar hooks: npm run prepare.
  5. Em Windows, preferir Git Bash para depuração de scripts shell.

Observação importante:

  • CI continua obrigatório e independente de hooks locais. Mesmo com bypass local, o pipeline valida cobertura/lint/build antes de merge.

Roadmap técnico sugerido

DX e onboarding

  • Adicionar script único de bootstrap (exemplo: npm run setup:dev) para criar .env e validar pré-requisitos.
  • Adicionar verificação automática de scripts quebrados no CI.
  • Padronizar comandos cross-platform (evitar dependência de sintaxe de variável de ambiente Unix em scripts críticos).

Segurança

  • Aplicar política de rotação de SESSION_SECRET e credenciais OAuth.
  • Adicionar checklist de segurança para PRs (cookies, CORS, secrets, headers).

Performance

  • Definir estratégia de paginação e filtros em camada de API com métricas por endpoint.
  • Revisar TTL e cardinalidade dos índices no Valkey para reduzir consumo de memória.

Observabilidade

  • Padronizar correlação de logs por request id.
  • Publicar guia mínimo de troubleshooting com sinais de saúde dos serviços frontend/backend/scraper-go.

Contribuição

  1. Abra um card no Linear.
  2. Crie branch a partir de master.
  3. Implemente com testes.
  4. Execute validações locais:
npm run validate
npm run test:coverage
  1. Abra PR para develop com contexto técnico objetivo.

Se você vai trabalhar em backend, scraper ou testes, use também:

About

Simplifique sua busca por emprego. Todas as oportunidades do mercado reunidas em uma plataforma inteligente e automatizada.

Topics

Resources

Stars

86 stars

Watchers

3 watching

Forks

Contributors

Languages