Skip to content

yuokada/quarkus-react-todo-app

Repository files navigation

Quarkus React Todo App

This project combines a Quarkus REST backend with a Vite/React Todo UI using the Quarkiverse Quinoa extension. Redis is used as a lightweight data store backing the Todo API.

Architecture at a Glance

  • Backend: Quarkus 3 + RESTEasy Reactive + Quarkus Redis Client. The Java code is organized into domain, application, infrastructure, and presentation packages under src/main/java/io/github/yuokada/practice.
  • Frontend: React (Vite) with the main logic in src/main/webui/src/App.jsx.
  • Storage: Redis (DevServices or redis://localhost:6379/0). Tasks are stored as the TodoTask record.
  • Quinoa: Bridges Quarkus and the Vite app. In dev mode it proxies the Vite dev server; in prod it serves the built dist/index.html and assets.

Package Structure

The backend now follows a simple Clean Architecture-style package split.

  • io.github.yuokada.practice.domain.model Holds business data types such as TodoTask, Status, and Increment. These classes do not depend on Quarkus or Redis APIs.
  • io.github.yuokada.practice.domain.repository Defines repository interfaces used by the application layer, such as TodoRepository, TodoAsyncRepository, and IncrementRepository.
  • io.github.yuokada.practice.application.service Contains use-case services like TodoService, TodoAsyncService, and IncrementService. These services depend on repository interfaces, not on Redis-specific implementations.
  • io.github.yuokada.practice.infrastructure.redis Contains Redis-backed implementations such as RedisTodoRepository, RedisTodoAsyncRepository, and RedisIncrementRepository. Quarkus Redis datasource access is isolated here.
  • io.github.yuokada.practice.infrastructure.dynamodb Contains DynamoDB-backed implementations such as DynamoDbTodoRepository, DynamoDbTodoAsyncRepository, DynamoDbIncrementRepository, and DynamoDbClientProducer. AWS SDK v2 access is isolated here.
  • io.github.yuokada.practice.presentation.rest Contains JAX-RS resource interfaces and implementations such as TodoResourceImpl, TodoAsyncResourceImpl, and IncrementResource. This layer maps HTTP requests and responses to application services.

Dependency direction:

  • presentation -> application -> domain
  • infrastructure -> domain

In practice, this means REST resources do not talk to Redis directly, and application services do not import Quarkus Redis APIs.

Common Commands

Purpose Command Notes
Backend + frontend live coding ./mvnw compile quarkus:dev Launches Quarkus dev mode and Quinoa-managed Vite dev server at http://localhost:8080. Dev UI at /q/dev.
Backend tests ./mvnw test Uses Redis DevServices or local Redis depending on config.
Package JAR ./mvnw package Artifacts end up in target/quarkus-app/.
Native build ./mvnw package -Pnative Add -Dquarkus.native.container-build=true to build via container.
Start local Valkey docker compose up valkey -d Exposes Valkey on localhost:6379 for local dev.
Start DynamoDB Local docker compose up dynamodb-local -d Exposes DynamoDB Local on localhost:8000.
Init DynamoDB tables ./scripts/init-dynamodb.sh Creates todo_tasks and app_counters tables. Requires AWS CLI.
Frontend lint/check cd src/main/webui && npm run biome:check Runs Biome without modifying files.
Frontend dev only cd src/main/webui && npm run dev Runs Vite standalone (default port 5173).
Frontend build cd src/main/webui && npm run build Updates Quinoa’s source dist/ folder.
Build container image (Jib) ./mvnw package -Dquarkus.container-image.build=true Produces an OCI image via Jib; append -Dquarkus.container-image.push=true to push.

Toolchain:

  • Java: Temurin 25
  • Node.js: 24.14.0

Quinoa Configuration

src/main/resources/application.properties contains:

quarkus.quinoa.dev-server-port=5173
quarkus.quinoa.build-dir=dist
quarkus.quinoa.index-page=index.html
quarkus.quinoa.enable-spa-routing=true

This mimics the setup recommended in the Advanced Guides. Dev mode proxies Vite, while prod serves the generated dist/index.html and falls back to it for SPA routing.

REST API Summary

Base URL: http://localhost:8080/api/todos

Method Path Description
GET / Fetch all tasks
GET /{id} Fetch a single task
POST / Create a task ({"title":"...", "completed":false})
PUT /{id} Update title/completed
DELETE /{id} Delete a task (404 when missing)

Additional async endpoints (/api/async/todos) and increment examples are exposed from the presentation layer. OpenAPI definitions are emitted into openapi-definition/.

see also: http://localhost:8080/q/swagger-ui/

Frontend Highlights

  • App.jsx implements list rendering, creation form, completion toggles, and deletion, all backed by fetch calls to /api/todos.
  • App.css provides a lightweight card-style layout with responsive tweaks.
  • Error/loading states feed back to the UI via status messages.

Backend Selection

The backend storage can be switched at runtime via app.repository.type in application.properties.

Value Backend
redis Valkey/Redis
dynamodb (default) DynamoDB (or DynamoDB Local)

To use DynamoDB Local in dev mode:

%dev.app.repository.type=dynamodb
%dev.app.dynamodb.endpoint-override=http://localhost:8000

Steps:

  1. docker compose up dynamodb-local -d
  2. ./scripts/init-dynamodb.sh
  3. ./mvnw compile quarkus:dev

Redis Usage

  • DevServices: Leaving %dev.quarkus.redis.hosts commented lets Quarkus start Redis automatically in dev/test.
  • Local Redis: Set %dev.quarkus.redis.hosts=redis://localhost:6379/0 to reuse an existing instance.
  • Docker Compose: docker compose up -d starts the local Valkey container defined in compose.yaml; stop it with docker compose down.
  • Seed scripts (users.redis, test-task.redis) help bootstrap data when needed.

Testing

  • Tests live under src/test/java/... and rely on Quarkus JUnit5 + RestAssured.
  • %test.quarkus.redis.load-script=test-task.redis loads fixtures for deterministic results.

Container Image (Jib)

  • The dependency quarkus-container-image-jib is included and configured via application.properties.
  • Default image coordinates: io.github.yuokada.practice/quarkus-react-todo-app:latest-jib.
  • Build locally: ./mvnw package -Dquarkus.container-image.build=true
  • Push to a registry: ./mvnw package -Dquarkus.container-image.build=true -Dquarkus.container-image.push=true
  • Override registry/name/tag as needed with quarkus.container-image.* properties or system properties (see Quarkus container image guide).

Related Guides

Live code the backend and frontend together with minimal configuration—Quinoa proxies the framework dev server during development and serves the generated assets in production.

Provided Code

Quinoa

This project uses Quinoa to wire a Vite/React frontend into the Quarkus application lifecycle.

Related guide section...

React + Vite

RESTEasy Reactive

Easily start your Reactive RESTful Web Services

Related guide section...

Redis

For more contributor-oriented details (naming, linting, etc.), see AGENTS.md.

About

Sample application using quarkus-quinoa extension

Topics

Resources

Stars

Watchers

Forks

Contributors