No description
Find a file
Gabriel Santana de Menezes 814bc51b86 Fix task timer showing negative values
Ensure running seconds never go negative by using Math.max(0, ...)
This prevents the timer from showing negative values when there's a
clock skew between client and server.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-18 09:59:56 -04:00
.claude/skills chore: remove duplicated standards from new-task skill 2026-05-12 20:04:45 -04:00
.github tentando outra forma de ler os dados 2026-05-13 19:07:50 -04:00
backend Add optional assignee to task form 2026-05-17 21:18:07 -04:00
deploy chore: configurar domínios customizados task.beetech.dev e api.task.beetech.dev 2026-05-16 11:14:07 -04:00
frontend Fix task timer showing negative values 2026-05-18 09:59:56 -04:00
.gitignore gc 2026-05-12 20:06:44 -04:00
CLAUDE.md feat: filtros de busca nas listagens de tasks (#26) 2026-05-14 22:12:05 -04:00
GITHUB_SECRETS_CHECKLIST.md chore: deploy 2026-05-12 20:06:44 -04:00
README.md chore: deploy 2026-05-12 20:06:44 -04:00

TimeTrack MVP

Minimal vertical slice for task management using:

  • React + TypeScript + Tailwind CSS
  • Java + Quarkus
  • PostgreSQL
  • Keycloak prepared for future authentication

Structure

  • frontend/: Vite React app with task list, task creation, and status updates
  • backend/: Quarkus API with a simple Clean Architecture split
  • docker-compose.yml: local PostgreSQL and Keycloak services

Run infrastructure

Start PostgreSQL and Keycloak:

docker-compose up

Services:

  • PostgreSQL: localhost:5432
  • Keycloak: http://localhost:8081
  • Keycloak admin: admin / admin

Run the backend

The backend uses the Maven wrapper generated by Quarkus.

cd backend
./mvnw quarkus:dev

Default database settings point to the local Docker PostgreSQL instance, including in the dev profile:

  • database: beetask
  • user: beetask
  • password: beetask
  • JDBC URL: jdbc:postgresql://localhost:5432/beetask

If needed, you can override them with:

  • DB_URL
  • DB_USER
  • DB_PASSWORD

Main API endpoints:

  • POST /tasks
  • PATCH /tasks/{id}/status
  • GET /tasks

Example create request:

curl -X POST http://localhost:8080/tasks \
  -H "Content-Type: application/json" \
  -d '{"name":"Prepare sprint review","description":"Collect release notes"}'

Run the frontend

cd frontend
npm install
npm run dev

The Vite dev server runs on http://localhost:5173 and proxies /api/* to the backend on http://localhost:8080.

If needed, you can override the API target with VITE_API_URL.

Architecture notes

The backend keeps the vertical slice intentionally small:

  • domain: task entity and status enum
  • application: use cases and repository port
  • adapter/in: REST API
  • adapter/out: PostgreSQL persistence with Panache

Important pragmatic decisions:

  • UUIDs are generated in the application layer to keep the slice simple.
  • Flyway owns schema creation with a single migration.
  • Keycloak is available locally now but not integrated into the app yet.

Verification

Backend:

cd backend
./mvnw test

Frontend:

cd frontend
npm run build

Deploy automatizado

O repositório agora inclui um workflow em .github/workflows/deploy-main.yml para deploy automático quando houver push na branch main.

Fluxo:

  • roda testes do backend
  • roda build do frontend
  • gera e publica imagens Docker no GHCR
  • copia deploy/docker-compose.prod.yml para o servidor
  • conecta via SSH na Hostinger e executa docker compose pull && docker compose up -d

Arquivos de apoio:

  • backend/Dockerfile: imagem de produção do backend
  • frontend/Dockerfile: build do Vite + entrega por Nginx
  • frontend/nginx.conf: fallback SPA
  • deploy/docker-compose.prod.yml: stack de produção
  • deploy/.env.production.example: variáveis esperadas no servidor

Secrets necessários no GitHub:

  • HOSTINGER_HOST: IP ou domínio do servidor
  • HOSTINGER_PORT: porta SSH, normalmente 22
  • HOSTINGER_USER: usuário SSH
  • HOSTINGER_SSH_KEY: chave privada SSH usada no acesso ao servidor
  • HOSTINGER_APP_PATH: diretório remoto onde o deploy será mantido, por exemplo /home/user/apps/beetask
  • GHCR_USERNAME: usuário dono do pacote no GHCR
  • GHCR_READ_TOKEN: token com permissão de read:packages para o servidor fazer pull das imagens
  • FRONTEND_VITE_API_URL: URL que o frontend usará para a API, por exemplo https://api.seudominio.com ou /api
  • POSTGRES_USER
  • POSTGRES_PASSWORD
  • DB_URL: JDBC URL completa do banco, por exemplo jdbc:postgresql://203.0.113.10:5432/beetask
  • MP_JWT_VERIFY_ISSUER
  • SMALLRYE_JWT_SIGN_KEY_LOCATION
  • MP_JWT_VERIFY_PUBLICKEY_LOCATION

Pré-requisitos no servidor:

  • Docker instalado
  • Docker Compose plugin disponível via docker compose
  • pasta definida em HOSTINGER_APP_PATH com permissão de escrita para o usuário SSH
  • caso as imagens GHCR sejam privadas, o GHCR_READ_TOKEN precisa conseguir fazer pull

Observações:

  • o workflow usa a tag latest para o deploy em produção
  • a rota do frontend no container está exposta na porta 3000 do servidor e o backend na 8080; normalmente você vai colocar Nginx, Caddy ou o proxy da Hostinger na frente dessas portas
  • se quiser servir frontend e backend em domínios diferentes, ajuste FRONTEND_VITE_API_URL