https://github.com/hyperpuncher/datastar-electron
Datastar + Electron. Replace IPC with HTTP.
https://github.com/hyperpuncher/datastar-electron
Last synced: 20 days ago
JSON representation
Datastar + Electron. Replace IPC with HTTP.
- Host: GitHub
- URL: https://github.com/hyperpuncher/datastar-electron
- Owner: hyperpuncher
- License: mit
- Created: 2026-05-16T07:55:02.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-05-16T09:48:58.000Z (about 2 months ago)
- Last Synced: 2026-05-16T11:28:55.588Z (about 2 months ago)
- Language: TypeScript
- Homepage:
- Size: 11.7 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# datastar-electron
Datastar + Electron. No IPC, no server, just HTTP.
Inspired by [ssr-electron](https://github.com/StreamUI/ssr-electron) by Jordan Howlett.
## How it works
Electron intercepts `http://` requests from the renderer. Your handler returns a Response. That's it.
```
data-on:click="@post('/increment')" ← Datastar in browser
↓
fetch('http://localhost/increment') ← Electron intercepts (no network)
↓
your handler(request) ← Your code
↓
DS.stream(...) → Response ← Official SDK formats SSE
↓
Datastar patches signals into DOM ← Browser updates reactively
```
## Install
```bash
npm i datastar-electron
pnpm i datastar-electron
bun i datastar-electron
```
## Quick start
```typescript
import { app, BrowserWindow } from "electron";
import { createRouter, ServerSentEventGenerator as DS } from "datastar-electron";
const router = createRouter({ debug: true });
app.whenReady().then(() => {
// Serve HTML
router.registerRoute("/", () => {
return new Response(
`
Count: 0
Loading...
Increment
`,
{ headers: { "Content-Type": "text/html" } },
);
});
// Handle clicks with SSE
let count = 0;
router.registerRoute(
"/increment",
() =>
DS.stream(async (stream) => {
stream.patchSignals(JSON.stringify({ count: ++count }));
}),
"POST",
);
const win = new BrowserWindow({ width: 800, height: 600 });
win.loadURL("http://localhost/");
});
```
## API
### `createRouter(options?)`
Creates the protocol handler. Auto-registers on app ready.
```typescript
const router = createRouter({ debug: true });
```
### `router.registerRoute(path, handler, method?)`
Register a route. Supports `:params`.
```typescript
router.registerRoute("/api/data", (req) => new Response(JSON.stringify({ ok: true })));
// With params
router.registerRoute(
"/toggle/:id",
(req) => {
const id = new URL(req.url).pathname.split("/").pop();
// ...
},
"POST",
);
```
### `DS.stream(callback, options?)`
Returns an SSE Response. From the official Datastar SDK.
```typescript
import { ServerSentEventGenerator as DS } from "datastar-electron";
// One-shot (auto-closes)
return DS.stream(async (stream) => {
stream.patchSignals('{"count": 42}');
stream.patchElements("
Updated", { selector: "#msg" });
});
// Long-lived (stays open)
return DS.stream(
async (stream) => {
while (true) {
stream.patchSignals(
JSON.stringify({ time: new Date().toLocaleTimeString() }),
);
await new Promise((r) => setTimeout(r, 1000));
}
},
{ keepalive: true },
);
```
## License
MIT