Getting Started¶
This guide walks you through installing Adapter, creating your first component, and understanding the basic styling model.
If you haven’t yet, read intro.md for the high-level concepts and motivation.
1. Install Adapter¶
Adapter works in browsers, Deno, and Node-based bundlers. Choose the setup that matches your project.
CDN (browser-only, great for demos)¶
You can load Adapter directly from a CDN in any HTML page:
<script type="module">
import { Adapter } from "https://cdn.jsdelivr.net/npm/@devcapsule/adapter/+esm";
// your components go here
class HelloCard extends Adapter {}
HelloCard.css = `
display: block;
padding: 1rem;
border-radius: 0.5rem;
border: 1px solid currentColor;
`;
HelloCard.define("hello-card");
document.body.innerHTML = "<hello-card>Hello Adapter</hello-card>";
</script>
Deno / JSR¶
npm (Node / bundlers via JSR)¶
Use the official compatibility helper so npm stays in sync with the JSR release:
This command installs the compatibility package (published as @jsr/devcapsule__adapter) and adds the correct alias to your package.json, per the JSR npm compatibility guide.
After installing you can import Adapter with its canonical name:
2. Your first Adapter component¶
The easiest way to use Adapter is to extend the Adapter base class and assign a CSS string to the class itself.
import { Adapter } from "@devcapsule/adapter";
class Card extends Adapter {}
Card.css = `
display: block;
padding: 1rem;
border-radius: 0.5rem;
border: 1px solid rgba(0, 0, 0, 0.15);
background: white;
`;
// Register the custom element
Card.define("ui-card");
Use it in HTML like any other custom element:
Behind the scenes (see src/adapter.ts):
- A class controller (
AdapterClassController) collects the CSS assigned on the class. - When you call
Card.define("ui-card"), Adapter - registers the custom element with
customElements.define, and - creates a constructable
CSSStyleSheetshared by allui-cardinstances. - This stylesheet is attached via
document.adoptedStyleSheets, so everyui-cardshares the same base styles.
3. Class-level vs instance-level styles¶
Adapter gives you two main ways to style components:
- Class-level styles – shared by all instances of a component.
- Instance-level styles – scoped to one specific element.
Class-level styles¶
Class-level styles are defined on the class itself:
class Button extends Adapter {}
Button.css = `
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.5rem 1rem;
border-radius: 999px;
border: 1px solid transparent;
cursor: pointer;
`;
Button.define("ui-button");
You can add more base styles later using static addStyle:
Adapter aggregates these class-level blocks and writes them into the shared class stylesheet managed by AdapterClassController.
Instance-level styles via JS¶
Every element instance also owns its own constructable stylesheet, managed by AdapterObjectController.
You can style a single instance from JavaScript:
const card = document.createElement("ui-card") as InstanceType<typeof Card>;
card.css = `
border-color: hotpink;
`;
document.body.append(card);
When you set card.css:
- Adapter ensures the element has a stable, UUID-based class name.
- It generates a selector like
ui-card.ui-card-1234 { ... }. - It writes that rule into the instance’s own
CSSStyleSheet.
That stylesheet is attached to the element’s root node (document or shadow root) through adoptedStyleSheets, so the styles are local to that instance.
Instance-level styles via the css attribute¶
You can also set styles declaratively using an attribute. Adapter observes the css attribute and keeps it in sync with the instance stylesheet.
In src/adapter.ts, AdapterObjectController uses a MutationObserver to watch for css attribute changes and update element.css automatically.
Next steps: read core-concepts.md for a deeper look at the controllers and mixin, or jump to framework-integration.md to see how Adapter fits into React, Vue, and other stacks.