name: codename-one
description: Build and modify Codename One cross-platform mobile apps (Java 17, Maven, ParparVM/Android/iOS/JavaScript). Use when the project contains a common/codenameone_settings.properties, depends on com.codenameone:codenameone-core, edits CSS files under common/src/main/css/, calls cn1:run, cn1:test, cn1:build, references com.codename1.ui.* / com.codename1.testing.*, or when the user asks to build a UI, write screen tests, generate screenshots, or compare to Swing/HTML.
metadata:
type: skill
Codename One — App and UI Authoring Skill
This skill teaches you how to write code for a Codename One (CN1) cross-platform mobile project. Codename One compiles Java/Kotlin bytecode to native iOS, Android, desktop and web. It looks like Java AWT/Swing, behaves like a mobile UI toolkit, and styles with a subset of CSS.
Use this skill when:
- A file you are editing imports
com.codename1.ui.*,com.codename1.io.*,com.codename1.testing.*, or extendscom.codename1.system.Lifecycle. - You are editing a file in
common/src/main/css/(CN1 CSS). - You are running
cn1:run,cn1:debug,cn1:test, orcn1:buildMaven goals. - The user asks for a UI screen, a screenshot test, a responsive layout, or wants to convert a Swing/HTML snippet to CN1.
How this skill is organized
SKILL.md (this file) is the top-level cheat sheet. Deeper reference material lives under references/ — pull the relevant file in only when you need it:
references/build-and-run.md— Local vs cloud builds, JDK matrix, Maven goals,codenameone_settings.properties, running the simulator, building for iOS/Android/Web, automated (Enterprise) cloud builds in CI.references/build-hints.md— Curated index ofcodename1.arg.*build hints (iOS, Android, push, web).references/java-api-subset.md— How to inspect the supported Java API subset, IO (Storage,FileSystemStorage), networking (ConnectionRequest,Rest), OAuth/OpenID Connect (OidcClient), WebSockets (cn1lib), concurrency, dates, SQLite. Read this whenever the compliance check fails or when you reach for ajava.*API.references/api-clients.md— The three "spec to typed client" code generators that share one architecture: REST/OpenAPI (cn1:generate-openapi+@RestClient), gRPC (cn1:generate-grpc+@GrpcClient), and GraphQL (cn1:generate-graphql+@GraphQLClient). Read this when the backend has an OpenAPI spec, a.proto, or a GraphQL schema and you want a generated, annotated client instead of hand-rolling calls.references/ui-components.md— Form, Toolbar, Container layouts (Border/Box/Flow/Grid/Layered), common components, navigation, dialogs.references/binding-and-validation.md—@Bindable/@Bindannotation binding and annotation-driven validation (@Required,@Length,@Regex,@Email,@Url,@Numeric,@ExistIn,@Validate). Read this whenever you see one of those annotations, wire a model to a form, or need to gate a submit button on validation.references/css.md— CSS capabilities and (important) limitations. Selectors, supported properties, 9-patch borders, theme constants, and the build-time vector transcoder that compiles SVG and Lottie / Bodymovin JSON referenced viaurl(...)intoGeneratedSVGImagesubclasses.references/swing-comparison.md— Mapping Swing concepts and code to Codename One. Read this when porting Swing code.references/html-css-cheatsheet.md— Converting common HTML/CSS snippets to CN1 components + CSS.references/android-to-cn1.md— Porting Android (XML + Kotlin/Java) screens to Codename One.references/react-to-cn1.md— Bringing a React / JSX + CSS design (e.g. a Claude-generated bundle:*.jsx+tokens.css+styles.css) into Codename One: the component/hook/CSS mapping, thetokens.css->theme.csstoken workflow, dark-mode re-skinning, and the render-on-desktop-then-inspect loop. Read this when the user hands you a React/HTML design to rebuild in CN1.references/testing-and-screenshots.md—AbstractTest,TestUtils,screenshotTest, thecn1:testMaven goal, the screenshot tolerance algorithm.references/mockup-comparison.md— Building a screen to match a designer mockup:tools/CompareToMockup.javascores a render against a mockup image and prints a similarity % (with partial/region masking so device chrome doesn't sabotage the score), andtools/DesignImport.javaturns a Figma/Sketch/Adobe XD file or an HTML/React design'stokens.css/styles.css(e.g. a Claude-generated mockup) into a startertheme.css+ tokens + layout map. Read this when the user gives you a mockup, a Figma/Sketch/XD file, an HTML/CSS design bundle, or asks "how close is this screen to the design".references/junit-testing.md— Standard JUnit 5 tests against the simulator via@CodenameOneTest. Annotations (@RunOnEdt,@Theme,@DarkMode,@LargerText,@Orientation,@RTL,@SimulatorProperty), how it coexists withcn1:test, and why a headless CI runner has to be configured with Xvfb (or accepts that JUnit test classes will be skipped).references/mobile-adaptability.md— Density-independent units (mm),convertToPixels,LayeredLayoutfor responsive design,Display.isTablet(), font scaling.references/native-interfaces.md— Authoring native interfaces for iOS/Android/JavaScript/Desktop withcn1:generate-native-interfacesand platform callbacks.references/cn1libs.md— Creating, packaging, and consuming Codename One libraries (Maven and legacy.cn1lib).references/ai-and-speech.md— LLM client (com.codename1.ai),ChatView,SpeechRecognizer,TextToSpeech, non-promptingSecureStorageoverloads, the ML Kit cn1libs, and the simulator's offline Ollama redirect. Read this when the user asks for chat, voice, embeddings, image generation, barcode/document/face detection, or wants to store an LLM API key.references/printing.md— Cross-platform printing (com.codename1.printing):Printer.printPDF/printImage/print, thePrintResultoutcome, and per-platform caveats (iOS AirPrint, Android, desktop, native Windows, web). Read this when the user wants to print a document, report, image, or the current screen.references/games.md— Game development (com.codename1.gaming): theGameViewupdate loop,Sprite/AnimatedSprite/SpriteSheet, pollableGameInput,TouchControls,SoundPool, and 2Dcom.codename1.gaming.physics(Box2D). Read this for arcade/casual/scroller/board games or any real-time animated canvas.references/3d-graphics.md— Portable GPU 3D (com.codename1.gpu): theRenderView+Rendererloop, declarativeMaterial/VertexFormat(engine-generated shaders — no GLSL),Primitives,GltfLoaderfor glTF models,Camera/Light/Matrix4, and platform backends. Read this for product viewers, 3D scenes, or custom GPU rendering.references/snapshot-builds.md— Edge case: compiling against a Codename One SNAPSHOT from git.references/debugging.md—jdb-attach workflow for an agent: start the simulator paused, set breakpoints, dump locals, drive the session non-interactively from a script.tools/— runnable Java 17 single-file utilities.tools/IsApiSupported.javaanswers "is thisjava.*class in the CN1 subset?";tools/IsCssValid.javaanswers "does thistheme.csscompile?";tools/CompareToMockup.javascores a rendered screenshot against a designer mockup (similarity %, with region masking);tools/DesignImport.javaturns a Figma/Sketch/Adobe XD design — or an HTML/React design'stokens.css/styles.css(Claude-generated mockups) — into starter CN1 CSS + tokens + a layout map.tools/DumpForm.javaboots the app in desktop mode and dumps a model of the current screen, whichtools/DescribeForm.java(vision-free outline),tools/AlignmentCheck.java(designer alignment guides) andtools/GuiLint.java(nested scroll, opaque text/containers, image borders) analyse.tools/UpdateSkills.javaself-updates this whole skill from GitHub. Run withjava tools/<Name>.java <args>.
When the user's task hits any one of those topics, read the matching reference before generating code. Do not paste large snippets without checking.
Project layout (multi-module Maven)
A CN1 project generated by the initializr has these modules:
my-app/
├── pom.xml # Aggregator. cn1.plugin.version + cn1.version pinned here.
├── common/ # Cross-platform Java/Kotlin source. THIS IS WHERE THE APP LIVES.
│ ├── pom.xml # <source>17</source> <target>17</target> by default
│ ├── codenameone_settings.properties
│ └── src/main/
│ ├── java/<pkg>/<MainClass>.java
│ ├── css/theme.css # CN1 CSS (NOT regular web CSS - see references/css.md)
│ ├── l10n/ # i18n bundles (NOT src/main/resources!)
│ └── guibuilder/ # Optional GUI builder XML
├── javase/ # Desktop simulator port
├── android/ # Android wrapper (built via build server or local Gradle)
├── ios/ # iOS wrapper (ParparVM)
└── javascript/ # TeaVM-based web port
Only edit common/. The platform modules are thin wrappers — touching them is almost always wrong unless you are intentionally writing a native interface.
Java version and language features
This project targets Java 17 (<source>17</source> / <target>17</target> in common/pom.xml, plus codename1.arg.java.version=17 in codenameone_settings.properties). Use:
varfor local variable type inference- Text blocks (
"""...""") - Records
- Pattern matching for
instanceof switchexpressions- Lambdas, method references,
Streams
Caveat — the build server cross-compiles to bytecode that ParparVM/TeaVM can consume. Codename One ships a curated subset of the JDK, not the full java.* namespace. The cn1:bytecode-compliance Maven goal runs on every compile and fails the build if you call an unsupported API. The most common gotchas:
- No
java.nio.file.*— usecom.codename1.io.FileSystemStorageandStorage. - No
java.net.http.*/java.net.URLConnection— usecom.codename1.io.rest.Rest(preferred) orConnectionRequest. - No
java.util.concurrent.locks.*beyond simplesynchronized— useDisplay.getInstance().callSerially(...)orDisplay.startThread(...). - No
java.awt.*/javax.swing.*— CN1 has its own UI stack. Seereferences/swing-comparison.md. - No
java.lang.reflect.*on production builds — works in the simulator only. - No threads spawned with
new Thread(...).start()for UI work — always go throughDisplay.callSeriallyorDisplay.startThread(...).
For the authoritative subset list and IO/networking patterns, read references/java-api-subset.md (which also shows how to grep the java-runtime jar to verify any specific class/method).
The Event Dispatch Thread (EDT)
CN1 has a single EDT, exactly like Swing. All UI mutation must happen on it.
- Inside event listeners and lifecycle callbacks (
start,stop,init) you are already on the EDT. - From a background thread, hop back with
Display.getInstance().callSerially(() -> { ... })(orcallSeriallyAndWaitif you need to block). - Use
Display.getInstance().startThread(runnable, "name").start()instead ofnew Thread(...)so cleanup happens correctly across platforms.
references/swing-comparison.md contains a Swing→CN1 EDT idiom table.
The Lifecycle main class
Every CN1 app extends com.codename1.system.Lifecycle (or com.codename1.ui.util.Lifecycle in older code). The four methods you may override:
public class MyAppName extends Lifecycle {
@Override
public void init(Object context) {
// Called once on the EDT. The Lifecycle base class already installs
// the theme; reach for the cached global resources instance from
// here on (Resources.getGlobalResources() returns the in-RAM copy,
// no disk re-read).
}
@Override
public void runApp() {
// Build and show the first form.
Form f = new Form("Hello", new BorderLayout());
f.add(BorderLayout.CENTER, new Label("Welcome"));
f.show();
}
@Override
public void stop() { /* App backgrounded */ }
@Override
public void destroy() { /* App killed */ }
}
Minimal "first screen" pattern
import static com.codename1.ui.CN.*; // Convenience statics: callSerially, etc.
import com.codename1.ui.*;
import com.codename1.ui.layouts.*;
Form f = new Form("Profile", BoxLayout.y());
f.getToolbar().addCommandToRightBar("Save", null, e -> save());
f.add(new Label("Name"))
.add(new TextField())
.add(new Button("Submit"));
f.show();
BoxLayout.y() (vertical) and BoxLayout.x() (horizontal) are the most common layouts. Wrap a Form content pane in BorderLayout when you want a header/footer/center split. See references/ui-components.md for the full layout matrix.
CSS in Codename One
CN1 ships with a CSS compiler that bakes common/src/main/css/theme.css into the binary theme resource (theme.res). It supports a deliberate subset of web CSS:
Form {
background-color: #0f172a; /* hex, rgb(), or named colors */
padding: 2mm; /* mm is the recommended unit */
}
Button {
background-color: #1d4ed8;
color: #ffffff;
border: 1px solid #1d4ed8;
border-radius: 3mm;
padding: 2mm 4mm;
}
Button.pressed { /* state pseudo-class baked as UIID */
background-color: #1e3a8a;
}
#Constants {
useLargerTextScaleBool: true; /* theme constants, not standard CSS */
}
Key differences from web CSS (read references/css.md before authoring more):
- Selectors target UIIDs (Codename One component style names), not arbitrary HTML elements.
Button,Form,Label,Toolbar,Titleare the most common. - No descendant combinator, no
:hover, no media queries. State variants are baked:.pressed,.disabled,.selected. - Units: prefer
mm(millimeters) overpx. CN1 convertsmmto device pixels viaDisplay.convertToPixels.1mm≈ 6-9 px depending on density. border-radiusworks but is rasterized at compile time — animating it at runtime requires programmatic styling.- No
transform, noflex, nogrid. Use CN1 Java layouts for arrangement; CSS is only for styling. - Bundled named colors are limited:
pink,orange,purple,yellow,gray/greyare translated to hex by the initializr, anything else you must specify as hex.
references/html-css-cheatsheet.md shows how to map "I want a flexbox row" / "I want a hero section" / "I want a card" to CN1 idioms.
Adaptability and responsive design
Mobile screens vary wildly. CN1 gives you:
- Density-independent units:
1mmalways renders ~1mm tall regardless of pixel density. Always size inmm, notpx. Display.getInstance().convertToPixels(2.5f)— convert millimeters to current device pixels programmatically.Display.getInstance().isTablet(),Display.getInstance().isPortrait(),Display.getInstance().getDisplayWidth/Height()— branch on form factor.LayeredLayoutwithLayeredLayoutConstraintfor precise responsive positioning (percent-based insets).Toolbarautomatically reshapes to platform conventions (Android side menu / iOS tab bar).
See references/mobile-adaptability.md for patterns: phone-vs-tablet master-detail, orientation listeners, dynamic font scaling.
Testing
CN1 supports two compatible test styles in the same project:
- Legacy
AbstractTest+cn1:test. Required for tests that must also run on a device (mvn cn1:test -Dtarget=ios). Compiles under the device subset (no reflection, no JavaSE APIs). Seereferences/testing-and-screenshots.md. - Standard JUnit 5 +
@CodenameOneTest. Runs only in the simulator JVM via Surefire, so you get reflection, Mockito, AssertJ, IDE green-bar integration,-Dtest=Foo#barfiltering. Faster startup. Seereferences/junit-testing.md.
Both runners coexist — cn1:test discovers UnitTest implementers, Surefire discovers @Test methods, they don't trip over each other. Pick per test class.
// Legacy AbstractTest -- compiles under the device subset, runs via `cn1:test`.
public class LoginFormTest extends AbstractTest {
@Override public boolean shouldExecuteOnEDT() { return true; }
@Override public boolean runTest() throws Exception {
new MyAppName().runApp();
TestUtils.waitForFormTitle("Login");
TestUtils.setText("usernameField", "alice");
TestUtils.clickButtonByLabel("Sign In");
TestUtils.waitForFormTitle("Home");
return screenshotTest("home-screen-baseline");
}
}
// JUnit 5 -- simulator-only, runs via `mvn test` / Surefire.
@CodenameOneTest
class GreetingFormTest {
@Test
@RunOnEdt
void formShowsExpectedTitle() {
new Form("Hello").show();
assertEquals("Hello", Display.getInstance().getCurrent().getTitle());
}
}
Run with mvn -pl common cn1:test (cn1:test runner only) or mvn test (both runners). The cn1app archetype already wires up Surefire + JUnit Jupiter in the generated POMs.
screenshotTest(name) captures the current form, compares against a stored baseline under Storage, and returns true if within tolerance. First run records the baseline. See references/testing-and-screenshots.md for the tolerance algorithm and how to validate UI you just wrote.
Important: a "screenshot matches baseline" only proves consistency, not correctness. If you just generated the baseline yourself, you have not validated the screen — visually inspect at least once before treating that baseline as ground truth.
Headless caveat: any simulator-driven test (both flavors) needs an X server / Xvfb to construct the simulator's
JFrame. The@CodenameOneTestextension auto-aborts the class on a headless JVM so you get "skipped" instead of "errored"; thecn1:testrunner needs you to skip with-DskipTestsor run underxvfb-run.
Build and run commands
From the project root:
# Run in the desktop simulator (requires JDK 11–25 at runtime; build still uses JDK 17 source level)
mvn -pl common cn1:run
# Run with breakpoints
mvn -pl common cn1:debug
# Execute the CN1 test runner
mvn -pl common cn1:test
# Cloud build for Android/iOS/JS (requires CN1 build server creds)
mvn -pl android package -Dcodename1.platform=android -Dcodename1.buildTarget=android-device
mvn -pl ios package -Dcodename1.platform=ios -Dcodename1.buildTarget=ios-device
mvn -pl javascript package -Dcodename1.platform=javascript -Dcodename1.buildTarget=javascript
See references/build-and-run.md for the local-vs-cloud matrix, automated-build mode (Enterprise), iOS local-build prerequisites, and the complete goal list. The full codename1.arg.* index lives in references/build-hints.md.
What NOT to do
- Don't use
java.awt.Color/java.awt.Font/javax.swing.*— CN1 has its ownColorconstants (justintARGB),Font.createTrueTypeFont, andComponenthierarchy. - Don't add CSS that references web-only properties (
display,flex,position,transform,@media) — the CN1 CSS compiler will silently ignore them or fail. - Don't put localization bundles under
common/src/main/resources/. The CN1 plugin scanscommon/src/main/l10n/(orcommon/src/main/i18n/); bundles placed anywhere else are NOT baked intotheme.resandResources.getL10N("messages", lang)returnsnullat runtime. - Don't spin up
new Thread(...)for UI work — useDisplay.getInstance().callSerially(...)orDisplay.startThread(...). - Don't mutate UI off the EDT. Symptoms: random repaint glitches, native crashes on iOS.
- Don't write screenshot tests where the baseline was just generated by the same code you are validating — that proves nothing.
Sanity-check loop before reporting "done"
For any UI-altering change:
- Run
mvn -pl common cn1:runin the simulator and click through the changed flow. - Inspect at least one screenshot (capture via the simulator menu → Save Screenshot, or generate via a test).
- Resize the simulator window or toggle a different skin to confirm the layout doesn't break on a different form factor.
- If you wrote a
screenshotTest, delete the auto-generated baseline once if the screen has changed, then re-run twice — the second run should pass withtrue.
If you cannot run the simulator (e.g. headless environment), say so explicitly in the response rather than claiming the UI works.
Reference quick-look index
| If the user asks for... | Open this reference |
|---|---|
| "Add a screen with a list / form / dialog" | references/ui-components.md |
"Wire this form to a model" / "Validate this form" / @Bindable, @Required, @Email, ... |
references/binding-and-validation.md |
| "Make this look like X" / CSS tweaks | references/css.md |
| "Port this from Swing" / Swing idioms | references/swing-comparison.md |
| "I have HTML/CSS, convert it" | references/html-css-cheatsheet.md |
| "I have a React/JSX design (jsx + tokens.css), rebuild it in CN1" / "match this Claude design" | references/react-to-cn1.md |
| "I have Android XML/Kotlin/Java, convert it" | references/android-to-cn1.md |
"Generate a client for this OpenAPI spec / .proto / GraphQL schema" / @RestClient, @GrpcClient, @GraphQLClient |
references/api-clients.md |
| "Write a test for this screen" / "Compare to a baseline" | references/testing-and-screenshots.md |
| "Match this mockup" / "Compare to a Figma/Sketch/XD design" / "Import this HTML/CSS (Claude) design's tokens" / "How close is this screen to the design" | references/mockup-comparison.md |
| "Make it look right on tablet/landscape" | references/mobile-adaptability.md |
| "How do I run/build/deploy" | references/build-and-run.md |
"What's the right codename1.arg.* for X" / native config |
references/build-hints.md |
| "Why does the compliance check fail" / Java/IO/networking | references/java-api-subset.md |
| "I need to call a native iOS/Android/JS/desktop API" | references/native-interfaces.md |
| "How do I create / consume a cn1lib" | references/cn1libs.md |
| "Add a chatbot" / "Integrate OpenAI/Ollama/Anthropic" / "Stream LLM tokens" / "Generate an image" / "Embed text" | references/ai-and-speech.md |
| "Read voice input" / "Speak text aloud" / "Add a voice button to my chat" | references/ai-and-speech.md |
| "Print a document / report / image" / "print the current screen" / AirPrint | references/printing.md |
"Build a game" / sprites, game loop, joystick, collisions / GameView |
references/games.md |
"Render 3D" / "show a 3D model" / glTF / RenderView / custom GPU drawing |
references/3d-graphics.md |
| "Scan a barcode" / "Detect a face" / "Crop a document photo" via ML Kit | references/ai-and-speech.md |
| "Store an LLM API key" / non-prompting SecureStorage | references/ai-and-speech.md |
| "Build against a Codename One SNAPSHOT from git" | references/snapshot-builds.md |
"Debug a faulty screen — attach jdb to the simulator" |
references/debugging.md |
Quick yes/no check: "is this java.* class supported", "does my theme.css compile" |
tools/ directory — java tools/IsApiSupported.java <class> / java tools/IsCssValid.java <file> |
| "Score this screen against a mockup" / "Import a Figma/Sketch/XD design" | tools/ directory — java tools/CompareToMockup.java <render> <mockup> / java tools/DesignImport.java <design> (see references/mockup-comparison.md) |
| "Describe this screen" / "are these elements aligned" / "lint this UI for bugs" | tools/ — java -cp <cp> tools/DumpForm.java <MainClass> then tools/DescribeForm.java / tools/AlignmentCheck.java / tools/GuiLint.java on the model (see references/mockup-comparison.md) |
| "Update / refresh the Codename One skill to the latest" | tools/ — java tools/UpdateSkills.java [--dry-run] |