
Security News
npm Adopts OIDC for Trusted Publishing in CI/CD Workflows
npm now supports Trusted Publishing with OIDC, enabling secure package publishing directly from CI/CD workflows without relying on long-lived tokens.
A minimalist & flexible toolkit for interactive islands & state management in hypermedia-driven web applications.
â ď¸ Expect API changes until v1.0.0 â ď¸
Current version: 0.3.23.
Bundle Size: 14kb minified & gzipped.
A simple yet powerful toolkit for interactive islands in web applications. No build step required.
It has features you'd expect from a modern UI framework, such as reactive web components, async state management, streams, and cross-component state management.
Note that Cami specializes in bringing rich interactivity to your web application. As such, it's meant to be used alongside a backend framework such as FastAPI, Rails, Sinatra, or any server really that responds with HTML. Just paste in Cami's CDN link (or import the bundle) and you'll get the power of many modern UI frameworks without it taking over your workflow. Just progressively enhance your HTML with Cami web components.
<!-- The most basic example: the counter -->
<cami-counter></cami-counter>
<script src="https://unpkg.com/cami@latest/build/cami.cdn.js"></script>
<script type="module">
const { html, ReactiveElement } = cami;
class CounterElement extends ReactiveElement {
count = 0
template() {
return html`
<button @click=${() => this.count--}>-</button>
<button @click=${() => this.count++}>+</button>
<div>Count: ${this.count}</div>
`;
}
}
customElements.define('cami-counter', CounterElement);
</script>
Documentation | API Reference | CDN Link | Introduction
When you first create a web component, you'll need to subclass ReactiveElement
. This is an extension of HTMLElement
that turns all of your properties into observable properties. These properties are observed for changes, which then triggers a re-render of template()
.
The template()
method returns template literals tagged with the html tag. The html tag is a function and you pass it a tagged template literal. It looks strange at first as it's not wrapped in parentheses, but it's just a function call with a special syntax for passing in a template literal.
This template literal is a special type of string that allows you to embed javascript expressions in it using normal string interpolation ${}
. Events are handled using @
(event listeners), such as @click
, @input
, @change
, etc. Just prepend any event with @
and you can handle it by passing a function, such as @click=${() => alert('clicked')}
.
Below, we create a CounterElement
that has a count
property. When we mutate count
, the component will re-render template()
.
To use it, you'll need to create a custom element and register it with customElements.define
. Then you can use it in your HTML file by adding the tag <counter-component></counter-component>
like any other HTML tag.
<script src="https://unpkg.com/cami@latest/build/cami.cdn.js"></script>
<article>
<h1>Counter</h1>
<counter-component
></counter-component>
</article>
<script type="module">
const { html, ReactiveElement } = cami;
class CounterElement extends ReactiveElement {
count = 0
template() {
return html`
<button @click=${() => this.count--}>-</button>
<button @click=${() => this.count++}>+</button>
<div>Count: ${this.count}</div>
`;
}
}
customElements.define('counter-component', CounterElement);
</script>
ReactiveElement
. This is done through Observable Properties. They are properties of a ReactiveElement
instance that are automatically observed for changes. When a change occurs, the ReactiveElement
instance is notified and can react accordingly by re-rendering the component. Observable properties support deep updates, array changes, and reactive attributes, making it easier to manage dynamic content. Lastly, this removes the boilerplate of signal()
, setState()
, or reactive()
that you might find in other libraries.query
and mutation
. Use the query
method to fetch and cache data, with options to control how often it refreshes. The mutation
method lets you update data and immediately reflect those changes in the UI, providing a smooth experience without waiting for server responses.cami.store
. By default, this uses localStorage
to persist state across page refreshes. This is useful for storing user preferences, authentication tokens, and other data that needs to be shared across components. This is also useful for storing data that needs to be shared across tabs.map
, filter
, flatMap
, and debounce
to process events in a sophisticated yet manageable way, for clean & declarative code.Please visit our Documentation, API Reference, Examples, or Core Concepts to learn more.
I wanted a minimalist javascript library that has no build steps, great debuggability, and didn't take over my front-end.
My workflow is simple: I want to start any application with normal HTML/CSS, and if there were fragments or islands that needed to be interactive (such as dashboards & calculators), I needed a powerful enough library that I could easily drop in without rewriting my whole front-end. Unfortunately, the latter is the case for the majority of javascript libraries out there.
That said, I like the idea of declarative templates, uni-directional data flow, time-travel debugging, and fine-grained reactivity. But I wanted no build steps (or at least make 'no build' the default). So I created Cami.
ReactiveElement
, and once you need to share state between components, you can add our store. It's a great choice for rich data tables, dashboards, calculators, and other interactive islands. If you're working with large applications with large teams, you may want to consider other frameworks.To learn Cami by example, see our examples.
bun install
bun run build:docs
bun run build:minify
JSDoc is used to build the API reference. We use Material for MkDocs for the documentation.
To make JSDoc be compatible with MkDocs, we use jsdoc2md to generate markdown files from JSDoc comments. We use then use MkDocs to build the documentation site.
We use Jasmine for testing. To run the tests, run:
bunx serve # serves the test files (it's just html)
Then open http://localhost:8080/test/SpecRunner.html
in your browser.
It's short for Camiguin, a pretty nice island.
FAQs
A minimalist & flexible toolkit for interactive islands & state management in hypermedia-driven web applications.
The npm package cami receives a total of 8 weekly downloads. As such, cami popularity was classified as not popular.
We found that cami demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
npm now supports Trusted Publishing with OIDC, enabling secure package publishing directly from CI/CD workflows without relying on long-lived tokens.
Research
/Security News
A RubyGems malware campaign used 60 malicious packages posing as automation tools to steal credentials from social media and marketing tool users.
Security News
The CNA Scorecard ranks CVE issuers by data completeness, revealing major gaps in patch info and software identifiers across thousands of vulnerabilities.