This guide focuses on practical CotomyElement usage. The goal is to move from API familiarity to coding patterns you can apply immediately in production screens.
Introduction: Why CotomyElement Comes First
If you start Cotomy from forms or API helpers, you can still build features. But you will miss the actual center of the model.
CotomyElement is the smallest structural unit in Cotomy. It is not a virtual component instance. It is a wrapper around a real DOM element, with runtime behavior for events, scoped CSS, lifecycle hooks, and DOM-safe manipulation. For API details, see CotomyElement reference .
A quick comparison with React helps set expectations:
A React component is a declarative render unit over a virtual tree, while CotomyElement is a direct DOM structural unit over the real tree.
Cotomy does not ask you to treat the DOM as a render artifact. It asks you to treat the DOM as a live operational surface.
That is why CotomyElement comes first. If you understand this class, the rest of Cotomy (CotomyForm, CotomyApi, CotomyPageController) becomes an extension of the same structural boundary.
Binding to an Existing DOM Element
In business systems, you often start with existing server-rendered HTML. Cotomy supports this directly: bind to existing DOM and add behavior.
import { CotomyElement } from "cotomy";
const element = CotomyElement.byId("user-panel");
You can do the same with a derived class:
import { CotomyElement } from "cotomy";
class UserPanel extends CotomyElement {
public activate(): void {
this.attribute("data-state", "active");
}
}
const panel = CotomyElement.byId<UserPanel>("user-panel", UserPanel);
panel!.activate();
Why this matters:
The bound element becomes your structural root boundary, scoped behavior and event registration are attached to that runtime instance, and HTML ownership stays where it already belongs while you add behavior safely.
This is the practical meaning of “DOM = state”. You are not mirroring screen state into another hidden object graph. You are operating on the actual structure the user sees.
Creating a New DOM Element
Sometimes you do not have existing markup. You need to generate a new UI block intentionally. If you use VS Code, es6-string-html is recommended so /* html / and / css */ template literals are syntax-highlighted.
Pattern A (Base): HTML string input
import { CotomyElement } from "cotomy";
const card = new CotomyElement(/* html */ `
<section class="card">
<h3>Profile</h3>
<p>DOM-first structure</p>
</section>
`);
This is the default creation style in many screens. If you do not need scoped CSS for that block, this is usually enough.
Pattern B: html + css input (scoped style)
import { CotomyElement } from "cotomy";
const panel = new CotomyElement({
html: /* html */ `
<section class="panel">
<h2 class="title">Users</h2>
<p class="desc">Scoped style example</p>
</section>
`,
css: /* css */ `
[root] {
border: 1px solid #d8e0e6;
border-radius: 8px;
padding: 12px;
background: #fff;
}
[root] .title {
margin: 0 0 6px;
font-size: 1rem;
}
`
});
In this form, [root] explicitly marks the style boundary. Use this when you want to clearly show root-level and child-level selectors.
You can also omit [root] for simple single-rule CSS:
const compact = new CotomyElement({
html: /* html */ `
<section class="compact">
<h3 class="title">Compact</h3>
<p class="desc">Single-rule scoped style</p>
</section>
`,
css: /* css */ `
.compact {
padding: 8px;
border: 1px solid #d8e0e6;
}
`
});
In this mode, Cotomy prepends the root scope once. For multi-rule CSS, write [root] explicitly on each selector:
const detailed = new CotomyElement({
html: /* html */ `
<section class="detailed">
<h3 class="title">Detailed</h3>
<p class="desc">Explicit root selectors</p>
</section>
`,
css: /* css */ `
[root] .detailed {
padding: 8px;
border: 1px solid #d8e0e6;
}
[root] .title {
margin: 0 0 4px;
}
[root] .desc {
color: #52606d;
}
`
});
Pattern C: tagname + text + css input (lightweight)
This pattern is less central, but useful for simple text or message output where writing full HTML tags is unnecessary.
import { CotomyElement } from "cotomy";
const message = new CotomyElement({
tagname: "p",
text: "Saved successfully.",
css: /* css */ `
[root] {
color: #0b6b57;
font-weight: 600;
}
`
});
This is explicit structure generation, not a render cycle. You decide when and where the element exists, then attach behavior.
Adding an Element Through CotomyWindow
CotomyWindow is the runtime surface for page-level behavior. In current Cotomy implementation, you use CotomyWindow.instance and append through append(. ). Related references: CotomyWindow and Forms Basics .
import { CotomyElement, CotomyWindow } from "cotomy";
const win = CotomyWindow.instance;
win.initialize();
const notice = new CotomyElement('<div class="notice">Ready</div>');
win.append(notice);
CotomyWindow.initialize() will be covered in detail in a future guide. If you are not using CotomyPageController, call CotomyWindow.instance.initialize() explicitly during startup.
Why use window-level append instead of appending to the body from scattered locations:
You operate through a shared lifecycle boundary, removal observation and runtime events are initialized in one place, and page-level behavior stays consistent as screens grow.
This does not forbid direct DOM usage. It keeps structural operations coordinated through runtime boundaries in long-lived UI.
A common integration pattern is:
- CotomyWindow.instance.initialize() once at startup
- create or bind elements
- append entry elements through CotomyWindow.instance.append(. )
Retrieving Existing Elements — Static Methods
Use CotomyElement static retrieval methods when you need predictable element lookup without external helper libraries.
CotomyElement.byId(id, type?)
Returns one typed element or undefined. Best when the page has a stable ID contract.
import { CotomyElement } from "cotomy";
const profile = CotomyElement.byId("profile");
if (profile) {
profile.attribute("data-state", "active");
}
CotomyElement.first(selector, type?)
Returns the first match or undefined. Use for single-entry blocks selected by CSS.
const firstError = CotomyElement.first(".field-error");
firstError?.setFocus();
CotomyElement.last(selector, type?)
Returns the last match or undefined. Useful for append-like UI where newest/last element matters.
const latestRow = CotomyElement.last(".result-row");
latestRow?.scrollIn();
CotomyElement.find(selector, type?)
Returns all matches as an array. Use when applying the same operation to multiple elements.
CotomyElement.find("[data-status='pending']").forEach(el => {
el.attribute("data-highlight", "true");
});
CotomyElement.contains(selector) / CotomyElement.containsById(id)
Boolean existence checks. Use for guard conditions before costly operations.
if (CotomyElement.containsById("approval-panel")) {
// proceed with panel setup
}
CotomyElement.empty(type?)
Creates a hidden placeholder element. Useful as a safe no-op fallback when you want chain-style handling.
const meta = CotomyElement.byId("meta") ?? CotomyElement.empty();
meta.attribute("data-ready", "1");
Compared with jQuery-like usage:
Return types are explicit (CotomyElement | undefined, arrays, booleans), there is no implicit collection wrapper with mixed semantics, and typed constructor override supports class-based structure.
Design Guidelines for Using CotomyElement
The following rules keep Cotomy usage stable in production code.
Treat one feature as one element boundary, write scoped CSS relative to the root boundary, avoid moving too much UI state into detached JS variables, and operate on DOM state directly when the user-facing state is already in the DOM.
Practical guideline:
Keep domain decisions out of element classes, keep element classes focused on structure, interaction, and presentation state, and treat API results as operational input before updating the DOM intentionally.
This keeps separation of concerns clear while preserving debuggability in browser tools.
What CotomyElement Is Not
Misunderstanding this class leads to most early integration mistakes.
CotomyElement is not:
a virtual DOM implementation, a re-render engine, or a centralized state management framework.
It is a runtime-oriented DOM abstraction with lifecycle and structural safety behaviors.
If you expect auto re-render from object mutation, you are using the wrong mental model. If you expect hidden state synchronization, same issue.
Cotomy’s design expects explicit structural updates on real DOM nodes.
Conclusion: From Element to Structured UI
CotomyElement is the practical starting point for Cotomy. You can bind existing HTML, generate new structure, append through CotomyWindow.instance, and retrieve elements through static methods with predictable return behavior.
This is enough to build robust screen structure before introducing higher-level helpers.
Once this layer is clear, the next practical step is forms. That is where intent declaration, submission flow, and failure channels become operationally meaningful.
Practical Guide
This article is part of the Cotomy Practical Guide, which focuses on hands-on usage patterns for the framework.
Series articles: Working with CotomyElement, CotomyPageController in Practice , and Standardizing CotomyPageController for Shared Screen Flows .