Server-first.
Fragment-driven.
No SPA required.

Write HTML components that run on the server. Add interactivity exactly where you need it — with fragments, signals, or server functions. Nothing more.

01

Server Render

Components run on the server. Request data, session, params — all available at render time. Full HTML shipped, zero JS by default.

<script>
  import { params } from 'jamrock:conn';
  const { name } = params;
</script>

<h1>Hello, {name}!</h1>
02

Fragments

Named regions of the page that can be updated live via SSE — without a full reload, without a client router, without any boilerplate.

<fragment name="feed" interval="5">
  {#each posts as post}
    <article>{post.title}</article>
  {/each}
</fragment>
03

Client Signals

When you genuinely need client reactivity, reach for signals. Declare them in a client script, reference them with $ in templates.

<script context="client">
  import { signal } from 'jamrock';
  const count = signal(0);
</script>

<button onclick={() => count.value++}>
  Clicked {$count} times
</button>

Try it live

This counter runs on the server. Click a button — the fragment re-renders via SSE, no page reload.

0
<script context="module">
  let count = 0;
  export async function increment() { count++; }
  export async function decrement() { if (count > 0) count--; }
</script>

<fragment name="counter">
  <form rpc:call={decrement}><button></button></form>
  <span>{count}</span>
  <form rpc:call={increment}><button>+</button></form>
</fragment>

Get started

Install jamrock and pick a runtime — node, deno, or bun:

curl -L get.jamrock.dev | bash

Then scaffold your first app:

jamrock init my-app
cd my-app && npm install
npm run dev

■ Jamrock v0.0.0 (node v24) Processing ./pages → ./build Listening on http://localhost:8080