# 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: ```bash 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. ```bash 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: ```bash curl -X POST http://localhost:8080/tasks \ -H "Content-Type: application/json" \ -d '{"name":"Prepare sprint review","description":"Collect release notes"}' ``` ## Run the frontend ```bash 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: ```bash cd backend ./mvnw test ``` Frontend: ```bash 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`