Local Development
Hephaestus supports full-stack development across Java, TypeScript, and Python. This guide focuses on the development environment; production operations are covered in the Admin Guide.
Prerequisites
Install and configure the following tools before you attempt a local build:
- Java JDK 21 – Required for the Spring Boot application server.
- Docker Desktop – Used for PostgreSQL, Keycloak, and NATS containers.
- Node.js LTS (>= 22.10) and npm (>= 10.8) – For the React client.
- Python (>= 3.13) and Poetry (>= 2.0) – For the FastAPI intelligence service.
- NATS CLI (optional) – Helpful when debugging webhook messages.
Recommended IDE setup
Open the repository using the project.code-workspace file in VS Code and install the workspace recommendations (@recommended in the Extensions view). Key extensions include:
- Java Extension Pack
- Spring Boot tools
- Python and Poetry support
- ESLint + Prettier
- Tailwind CSS IntelliSense
JetBrains alternatives such as IntelliJ (Java), WebStorm (React), and PyCharm (Python) work equally well.
Application server
Maven profiles and local configuration
We ship three Maven profiles: local (default), prod, and spec. For development stick to the local profile.
Create application-server/src/main/resources/application-local.yml to override defaults. This file is gitignored.
Never commit application-local.yml. It may contain secrets and machine-specific configuration.
Running the server
-
Start Docker Desktop.
-
From
server/application-server, run:./mvnw spring-boot:run -
Access the API at
http://localhost:8080or explorehttp://localhost:8080/swagger-ui/index.html.
GitHub configuration
Hephaestus supports two GitHub authentication modes. Pick the one that fits your workflow:
| Mode | Best for | Workspace creation | Repository monitors |
|---|---|---|---|
| PAT | Quick local development | Manual (from config) | Manual (you list them) |
| GitHub App | Testing webhooks, production | Automatic (from installations) | Automatic (from installation events) |
Option A: Personal Access Token (simpler)
-
Create a Personal Access Token with scopes:
repo,read:org,read:user. -
Create
application-local.yml:hephaestus:
workspace:
init-default: true
default:
login: your-github-org # e.g., "ls1intum" or "HephaestusTest"
token: ghp_your_token
repositories-to-monitor:
- your-github-org/repo1
- your-github-org/repo2 -
Leave
github.app.idunset or set to0.
Option B: GitHub App
-
Create a GitHub App with appropriate permissions.
-
Create
application-local.yml:github:
app:
id: 12345
privateKey: |
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
hephaestus:
workspace:
init-default: false # Workspaces created from installations -
Install the app on your organization. Workspaces and monitors are created automatically.
Limiting sync scope (development filters)
When using GitHub App mode, your app might have access to hundreds of repositories. Use filters to focus on specific orgs/repos during development:
monitoring:
filters:
allowed-organizations:
- ls1intum
- HephaestusTest
allowed-repositories:
- ls1intum/Hephaestus
- ls1intum/Artemis
- HephaestusTest/demo-repository
Empty lists = no filtering (production behavior). Non-empty = only sync matching items.
Filters don't delete data—they just skip sync operations. Workspace and organization metadata is still created for all installations.
Keycloak integration
Keycloak runs in Docker as part of the development compose stack. The bundled realm import no longer ships test users—authentication always flows through GitHub and mirrors production.
Configure the GitHub identity provider
-
Create a new GitHub OAuth application with the callback URL
http://localhost:8081/realms/hephaestus/broker/github/endpoint. -
Export the generated Client ID and Client secret, then copy
server/application-server/.env.exampletoserver/application-server/.envand update the placeholders:cp server/application-server/.env.example server/application-server/.env
KEYCLOAK_GITHUB_CLIENT_ID=<github-client-id>
KEYCLOAK_GITHUB_CLIENT_SECRET=<github-client-secret>
KEYCLOAK_GITHUB_ADMIN_USERNAME=<github-handle-with-admin-access>The Keycloak container resolves these placeholders during realm import, as documented in the Keycloak import guide.
-
(Re)start the local stack:
docker compose up keycloak postgres. On first boot Keycloak importskeycloak-hephaestus-realm-example-config.jsonand wires the GitHub provider automatically. -
Sign in via GitHub using the account referenced by
KEYCLOAK_GITHUB_ADMIN_USERNAME. During the first brokered login Keycloak automatically grants that account theadminrealm role and therealm-management→realm-adminclient role, unlocking the administrative views in the application server and Keycloak console.
Webhook ingest service
When you run docker/compose.core.yaml or the server/webhook-ingest/compose.yaml stack, set the webhook secrets up front so signature checks succeed:
cp docker/.env.example docker/.env
export WEBHOOK_SECRET=$(openssl rand -hex 32)
echo "WEBHOOK_SECRET=$WEBHOOK_SECRET" >> docker/.env
The value must match the secret configured on your GitHub and GitLab webhooks (validated via X-Hub-Signature-256 when available).
Web client (webapp)
-
Install dependencies:
npm install -
Start Vite on port 4200:
npm -w webapp run dev -
Visit
http://localhost:4200.
UI foundations
- We ship Tailwind CSS 4 in JIT mode. Keep utility classes in JSX and rely on design tokens defined in
src/styles.css. - Ensure Tailwind IntelliSense is enabled in your IDE—typeahead prevents typos and invalid compositions.
- Avoid premature abstractions with
@apply; duplication is fine when it keeps components readable.
Component workflow (Storybook + Chromatic)
Storybook is the source of truth for presentational components.
npm -w webapp run storybook # Local playground on http://localhost:6006
npm -w webapp run build-storybook # Static bundle for Chromatic
npm -w webapp run chromatic:ci # Visual regression in CI
- Every new UI component ships with at least one story covering empty, loading, and error states.
- Chromatic runs on every pull request—review visual diffs before merging.
- Reference ui.shadcn.com for composition patterns; stick to headless Radix primitives when you need new widgets.
OpenAPI client
The generated client in src/api is the only way the webapp talks to server services.
npm -w webapp run openapi-ts
- Generated types drop the
Dtosuffix and mirror the Spring Boot API responses. - Pair every new endpoint with a typed TanStack Query hook for caching and invalidation.
- Never hand-roll fetch calls—shared interceptors handle auth tokens and error telemetry.
Intelligence service (server/intelligence-service)
-
Create and activate a virtual environment:
python3 -m venv .venv
source .venv/bin/activate -
Install dependencies with Poetry:
poetry install -
Start FastAPI:
fastapi devThe service is available at http://127.0.0.1:8000 with interactive docs at
/docs.
GenAI integrations
Copy .env.example to .env and add credentials for the GenAI providers (e.g., Ollama, OpenAI) plus optional LangSmith/Langfuse instrumentation.
FastAPI fundamentals
- Routes live in
app/routers. Keep dependencies minimal and favour dependency injection for shared services. - LangGraph flows sit in
app/mentor. Regenerate the shared state definitions whenever you introduce new slots. - Auto-generated SQLAlchemy models (
app/db/models_gen.py) must not be edited manually—usenpm run db:generate-models:intelligence-serviceafter schema changes.