JTE templates for Basecoat components and Lucide icons.
Compatible with Basecoat 0.3.3.
This repository shows how to use Basecoat with:
- reusable JTE component templates in
src/main/jte/basecoat - generated Lucide icon templates in
src/main/jte/lucide - example usages in
src/main/jte/kitchenSink - toast partials in
src/main/jte/partials/toast
src/main/jte/basecoatJTE templates that mirror the original Basecoat Nunjucks macros.src/main/jte/lucideGenerated JTE templates for canonical Lucide icons.src/main/jte/kitchenSinkExample pages showing how to use the components and icons.src/main/jte/partials/toastSmall toast partials used by the kitchen sink examples.scripts/generate-lucide-jte.jsGenerates Lucide JTE templates from the installedlucidenpm package.
Each icon is a JTE template under src/main/jte/lucide.
Example:
@import java.util.Map
@template.lucide.bookOpen(attrs = Map.of("class", "size-4"))
@template.lucide.circleCheck(attrs = Map.of("aria-hidden", "true"))
@template.lucide.loaderCircle(
attrs = Map.of(
"class", "animate-spin",
"role", "status",
"aria-label", "Loading"
)
)Supported icon params:
sizecolorstrokeWidthabsoluteStrokeWidthattrs
attrs is the place for HTML attributes such as:
classrolearia-labelaria-hiddenfocusabledata-*
Important:
- for ARIA and
focusable, use string values like"true"and"false" - icon names are generated from canonical Lucide file names, not alias export names
Example:
circle-check->@template.lucide.circleCheck()circle-check-big->@template.lucide.circleCheckBig()
Reusable component templates live in src/main/jte/basecoat.
Current component templates include:
dialog.jtedropdownMenu.jtepopover.jteselect.jtetabs.jtetoast.jtetoaster.jte
Most of these templates support an attrs-style API through Map<?, ?> parameters for passing HTML attributes through to the rendered elements.
Example dialog usage:
@import java.util.Map
@template.basecoat.dialog(
id = "demo-dialog",
trigger = "Open dialog",
triggerAttrs = Map.of("class", "btn-outline"),
title = "Edit profile",
description = "Make changes to your profile here.",
content = @`
<form class="form grid gap-4">
<div class="grid gap-3">
<label for="name">Name</label>
<input id="name" type="text" value="Pedro Duarte" />
</div>
</form>
`,
footer = @`
<button type="button" class="btn-outline">Cancel</button>
<button type="button" class="btn">Save</button>
`
)Example dropdown usage:
@import java.util.Map
@template.basecoat.dropdownMenu(
id = "demo-dropdown",
triggerText = "Open",
triggerAttrs = Map.of("class", "btn-outline"),
popoverAttrs = Map.of("class", "min-w-56"),
content = @`
<div role="menuitem">Profile</div>
<div role="menuitem">Billing</div>
<hr role="separator">
<div role="menuitem">Log out</div>
`
)Example select usage:
@import java.util.List
@import java.util.Map
@import com.basecoatui.jte.util.BasecoatSelect.Item
@template.basecoat.select(
id = "fruit-select",
name = "fruit",
triggerAttrs = Map.of("class", "w-[180px]"),
selected = "blueberry",
items = List.of(
Item.of("Fruits", List.of(
Item.of("Apple", "apple"),
Item.of("Banana", "banana"),
Item.of("Blueberry", "blueberry")
))
)
)Example toast partials live in src/main/jte/partials/toast.
They are intended to be rendered into the toaster container, for example via htmx.
Example toaster:
@template.basecoat.toaster()Example toast partial usage:
@template.partials.toast.success()The kitchen sink examples under src/main/jte/kitchenSink are the best reference for how the JTE templates are meant to be used.
They show:
- direct Lucide icon usage
- Basecoat component template usage
- form/select/dropdown/tab/dialog patterns
- toast examples and partial rendering
From the repository root:
npm run generate:lucide-jteThe Spring Boot app serves the kitchen sink demo at /.
For local development, run Spring Boot and the webpack dev server in two terminals.
- Start the Spring Boot app on port
8080:
./mvnw spring-boot:run- Start the webpack dev server on port
8081:
npm install
npm run devserver- Open the demo in your browser:
http://localhost:8081
The webpack dev server proxies requests to the Spring Boot app on http://localhost:8080, while serving the frontend assets with live reload.
If you do not need the webpack dev server, you can also build the frontend assets once and run only Spring Boot:
npm install
npm run build
./mvnw spring-boot:runThen open:
http://localhost:8080
./mvnw -q -DskipTests compile- Lucide templates are generated from the installed
lucidepackage innode_modules - only canonical Lucide icons are generated, not duplicate alias exports
- generated icon names follow the icon file name, converted to lower camel case