Skill v1.0.1
currentAutomated scan100/100+86 new
version: "1.0.1" name: jaspr-fundamentals description: Use when working in a Jaspr project, on Jaspr components, or other Jaspr-related tasks. Contains fundamentals of writing Jaspr components and using HTML components. metadata: jaspr_version: 0.23.3
Components
Jaspr uses a component-based architecture very similar to Flutter's widgets. Concepts like ui composition, architecture and state management are transferable.
- StatelessComponent: For components that don't need mutable state. You must override
Component build(BuildContext context). - StatefulComponent: For components with mutable state. Requires an associated
Stateclass. The state has lifecycle methods likeinitState()anddispose(). You must overrideComponent build(BuildContext context)in the state class. - InheritedComponent: For propagating context or state efficiently down the component tree.
Returning Components from build
Building UIs in Jaspr requires you to return a single Component from build().
- Rule 1: You MUST NOT use
Iterable<Component> build(BuildContext context) sync*. This is legacy code. - Rule 2: You MUST use dot-shorthands instead of capitalized component names for fragments, text, and empty nodes.
- Use
.fragment([...])(Do NOT useFragment([...])orfragment([...])). - Use
.text('...')(Do NOT useText('...')ortext('...')). - Use
.empty()to return an empty space safely.
Example Usage:
import 'package:jaspr/jaspr.dart';import 'package:jaspr/dom.dart';class MyComponent extends StatelessComponent {const MyComponent({super.key});@overrideComponent build(BuildContext context) {// 1. Return a single component (e.g. div)// 2. Use dot-shorthand (.text) instead of Text()return div(classes: 'my-class', [.text('Hello World'),]);}}
HTML Components
Jaspr provides typed components for standard HTML elements (e.g., div(), p(), a(), button()). To use these add the package:jaspr/dom.dart import.
All HTML components take standard named Key? key, String? id, String? classes, Styles? style, Map<String, String>? attributes and Map<String, void Function(Event)>? events parameters. Most HTML components take a positional List<Component> children parameter (except for self-closing tags like img, input, br, etc.).
- Rule 1: ALWAYS put the
childrenlist LAST, after all named parameters. - Rule 2: You MUST prefer available typed parameters (e.g.,
href,src,onClick) over using the rawattributes:orevents:maps. - Rule 3: When you are unsure about which typed parameters exist for an HTML component, you MUST read the respective reference file provided alongside this skill:
references/html/<tag>.mdcontains the full signature and example usage of the component for the given tag. (e.g.references/html/div.mdfordiv(),references/html/button.mdforbutton(), etc.)- Rule 4: When a respective reference file does not exist for a tag (and therefore the component itself doesn't exist), you MUST use the generic
.element(tag: '...', /* other standard params, */ children: [ /* ... */ ])constructor instead.
Example Usage:
import 'package:jaspr/jaspr.dart';import 'package:jaspr/dom.dart';class MyHtmlComponent extends StatelessComponent {const MyHtmlComponent({super.key});@overrideComponent build(BuildContext context) {return div(id: 'my-container', classes: 'my-class', [p(attributes: {'aria-label': 'Example Paragraph'}, [.text('Hello World'),]),// E.g. signature as found at 'references/html/a.md'a(href: 'https://example.com', [.text('Click me'),]),]);}}
Styling Components
Jaspr has built-in support for styling components using CSS-in-Dart. See the jaspr-styling skill for more information.
Interactivity and Events
1. Accessing Browser APIs
- Rule 1: In server or static mode, you MUST use
package:universal_web/web.dartto access browser APIs andpackage:universal_web/js_interop.dartto access js interop APIs. - Rule 2: When using
package:universal_webin server or static mode, you MUST wrap all API calls in anif (kIsWeb)check to prevent crashing the server render. - Rule 3: In client mode, you can use
dart:js_interopandpackage:webdirectly. - Rule 4: For global events, you MUST use
web.EventStreamProvidersto listen to events on thewindowordocumentas they provide a typed DartStreamof events.
// Example of safe usage in server/static mode:import 'package:universal_web/web.dart' as web;void logSize() {if (kIsWeb) {print('Window size: ${web.window.innerWidth}x${web.window.innerHeight}');// Example of global event listenerfinal sub = web.EventStreamProviders.resizeEvent.forTarget(web.window).listen((event) {print('Window resized');});}}
2. Handling Events
All DOM components support an events: parameter, and interactive components feature typed event callbacks (like onClick, onChange).
- Rule 1: You MUST use
web.Eventwhen typing raw events. - Rule 2: Use the
events()helper function for type-safe callback creation when needed.
import 'package:jaspr/jaspr.dart';import 'package:jaspr/dom.dart';import 'package:universal_web/web.dart' as web;class MyButton extends StatelessComponent {@overrideComponent build(BuildContext context) {return div(// Using raw eventsevents: {'click': (web.Event event) {print('Div clicked');}},[// Using typed parametersbutton(onClick: () => print('Button clicked'),[.text('Click me')])]);}}
3. Accessing Elements (GlobalNodeKey)
If you need direct reference to an underlying DOM element rendered by Jaspr, you can assign it a GlobalNodeKey.
import 'package:jaspr/jaspr.dart';import 'package:jaspr/dom.dart';import 'package:universal_web/web.dart' as web;class MyInput extends StatefulComponent {@overrideState<MyInput> createState() => _MyInputState();}class _MyInputState extends State<MyInput> {final GlobalNodeKey<web.HTMLInputElement> inputKey = GlobalNodeKey();void focusInput() {inputKey.currentNode?.focus();}@overrideComponent build(BuildContext context) {return input(key: inputKey, type: .text);}}
Further Resources
- For information on pre-rendering, async data fetching, hydration, and the
@clientannotation see the related skill: jaspr-pre-rendering-and-hydration. - For information on styling components see the related skill: jaspr-styling.
- For information on how to convert HTML to Jaspr code, see the related skill: jaspr-convert-html.
- An index of all available documentation can be found at https://jaspr.site/llms.txt.