Typescript library for making hypermedia systems using little to no Javascript code. The Typescript may be important to the datastar dev but its just a normal JS file to the browser. The goal is to make it easy to create realtime web apps with as little Javascript as possible. This is done by using HTML attributes to define the behavior of the page. This is similar to Alpine.js + HTMX but with a few key differences.
<div data-signal-count="0">
<div>
<button data-on-click="$count++">
Increment +
</button>
<button data-on-click="$count--">
Decrement -
</button>
<input type="number" data-model="count" />
</div>
<button
data-signal-get="'/api/echo'"
data-on-load="$$get"
data-on-click="$$get"
>
Contents
</button>
</div>
It's just normal HTML data attributes that get watched by plugins and build up a context object. The current plugins work off of signals to make everything reactive and allow very fast interactions in very little code.
Lives as a channel in the EventGraph Discord server. Feel free to join and ask questions.
- 💯 strict Typescript with full tree shaking support
- 📦 0 dependencies
- The best parts of Alpine.js and HTMX but created in a unique way to allow for a more declarative approach
- 💯 HTML compliant
- Fine grain reactivity
- Using Vite for development and Rollup for production builds.
- Everything is an plugin so you can add and remove features as needed
- Easy to use mock server for testing
- HOWL stack ready with Go specific tooling coming soon
- Even with all plugins its very small (see badge above)
- Faster than Alpine.js VDOM reactivity and HTMX needs Hyperscript or Alpine to work on most real world projects
- DHH would hate it
- Syntax is still very much in flux, but will stabilize with usage
- No progressive enhancement, you need Javascript enabled. Datastar is for making realtime web apps like dashboards, admin panels, etc. If you need progressive enhancement use Alpine-Ajax or HTMX and stick to just
<a/>
and<form/>
tags. Scripting is a first class citizen in hypermedia systems. - Modern browsers only (no IE11 support)
- Have to use custom attributes (data-*) so slightly more verbose but spec compliant always
- No SSE support yet (coming soon)
- Less memes and tweets
- No tests yet (but actively being used on an internal project). Plan to use Vitest+Playwright soon
- Documentation is on its way
- No book, but most of hypermedia concepts will port directly over.
So far the following plugins are available. More are coming as needed.
Name | Description |
---|---|
actions | Adds support for @action which is a sandboxed function call similar to an Alpine $magic but only for functions |
bind | Allows signals to be bound to attributes on a element |
focus | Focus an element, use when returning a fragment of HTML |
fragments | Adds @get ,@delete ,@put ,@post ,@patch actions. Usually used within on data-on-* attribute |
headers | data-header-foo="bar" will add { FOO: "bar"} to fragment calls |
intersect | Uses intersection observer to trigger a function when an element is in view |
model | Two way binding for form elements to signals |
on | Adds support for data-on-* attributes to call functions. Includes debounce,throttle,etc |
signal | Fine grained reactivity, used by most current plugins |
teleport | Move elements around the DOM, mostly for modals |
text | Update text content of an element |
pnpm i
pnpm dev // for development and kitchen sink demo.
pnpm build // for production
Just add this to your HTML file in head or body. This will add all the plugins and hook them up.
<script src="https://unpkg.com/@sudodevnull/datastar@0.0.4/dist/datastar.iife.js"></script>
import { addAllIncludedPlugins } from '@sudodevnull/datastar'
addAllIncludedPlugins()
If you look at that addAllIncludedPlugins
its just calling all the current plugins. You can add them individually if you want.
Learning from Alpine Ajax we can use a mock server available in the browser to test out the basics. Note Datastar is primarily targets at HOWL stack development. This means you can use it with any server that can serve HTML and receive JSON. The mock server is just for testing.
If you want to use the mock server you can add this after...
import { injectMockFetch } from '@delaneyj/datastar'
injectMockFetch({
'/api/echo': {
GET: async (req) => {
const queryString = req.url.split('?')[1]
const searchParams = new URLSearchParams(queryString)
const dsJSON = searchParams.get('dataStack')
if (!dsJSON) throw new Error('No dataStack found in query params')
const dataStack = ds.JSONParse(dsJSON)
await new Promise((resolve) => setTimeout(resolve, 1000))
return {
html: `
<pre data-swap="after">${ds.JSONStringify(dataStack, null, 2)}</pre>
<div id="foo">Bar</div>
`,
}
},
},
})
Datastar is a play on the fact its using normal custom HTML attributes to do its magic. These fall under the data-*
attribute prefix
I love what Caleb Porzio has done with Alpine.js and likewise with Carson Gross with HTMX. However after trying to make plugins in both I got disappointed with the limitations. Both are pure Javascript which is fine but leads to having to either keep the whole state in your head and or be prepared for lots of runtime errors. Personally I think the best way to do this is to use Typescript and have the build step and compiler catch as many errors as possible. Plus it makes it easier to extend and create optimized builds.
HTMX Essays are a great place to start.
There was a bit of a rant here before. TL;DR tried to show HTMX v2 could do all these things and it wasn't accepted by the community. I think HTMX is great and I will continue to recommend it. In general I think the some of the choices are throwing the baby out with the bathwater when it comes to things like Vite/TS/etc.