Skip to main content
Home

Lightweight library that works with vanilla DOM elements and provides fine-grained reactivity + utils for building websites.

This package works with Cloudflare Workers, Node.js, Deno, Bun, Browsers
This package works with Cloudflare Workers
This package works with Node.js
This package works with Deno
This package works with Bun
This package works with Browsers
JSR Score
100%
Published
4 weeks ago (4.0.2)

campfire

A cozy web framework for modern JavaScript.

campfire logo

Campfire helps you build maintainable, reactive web UI without a build step, without piles of dependencies, and without magic.


Features

  • Chainable builder API for expressive and readable DOM markup
  • Reactive data stores for tightly-coupled UI and state—no frameworks, no global hacks
  • Fluent HTML templating with autoescaping by default and simple pattern-matching
  • TypeScript-first: type inference for all APIs
  • Near-zero dependencies: ~5kb compressed, works in browsers & on the server
  • Composable by default: create reusable components as regular JS/TS functions
  • Collection helpers: ListStore and MapStore for ergonomic reactive collections
  • Clean DOM helpers for selection, insertion, mutation, and more

Install

Direct ES module (browser or Deno):

import { nu, Store } from "https://esm.sh/jsr/@campfire/core";

With npm:

pnpm i jsr:@campfire/core

Then:

import cf from "@campfire/core";

Quick Start

Create a DOM element with the builder API

const [button] = cf.nu("button#search")
    .content("Search")
    .attr("type", "submit")
    .on("click", searchHandler)
    .done();

Reactive UI state

const count = cf.store({ value: 0 });

const [counter] = cf.nu("div.counter")
    .deps({ count })
    .render(({ count }, { b }) => b.html`Clicked ${count} times!`)
    .done();

count.update((n) => n + 1);

Simple, composable components

const NameBadge = () => {
    const name = cf.store({ value: "" });
    const elt = cf.nu("div.badge")
        .deps({ name })
        .render(({ name }, { b, first }) => b.content(first ? "" : `Hi, ${name}!`))
        .done();
    return [name, elt];
};

const [name, badge] = NameBadge();
insert(badge, { into: document.body });
name.update("you");

API at a Glance

Function Purpose
nu() Create elements with chainable builder API
store() Create reactive values, arrays, or maps
select() Select DOM elements (array or single)
insert() Insert element(s) anywhere in the DOM
`html`` Safe HTML templating (escaped by default)
mustache() Render Mustache-style string templates
extend(), x() Modify or enhance any DOM element
empty(), rm() Empty or remove elements
seq(), ids() Utilities for number ranges and unique IDs

For full, annotated examples and advanced usage, see the docs.


Contributing

Pull requests and issues are welcome!


License and Acknowledgements

MIT License

See ACKNOWLEDGEMENTS.md for full license, icon, and upstream credit information.


If Campfire makes your project better, you can support maintenance and new features here.

New Ticket: Report package

Please provide a reason for reporting this package. We will review your report and take appropriate action.

Please review the JSR usage policy before submitting a report.

Add Package

deno add jsr:@campfire/core

Import symbol

import * as core from "@campfire/core";
or

Import directly with a jsr specifier

import * as core from "jsr:@campfire/core";

Add Package

pnpm i jsr:@campfire/core
or (using pnpm 10.8 or older)
pnpm dlx jsr add @campfire/core

Import symbol

import * as core from "@campfire/core";

Add Package

yarn add jsr:@campfire/core
or (using Yarn 4.8 or older)
yarn dlx jsr add @campfire/core

Import symbol

import * as core from "@campfire/core";

Add Package

vlt install jsr:@campfire/core

Import symbol

import * as core from "@campfire/core";

Add Package

npx jsr add @campfire/core

Import symbol

import * as core from "@campfire/core";

Add Package

bunx jsr add @campfire/core

Import symbol

import * as core from "@campfire/core";