Quarkus is an exciting framework for building modern Java applications, and Quinoa takes it up a notch by streamlining Single Page Application (SPA) development. Together, they enable a seamless workflow for both frontend and backend developers. This guide walks through setting up a Quarkus-based SPA using React as an example, although the process works just as well for other frameworks.


Why Quinoa Matters

Quinoa elegantly integrates frontend development into Quarkus projects. Here’s why you should care:

  • Unified Development:* Host your frontend and backend together during development.
  • Automation:* Automatically build and serve your frontend as part of the Quarkus lifecycle.
  • Streamlined APIs:* Simplify API calls with relative URLs.

Structuring Your Project

To keep things organized, place your frontend project as a submodule within the Quarkus project. Here’s a suggested structure:

Quarkus-Structure
|- src
|  |- main
|  |- docker
|  |- resources
|  |- webui (frontend project, must be named "webui")

Why Submodules?

  • Separation of Concerns: Clear division between frontend and backend responsibilities.
  • Independent Version Control: Manage the two projects separately.

Setting Up Quinoa in Quarkus

Step 1: Update Configuration

Add the following to application.properties in the resources directory:

quarkus.http.cors.origins=http://localhost
quarkus.http.cors=true
quarkus.quinoa.dev-server.port=3000
quarkus.quinoa.build-dir=dist
quarkus.quinoa.enable-spa-routing=true

Important Notes:*

  • quarkus.quinoa.build-dir: Specifies the directory containing the built frontend files (e.g., dist for React), it should be the folder generated by npm run build.
  • quarkus.http.cors: Enables CORS for smoother API interactions during development.
  • quarkus.quinoa.enable-spa-routing: Fixes the SPA routing issue for Quarkus (see github issue for details)

Adjust build-dir based on your frontend framework’s output directory.

Step 2: Add Dependency

In your pom.xml, include:

<dependency>
    <groupId>io.quarkiverse.quinoa</groupId>
    <artifactId>quarkus-quinoa</artifactId>
    <version>{latest-version}</version>
</dependency>

Developing with Quinoa

Seamless Integration

Once configured, running quarkus dev or quarkus build will:

  • Detect your frontend project via its package.json.
  • Build and serve the frontend automatically.

Simplified API Calls

Use relative URLs (e.g., /api/1.0/create) instead of absolute ones (e.g., http://localhost:8080/api/1.0/create). Quinoa handles the routing, ensuring that requests reach the backend effortlessly.


Preparing for Production

Building Executables

  1. Create a Fat JAR:

bash    quarkus build --no-tests   

  1. Optional: Build a Native Executable:*

bash    quarkus build --native --no-tests   

Native executables eliminate the need for a Java runtime, offering faster startup and lower memory usage. But it usually takes some time for graalvm to support the latest version of java.

Multi-Platform Docker Images

To build a Docker image compatible with Linux and macOS:

  1. Enable containerd in Docker settings (How to).
  2. Run the following command in the project root:

bash docker build --platform linux/amd64,linux/arm64 -f src/main/docker/Dockerfile.jvm -t quarkus/your-project:latest .   

This image can run on diverse environments, including Apple Silicon.


Wrapping Up

Quarkus and Quinoa together redefine SPA development by combining frontend and backend workflows into a cohesive experience. With minimal setup, you can create, test, and deploy modern web applications efficiently. Whether you’re working on a personal project or deploying at scale, this combination simplifies your life.

For further exploration, dive into the official Quarkus documentation or the React and Quarkus guide.