skills/.system/jwebmp-core/SKILL.md
Strongly-typed HTML/CSS/JS component model for Java — the heart of JWebMP. Provides typed HTML elements, CSS builder, server-driven events, dual rendering (HTML/JSON), CRTP fluent API, and page configurators. Use when working with JWebMP Core features, HTML component creation, CSS styling, event handling, page configuration, or any JWebMP page/component development tasks.
npx skillsauth add guicedee/ai-rules jwebmp-coreInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Comprehensive guide for working with JWebMP Core — the strongly-typed HTML/CSS/JS component model for Java.
Every JWebMP component serves dual purposes:
toString(true) renders as HTML with all queued CSS/JStoString() renders as JSON for AJAX/API responsesJWebMP uses an 11-layer CRTP (Curiously Recurring Template Pattern) chain:
ComponentBase → ComponentHierarchyBase → ComponentHTMLBase →
ComponentHTMLAttributeBase → ComponentHTMLOptionsBase → ComponentStyleBase →
ComponentThemeBase → ComponentDataBindingBase → ComponentDependencyBase →
ComponentFeatureBase → ComponentEventBase → Component → Your subclass
Page<?> page = new Page<>();
Div<?, ?, ?> container = new Div<>();
container.add(new Paragraph<>().setText("Welcome to JWebMP"));
page.getBody().add(container);
String html = page.toString(true); // Full HTML
String json = page.toString(); // JSON representation
@PageConfiguration(url = "/")
public class HomePage extends Page<HomePage> {
public HomePage() {
getBody().add(new H1<>().setText("Hello from JWebMP"));
}
}
Register in module-info.java:
provides com.jwebmp.core.services.IPage with my.app.HomePage;
Events must be named classes (no lambdas/anonymous inner classes):
public class ButtonClickEvent extends OnClickAdapter {
public ButtonClickEvent(Component component) {
super(component);
}
@Override
public void onClick(AjaxCall<?> call, AjaxResponse<?> response) {
response.addComponent(new Paragraph<>().setText("Clicked!"));
}
}
// Attach to component
button.addEvent(new ButtonClickEvent(button));
Div<?, ?, ?> styled = new Div<>();
styled.getCss()
.getBackground().setBackgroundColor$(ColourNames.AliceBlue);
styled.getCss()
.getBorder().setBorderWidth(new MeasurementCSSImpl(1, MeasurementTypes.Pixels));
styled.getCss()
.getFont().setFontSize(new MeasurementCSSImpl(14, MeasurementTypes.Pixels));
Features must be named classes:
public class TooltipFeature extends Feature<TooltipOptions, TooltipFeature> {
public TooltipFeature(IComponentHierarchyBase<?, ?> component) {
super("tooltip", component);
getOptions().setPlacement("top");
}
@Override
protected void assignFunctionalityToComponent() {
addQuery(getComponent().asBase().getJQueryID() + "tooltip(" + getOptions() + ");");
}
}
All HTML5 elements available as typed classes:
Div, Span, Paragraph (flow content)H1–H6 (headings)Table, TableRow, TableHeaderCell, TableDataCellForm, Input* (22 typed input variants)Select, Option, OptionGroupList (ul/ol), ListItemLink, Image, ButtonHeader, Footer, Nav, Section, Article, AsideInputTextType, InputEmailType, InputNumberType, InputDateTypeInputFileType, InputCheckBoxType, InputRadioTypepublic class AnalyticsConfigurator implements IPageConfigurator<AnalyticsConfigurator> {
@Override
public IPage<?> configure(IPage<?> page) {
page.addJavaScriptReference(new JavascriptReference("analytics", 1.0, "analytics.js"));
return page;
}
@Override
public Integer sortOrder() {
return 500; // After core configurators
}
}
Register via module-info.java:
provides com.jwebmp.core.services.IPageConfigurator with my.app.AnalyticsConfigurator;
RenderBeforeLinks / RenderAfterLinks — CSS insertion pointsRenderBeforeScripts / RenderAfterScripts — Script insertion pointsRenderBeforeDynamicScripts / RenderAfterDynamicScripts — Dynamic script pointsOnClickAdapter, OnChangeAdapter, OnSubmitAdapterOnDragAdapter, OnDropAdapterOnKeyDownAdapter, OnKeyUpAdapter, OnKeyPressAdapterOnMouseEnterAdapter, OnMouseLeaveAdapterOnFocusAdapter, OnBlurAdapterEach event type has a corresponding ServiceLoader SPI:
IOnClickService, IOnChangeService, IOnSubmitService, etc.| Package | Properties |
|---|---|
| css.backgrounds | background-color, background-image, background-repeat |
| css.borders | border-width, border-style, border-color, border-radius |
| css.fonts | font-family, font-size, font-weight, font-style |
| css.margins | margin-top, margin-right, margin-bottom, margin-left |
| css.padding | padding-top, padding-right, padding-bottom, padding-left |
| css.displays | display, visibility, overflow, position, float |
| css.text | text-align, text-decoration, text-transform, line-height |
| css.heightwidth | height, width, min-height, max-width |
| css.measurement | MeasurementCSSImpl — px, em, rem, %, vw, vh |
module com.jwebmp.core {
requires transitive com.jwebmp.client;
requires transitive com.guicedee.client;
requires transitive com.guicedee.vertx;
requires transitive com.fasterxml.jackson.databind;
exports com.jwebmp.core;
exports com.jwebmp.core.base;
exports com.jwebmp.core.base.html;
exports com.jwebmp.core.base.html.inputs;
exports com.jwebmp.core.events.*;
exports com.jwebmp.core.htmlbuilder.css.*;
uses IPage;
uses IPageConfigurator;
uses IEventConfigurator;
}
Form<?, ?> form = new Form<>();
form.add(new Label<>().setText("Name:"));
form.add(new InputTextType<>().setName("name").setRequired(true));
form.add(new Label<>().setText("Email:"));
form.add(new InputEmailType<>().setName("email").setRequired(true));
form.add(new Button<>().setText("Submit"));
form.addEvent(new FormSubmitEvent(form));
Table<?, ?, ?, ?> table = new Table<>();
TableHeaderGroup<?, ?> header = new TableHeaderGroup<>();
TableRow<?, ?> headerRow = new TableRow<>();
headerRow.add(new TableHeaderCell<>().setText("Name"));
headerRow.add(new TableHeaderCell<>().setText("Email"));
header.add(headerRow);
table.add(header);
TableBodyGroup<?, ?> body = new TableBodyGroup<>();
for (User user : users) {
TableRow<?, ?> row = new TableRow<>();
row.add(new TableDataCell<>().setText(user.getName()));
row.add(new TableDataCell<>().setText(user.getEmail()));
body.add(row);
}
table.add(body);
public class AjaxHandler extends OnClickAdapter {
@Override
public void onClick(AjaxCall<?> call, AjaxResponse<?> response) {
// Access request data
String param = call.getParameters().get("key");
// Modify DOM
response.addComponent(new Div<>().setText("New content"));
// Add reactions
response.addReaction(new AjaxResponseReaction<>(ReactionType.REDIRECT, "/newpage"));
}
}
<dependency>
<groupId>com.jwebmp.core</groupId>
<artifactId>core</artifactId>
</dependency>
Version managed by JWebMP BOM.
Page — Top-level HTML pageComponent — Base for all HTML elementsFeature — Wraps JS library with typed optionsEvent — Server-driven event handlerCSSComponent — CSS-only component (no HTML tag)DataAdapter — Bridges server data to JSONContentSecurityPolicy — CSP header buildercom.jwebmp.coredevelopment
Install Codex skills into $CODEX_HOME/skills from a curated list or a GitHub repo path. Use when a user asks to list installable skills, install a curated skill, or install a skill from another repo (including private repos).
tools
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Codex's capabilities with specialized knowledge, workflows, or tool integrations.
development
WebAwesome icon integration for JWebMP — modern, open-source icon library. Provides 1,500+ icons with solid/regular styles, sizing, rotation, animation, and CSS utilities. Drop-in FontAwesome alternative with fresh designs. Use when working with WebAwesome icons, modern icon designs, or as FontAwesome alternative in JWebMP applications.
development
WebAwesome Pro integration for JWebMP with premium icons and features. Extends jwebmp-webawesome with additional styles, premium icons, and advanced features. Use when working with WebAwesome Pro icons or premium WebAwesome features in JWebMP applications.