Imported from mcollovati/quarkus-hilla (
AGENTS.md). Install upstream withnpx skills add mcollovati/quarkus-hilla. Copyright stays with the author.
Quarkus-Hilla Development Guidelines
This document contains comprehensive guidelines for agentic coding agents working in the Quarkus-Hilla repository.
Build System & Commands
Maven Commands
# Build entire project
mvn clean install
# Run tests
mvn test
# Run single test class
mvn test -Dtest=ClassName
# Run single test method
mvn test -Dtest=ClassName#methodName
# Run integration tests
mvn verify -Pit-tests
# Skip tests during build
mvn clean install -DskipTests
# Run formatting
mvn spotless:apply -Pall-modules
# Check formatting
mvn spotless:check -Pall-modules
# Generate Jandex indexes
mvn jandex:index
Development Mode
# Run Quarkus dev mode
mvn quarkus:dev
# Run specific module in dev mode
cd module-name && mvn quarkus:dev
Native Image
# Build native image
mvn package -Pnative
# Run native tests
mvn verify -Pnative
Code Style Guidelines
Java Code Style
Formatting
- Tool: Spotless with Palantir Java Format
- Indentation: 4 spaces (no tabs)
- Line length: Under 120 characters
- Brace style: K&R (opening brace on same line)
- Imports: Explicit imports (no wildcards), organized by group
Import Order
jakarta.*importsjava.*andjavax.*imports- Third-party imports (alphabetical by package)
com.github.mcollovati.*imports (project-specific)- Static imports
Naming Conventions
- Classes: PascalCase (
EndpointController,MutinyEndpointSubscription) - Methods: camelCase (
serveEndpoint,getEndpointPrefix) - Variables: camelCase (
endpointName,formData) - Constants: UPPER_SNAKE_CASE (
DEFAULT_ENDPOINT_PREFIX,FEATURE) - Packages: lowercase with dots (
com.github.mcollovati.quarkus.hilla.deployment)
Annotation Usage
- Place annotations directly above declarations
- One annotation per line for multiple annotations
- Common annotations:
@BuildStep,@Record,@Inject,@Path,@Endpoint,@BrowserCallable,@AnonymousAllowed
Code Structure
@BrowserCallable
@AnonymousAllowed
public class HelloWorldService {
public String greet(String name) {
return "Hello, " + name + "!";
}
}
Error Handling
- Use checked exceptions in method signatures when appropriate
- Use runtime exceptions for programming errors (
IllegalArgumentException) - Include meaningful error messages
- Validate inputs at method entry points
TypeScript/React Code Style
Formatting
- Indentation: 2 spaces for frontend files
- Quotes: Single quotes for strings
- Semicolons: Required
- File extensions:
.ts,.tsxfor TypeScript/React
Import Order
// External libraries
import { Suspense, useEffect } from 'react';
import { AppLayout, DrawerToggle } from '@vaadin/react-components';
// Hilla-specific
import { createMenuItems, useViewConfig } from '@vaadin/hilla-file-router/runtime.js';
import { effect, signal } from '@vaadin/hilla-react-signals';
// Local imports
import { HelloWorldService } from 'Frontend/generated/endpoints.js';
import Placeholder from 'Frontend/components/placeholder/Placeholder';
Component Structure
export const config: ViewConfig = {
menu: { order: 0, icon: 'vaadin:globe' },
title: 'Hello Hilla',
};
export default function HelloWorldView() {
const name = useSignal('');
return (
<section className="flex p-m gap-m items-end">
<TextField
label="Your name"
onValueChanged={(e) => {
name.value = e.detail.value;
}}
/>
<Button onClick={async () => {
const serverResponse = await HelloWorldService.sayHello(name.value);
Notification.show(serverResponse);
}}>
Say hello
</Button>
</section>
);
}
File Naming
- Views: PascalCase with
Viewsuffix (HelloWorldView.tsx) - Layouts:
@layout.tsx,@index.tsx(prefix with @ for special routes) - Components: PascalCase (
Placeholder.tsx) - Utilities: camelCase (
auth.ts,routing.ts)
State Management
- Use Hilla signals:
useSignal('') - Access:
name.value, update:name.value = 'new' - Use React hooks when needed:
useState,useEffect
Testing Guidelines
Test Structure
@QuarkusTest
class EndpointTest extends AbstractTest {
@Test
void methodName_scenarioUnderTest() {
// Given - setup
// When - action
// Then - assertion
assertThat(result).isEqualTo(expected);
}
}
Test Naming
- Method names should describe the scenario:
invokeEndpoint_singleSimpleParameter() - Use Given-When-Then structure for complex tests
- Separate test classes for different concerns
Test Organization
- Unit tests:
src/test/java/ - Integration tests:
integration-tests/*/src/test/java/ - Base classes for common functionality:
AbstractTest - Test utilities in dedicated classes
Frontend Testing
- Use component testing patterns appropriate for React/Lit
- Test service integration with mock endpoints
- Verify routing and navigation
Package Structure
Runtime Packages
com.github.mcollovati.quarkus.hilla.runtime/
├── crud/ # CRUD operations
│ ├── spring/ # Spring Data integration
│ └── panache/ # Panache integration
├── graal/ # GraalVM native support
├── multipart/ # File upload handling
├── reload/ # Live reload functionality
└── security/ # Security components
Frontend Structure
src/main/frontend/
├── views/ # Page components
├── components/ # Reusable UI components
├── util/ # Utility functions
└── themes/ # Custom themes
Development Workflow
Before Committing
- Run formatting:
mvn spotless:apply -Pall-modules - Run tests:
mvn test - Check build:
mvn clean compile - Run integration tests:
mvn verify -Pit-tests
Making Changes
- Follow existing code patterns and naming conventions
- Add appropriate JavaDoc documentation
- Include tests for new functionality
- Update documentation if needed
- Verify formatting before committing
Agent Behavior Guidelines
File Deletion Policy
- ALWAYS ask for explicit confirmation before deleting any files
- Use
rm,git rm, or any deletion commands only after receiving explicit approval - Consider alternatives like moving files to backup locations when possible
- Provide clear information about what will be deleted before requesting approval
Endpoint Development
@BrowserCallable
@AnonymousAllowed // Add security constraints as needed
public class MyService {
public String method(String param) {
return result;
}
}
Configuration
- Use
@ConfigMappingfor type-safe configuration - Follow existing prefix patterns:
vaadin.hilla.* - Provide sensible defaults
Important Patterns
Null Safety
- Use
@NonNullApipackage annotations - Return
Optional<T>for nullable values - Validate null inputs in public methods
Reactive Programming
- Use Mutiny patterns:
Multi,Uni - Convert between reactive types appropriately
- Handle backpressure correctly
Error Responses
- Use appropriate HTTP status codes
- Include meaningful error messages
- Structure error responses consistently
Security
- Always apply security constraints to endpoints
- Use
@AnonymousAllowedonly for public endpoints - Validate user permissions in business logic
Module-Specific Notes
Quarkus Extension Development
- Use
@BuildStepfor build-time processing - Follow Quarkus extension patterns
- Implement proper feature detection
Frontend Development
- Use Vaadin components from
@vaadin/react-components - Follow Hilla routing patterns
- Implement proper loading states and error handling
Integration Tests
- Use abstract base classes for common setup
- Test both happy path and error scenarios
- Include native image testing when relevant
Documentation Requirements
JavaDoc
- Document all public classes and methods
- Include
@paramand@returntags - Provide usage examples for complex APIs
README Updates
- Update feature documentation
- Include configuration examples
- Document breaking changes
Docs Versioning & Maintenance
File layout:
README.md— feature/setup docs target the current major Vaadin/Hilla line only (today: 25.x), short, links out for depth. The Compatibility Matrix section is the one exception: it keeps every major's row (currently down to1.x) permanently — it's the single source of truth for version history, so it's never trimmed on a major bump. Seeetc/UpdateProjectVersion.javafor the automation that appends to it.docs/features.md— feature deep-dives for the current major.docs/configuration.md— the full Configuration Reference; the README's Configuration section only links its subsections. New config properties go here, not into the README.docs/vNN-docs.md(e.g.docs/v24-docs.md) — setup notes and workarounds for a retired major. Named after the version it documents, not "legacy". Does not duplicate the Compatibility Matrix rows — link toREADME.md#-compatibility-matrixinstead.docs/migration-vNN-to-vMM.md(e.g.docs/migration-v24-to-v25.md) — Quarkus-Hilla-specific upgrade steps between two majors. Link out to official Vaadin/Hilla docs for platform-level changes instead of duplicating them.
Version-tag rule (mirrors how Vaadin docs versioning works):
- Baseline = the oldest version of the current (most recent) major in the Compatibility Matrix (today: 25.0) — not the oldest row in the table overall, which is ancient history (
1.x) and irrelevant to tagging. - Tag a feature with
since X.Y(badge indocs/features.md,_(since X.Y)_in the README Feature Overview list) only if X.Y is newer than the baseline — i.e. not every install of the current major has it yet. - Feature shipped at or before the baseline → no tag, just describe it as a normal capability. A tag that only restates the baseline version is noise.
- When the baseline moves to a new major, tags older than the new baseline lose their tag — they're default now.
- The Quarkus column in the Compatibility Matrix can shift within a major (see the matrix's own note on Vaadin 25.0.9 raising the baseline from Quarkus 3.27 to 3.32) — don't assume it's constant across an entire major just because the Vaadin/Hilla version is.
When bumping the baseline to a new major (e.g. 25.x → 26.0):
- In
README.mdanddocs/features.md, dropsincetags for anything at or before the new baseline. - Create a new
docs/v25-docs.mddocumenting the outgoing major's (25.x) setup/workarounds — the existingdocs/v24-docs.mdstays untouched as the archive for 24.x-and-earlier. The Compatibility Matrix rows themselves stay inREADME.md; do not move them out. - Write
docs/migration-v25-to-v26.mdcovering Quarkus-Hilla-specific changes only (build plugin, config defaults, dependency changes). - Update the single
[!IMPORTANT]callout near the top ofREADME.mdand the Documentation list to point at the newvNN-docs.md/ migration doc. - Keep that top callout as the only prominent "on an older version?" pointer. Topical mentions elsewhere (e.g. Configuration Reference, Compatibility Matrix) may link to a specific anchor, but don't re-add generic duplicate call-outs — that's the clutter this structure replaced.
This file serves as the authoritative guide for development practices in the Quarkus-Hilla project. All agents should reference these guidelines when making changes to the codebase.