Fluent, dual API
Use Oat.Components for self-contained widgets, or apply
Oat.Behaviors to any existing Wicket component —
composition over inheritance, your choice per case.
Apache Wicket × Oat UI
A modern, themeable component library for Apache Wicket — built on Oat's ultra-lightweight, semantic CSS and JS. No utility-class soup, no client framework, just Wicket the way you already write it.
Why Wicket Oat
Wicket Oat wraps Oat's semantic HTML/CSS/JS in idiomatic Wicket
Components and Behaviors, so you get a current, themeable
UI without leaving Wicket's component model.
Use Oat.Components for self-contained widgets, or apply
Oat.Behaviors to any existing Wicket component —
composition over inheritance, your choice per case.
Oat styles real HTML elements by default. ~10KB of CSS and JS total, no build step, no bundler, no utility-class soup in your markup.
17 built-in themes, remembered per user in a cookie, plus your own themes registered in one line — full CSS custom-property theming to match your brand.
Every component is an ordinary WebMarkupContainer, Panel,
or Behavior subclass — test it with WicketTester
like anything else in your app.
Every form field automatically wires aria-describedby to its feedback
message, toggles aria-invalid on validation errors and marks
required fields — no extra markup or wiring required.
Fields take their model from a CompoundPropertyModel and their label
from .properties, by id. Validation errors show inline, and
feedback panels and toasts update themselves over Ajax.
Works under Wicket's default nonce-based Content Security Policy: no inline
scripts or styles, no 'unsafe-inline', no 'unsafe-eval'.
Get Started
<dependency>
<groupId>dev.jbaby</groupId>
<artifactId>wicket-oat-core</artifactId>
<version>0.1.1</version>
</dependency>
public class MyWicketApplication extends WebApplication {
@Override
protected void init() {
super.init();
WicketOats.install(this); // adds Oat's CSS/JS; returns OatSettings for themes
}
}
add(Oat.Components.button("save", "Save changes", target ->
Oat.toast(target, "Saved!", OatVariant.SUCCESS)));
add(Oat.Components.alert("notice", "Welcome back!", OatVariant.SUCCESS));
<a wicket:id="save"></a>
<div wicket:id="notice"></div>
Prefer plain Wicket constructors? Components like
OatAlert, OatBadge, OatCard and the
form fields work the same way with new — the factory is
mainly there for components like OatButton that need a callback
and would otherwise require subclassing:
add(new OatAlert("notice", "Welcome back!", OatVariant.SUCCESS));
Want the full walkthrough? See the Build a Contact Form tutorial.
The Application Frame
Most business applications share the same shell: a collapsible sidebar for
navigation, a top bar for identity and actions, and a content area in between.
OatAppLayout is a WebPage base class that gives you
exactly that, backed by Oat's data-sidebar-layout CSS grid —
no layout CSS to write yourself.
Extend OatAppLayout (or the ready-made BasePage
pattern shown here) and override a handful of hook methods. The sidebar
collapses to an off-canvas panel under 768px automatically, toggled by the
☰ button — no extra JavaScript required, it's wired
into Oat's vendored JS already.
public class BasePage extends OatAppLayout {
@Override
protected IModel<String> appNameModel() {
return Model.of("My Business App");
}
@Override
protected IModel<List<MenuItem>> sidebarMenuItemsModel() {
return Model.ofList(List.of(
MenuItem.of("Dashboard", DashboardPage.class),
MenuItem.of("Customers", CustomersPage.class)
));
}
@Override
protected Component createFooter(String id) {
// Any component works here - the built-in switcher is one option
return new OatThemeSwitcher(id);
}
}
Pages then simply extend BasePage and add their own content
— the sidebar, top bar, active-link highlighting, responsive behavior and
the user's theme are already handled. Bookmarkable pages pass their
PageParameters to super(...); menu items can carry
parameters and translatable labels, and items for pages the user isn't
authorized to open are left out.
Your page content renders here, inside <wicket:child/>.
Sample widget content…
Live demo — try the ☰ toggle, and resize your window.
Component Showcase
Not screenshots — this page loads the same Oat 0.8.1 build the library vendors, so what you see here is exactly what renders in your app.
Any HTML can live inside.
A themeable component library for Apache Wicket, built on Oat.
Manage your account here.
Change your password here.
| Name | Status |
|---|---|
| Invoice #1042 | Paid |
| Invoice #1043 | Due |
Theming
Click a theme below to preview it live on this entire page — the same
data-theme mechanism OatThemeSwitcher uses in your app,
where the user's choice is remembered in a cookie (and works with any session
class).
// Switch the current user's theme (kept in a cookie)
OatTheme.setCurrent(OatTheme.NORD);
// In init(): the default theme, and your own themes defined in CSS
WicketOats.install(this)
.setDefaultTheme(OatTheme.LIGHT) // or null to follow the browser
.addTheme(new OatTheme("brand", "Brand", "🏷️"));
// Pin one component to a theme, whatever the user chose
card.add(Oat.Behaviors.theme(OatTheme.LIGHT));
AI-Powered Development
Wicket Oat ships a standard Agent Skill
— a plain SKILL.md plus a references/ folder — giving the agent
deep knowledge of the Oat API, component library, and theming system. It works with any tool that
supports this directory-based skill convention.
It lives in the repo at wicket-oat/
(SKILL.md + references/).
Copy it into your agent's own skills folder — for example, with Claude Code:
cp -r wicket-oat .claude/skills/wicket-oat
Check your agent's own documentation for how it discovers or loads skills.
Once installed, try: “Add a primary Oat button that shows a success toast on click.” or “Turn this standard Wicket Label into an Oat success badge.”