Skip to content

Quasar example: executable experimental frontend

Experimental example

Experimental · Java 21 · Maven 3.9+

The Quasar facility and its generated frontend contract can change between releases. Evaluate the generated output and frontend dependencies before using them in a production application.

The canonical example-ux-quasar module combines a generated Spring Boot API, an in-memory H2 database and a generated Quasar page with a small manual application shell. It is intentionally separate from the stable Spring Boot example and uses only the public spring-boot and ux-quasar facilities.

The source is in the example-ux-quasar directory of the public JoinedWorkz examples repository.

1. Modules and data flow

The example contains three Maven modules:

  • model owns the CMN models, joinedworkz.properties and outlet routing;
  • backend-spring combines generated Java and OpenAPI output with the manual Spring Boot bootstrap, H2 configuration and runtime test; and
  • frontend-quasar combines generated pages, routes and the application store with the manual Quasar/Vue shell.

At development time the Quasar server sends /api requests to the Spring Boot backend. The backend stores records only in memory, so the example needs neither Docker nor an external database.

2. Generate and build

From the example directory, run:

bash
mvn clean verify -Dgpg.skip=true

The build:

  1. removes and regenerates both replaceable source trees;
  2. compiles the generated Spring Boot API;
  3. runs the H2-backed API test;
  4. installs Node 22.22.2 in the frontend module;
  5. runs npm ci against the committed public lockfile; and
  6. creates the Quasar production build.

The committed application shell uses Quasar 2.23.4, @quasar/app-vite 2.4.1, Vite 7.3.6 and sass-embedded 1.97.3. These versions and the lockfile form one tested frontend toolchain.

For a direct frontend build, use Node 22.22.2, also recorded in .nvmrc:

bash
cd frontend-quasar
npm ci
npm run build

3. Model and custom component

The UX component selects the public experimental Quasar platform, adds the generated route and uses the backend component:

cmn
package org.joinedworkz.examples.quasar.frontend

import org.joinedworkz.examples.quasar.api
import org.joinedworkz.examples.quasar.backend
import org.joinedworkz.examples.quasar.widgets
import org.joinedworkz.facilities.ux.quasar

platform Quasar

component<ux> WorkspaceFrontend uses WorkspaceBackend {
    route /workspaces WorkspaceListPage

    page WorkspaceListPage {
        use workspaces: /api/workspaces.queryEntities()
        content {
            Container {
                WorkspaceCards with workspaces
            }
        }
    }
}

WorkspaceCards is declared in a separate imported widget model. That model imports the Quasar profile so componentRef can be linked, but it deliberately does not select a platform:

cmn
package org.joinedworkz.examples.quasar.widgets

import org.joinedworkz.facilities.ux.quasar

widget WorkspaceCards componentRef='components/widgets.WorkspaceCards' {
    property items: Any[] defaultBinding=true
}

The reference resolves to the manually maintained src/components/widgets/WorkspaceCards.vue. This demonstrates how a reusable widget definition can stay independent of the platform selected by the model that consumes it.

4. Generated output and manual shell

These Git-ignored directories are fully replaceable:

text
backend-spring/src/generated/
frontend-quasar/src/generated/

The frontend generator creates the WorkspaceListPage, route fragment and Pinia application store. The manual shell remains outside the generated tree and owns:

  • package.json, the lockfile and Quasar configuration;
  • App.vue, the layout and Vue Router bootstrap;
  • composition of the generated route fragment;
  • consumption of the generated main-menu data;
  • request and pagination helpers; and
  • the WorkspaceCards Vue component.

Deleting the generated directories and running the model module recreates all replaceable output without changing the shell:

bash
mvn -pl model clean generate-sources

5. Run the application

Start the backend from the example root:

bash
mvn -pl backend-spring spring-boot:run

Start the frontend in a second terminal:

bash
cd frontend-quasar
npm ci
npm run dev

Open http://localhost:9000/workspaces. Both servers bind to the local loopback interface, and the frontend proxies /api to http://127.0.0.1:8080.

Create a short-lived H2 record through that proxy:

bash
curl -X POST http://localhost:9000/api/workspaces \
  -H 'Content-Type: application/json' \
  -d '{"name":"Example workspace","description":"Created through the proxy"}'

The omitted ID is intentional: the example's backend model selects the SpringBoot CUSTOM strategy. Its application-side lifecycle is documented in SpringBoot ID generation strategies; the Quasar facility and this combined frontend example remain experimental.

Reload the page to render the record through the generated query and the manual WorkspaceCards component.

6. Reproduce the checks

After the Maven build, the runtime script starts both servers on isolated loopback ports and checks the /api proxy and generated API:

bash
./verify-runtime.sh

The complete reproducibility check additionally proves that regeneration does not modify manual sources, the npm lockfile uses no local or private registry, and an invalid componentRef reports quasar.invalidComponentRef before the parent page is emitted:

bash
./verify-example.sh

7. Boundaries

  • Quasar support and this frontend example are experimental.
  • The generated frontend is an application fragment, not a complete shell.
  • H2 is a low-prerequisite example database, not a production recommendation.
  • The backend JAR and Quasar SPA are separate artifacts. The example does not claim Spring Boot resource serving, SPA fallback or deep-link reload from a combined JAR.

For the detailed generator and modeling contract, see the Quasar facility.