StoryTeller/docs/development-workflow.md
Konrad Neitzel 7302cc52a7 Add initial project structure with Maven, Quarkus, and React setup
- Created .gitignore to exclude build artifacts and IDE files.
- Added pom.xml for Maven project configuration, including dependencies for Quarkus, OpenAPI, and testing.
- Introduced project documentation outlining development workflow, architecture, and coding standards.
- Implemented core business logic with services for authentication, scenario management, story lifecycle, and user management.
- Established security context for JWT-based authentication.
- Generated API specifications and client code for frontend integration.
- Set up initial database entities and repositories for user, scenario, and story management.
2026-02-25 04:17:40 +01:00

4.6 KiB

StoryTeller Development Workflow

Stack and Layout

  • Backend: Quarkus 3.31.2 (Java 21, Maven).
  • Frontend: React 18 + TypeScript + Vite in src/main/web.
  • Database: PostgreSQL with Liquibase migrations.
  • Auth: SmallRye JWT with RSA key signing; BCrypt password hashing.
  • API Contract: OpenAPI 3.0.3 at src/main/resources/openapi/story-teller-api.yaml.
  • Generated Code:
    • Java interfaces/models: target/generated-sources/openapi/java/src/gen/java/
    • TypeScript client: src/main/web/src/api/generated/

Local Setup

  1. Prerequisites: JDK 21, Maven 3.9+, PostgreSQL, Node.js 22 (managed by frontend-maven-plugin).
  2. Database: Create a PostgreSQL database:
    CREATE DATABASE storyteller;
    CREATE USER storyteller WITH PASSWORD 'storyteller';
    GRANT ALL PRIVILEGES ON DATABASE storyteller TO storyteller;
    
  3. Build everything: mvn package (generates API code, compiles Java, builds frontend, runs tests).
  4. Run in dev mode: mvn quarkus:dev (hot reload, frontend proxy at http://localhost:5173).
  5. Frontend dev: cd src/main/web && npm run dev (standalone Vite dev server, proxies /api to Quarkus).

Default Admin Account

After first startup, Liquibase seeds an admin user:

  • Username: admin
  • Password: admin

Change this immediately in non-development environments.

OpenAPI-First Rules

  • The OpenAPI YAML is the single source of truth for backend and frontend API contracts.
  • Never edit generated files in target/generated-sources/ or src/main/web/src/api/generated/.
  • To change the API:
    1. Edit src/main/resources/openapi/story-teller-api.yaml.
    2. Run mvn generate-sources to regenerate Java and TypeScript.
    3. Update service/resource implementations to match new interfaces.

Common Commands

Command Description
mvn generate-sources Regenerate Java+TS from OpenAPI
mvn compile Compile Java backend
mvn test Run unit tests
mvn package Full build: Java + frontend + tests
mvn quarkus:dev Dev mode with hot reload
cd src/main/web && npm run dev Frontend dev server

Architecture Overview

de.neitzel.storyteller
├── business/         # Business logic services
├── common/
│   └── security/     # JWT, password hashing, auth context
├── data/
│   ├── entity/       # JPA entities
│   └── repository/   # Panache repositories
└── fascade/
    ├── api/          # Generated OpenAPI interfaces (DO NOT EDIT)
    ├── model/        # Generated OpenAPI models (DO NOT EDIT)
    └── rest/         # REST resource implementations

Authentication Flow

  1. Client sends POST /api/auth/login with username/password.
  2. Server verifies credentials, returns signed JWT with user claims.
  3. Client stores JWT in localStorage and sends it as Authorization: Bearer <token> on all subsequent requests.
  4. Quarkus SmallRye JWT validates the token on protected endpoints.
  5. AuthContext (request-scoped CDI bean) extracts user identity from the JWT.

Authorization

  • Public: /api/auth/*
  • Admin-only: /api/users/* (user management)
  • Authenticated users: /api/scenarios/*, /api/stories/* (with per-user ownership checks)

Story Generation & Compaction

The AI step generation flow includes automatic context compaction:

  1. Client sends a direction prompt.
  2. Server estimates context size (scene + characters + unmerged steps + direction).
  3. If it exceeds the limit (~12K chars), the oldest half of unmerged steps are compacted into the scene description.
  4. Steps are marked addedToScene = true after compaction.
  5. The AI generates the next step from the (possibly compacted) context.
  6. The response includes a compacted flag so the frontend can prompt the user to review the updated scene.

Note: The current AI adapter is a stub that generates placeholder text. Replace the generateAiContinuation and compactScene methods in StoryService with actual LLM integration.

Testing

  • Unit tests use JUnit 5 + Mockito in src/test/java/.
  • Tests cover auth, user service, scenario service, and story service.
  • Run with mvn test.

Troubleshooting

  • JWT errors: Ensure privateKey.pem and publicKey.pem exist in src/main/resources/.
  • Generated code issues: Run mvn clean generate-sources to rebuild from scratch.
  • TypeScript errors: Check that src/main/web/node_modules exists; run npm install in src/main/web.
  • DB connection: Verify PostgreSQL is running and the storyteller database/user exist.