- 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.
4.6 KiB
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/
- Java interfaces/models:
Local Setup
- Prerequisites: JDK 21, Maven 3.9+, PostgreSQL, Node.js 22 (managed by frontend-maven-plugin).
- Database: Create a PostgreSQL database:
CREATE DATABASE storyteller; CREATE USER storyteller WITH PASSWORD 'storyteller'; GRANT ALL PRIVILEGES ON DATABASE storyteller TO storyteller; - Build everything:
mvn package(generates API code, compiles Java, builds frontend, runs tests). - Run in dev mode:
mvn quarkus:dev(hot reload, frontend proxy at http://localhost:5173). - Frontend dev:
cd src/main/web && npm run dev(standalone Vite dev server, proxies/apito 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/orsrc/main/web/src/api/generated/. - To change the API:
- Edit
src/main/resources/openapi/story-teller-api.yaml. - Run
mvn generate-sourcesto regenerate Java and TypeScript. - Update service/resource implementations to match new interfaces.
- Edit
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
- Client sends
POST /api/auth/loginwith username/password. - Server verifies credentials, returns signed JWT with user claims.
- Client stores JWT in localStorage and sends it as
Authorization: Bearer <token>on all subsequent requests. - Quarkus SmallRye JWT validates the token on protected endpoints.
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:
- Client sends a direction prompt.
- Server estimates context size (scene + characters + unmerged steps + direction).
- If it exceeds the limit (~12K chars), the oldest half of unmerged steps are compacted into the scene description.
- Steps are marked
addedToScene = trueafter compaction. - The AI generates the next step from the (possibly compacted) context.
- The response includes a
compactedflag 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.pemandpublicKey.pemexist insrc/main/resources/. - Generated code issues: Run
mvn clean generate-sourcesto rebuild from scratch. - TypeScript errors: Check that
src/main/web/node_modulesexists; runnpm installinsrc/main/web. - DB connection: Verify PostgreSQL is running and the
storytellerdatabase/user exist.