v0.4.1 — Persistent Agent Memory

The AI-Native Web Framework

Write less. Build faster. No imports. Pure magic.

Counter.speck
<Counter>
  <state count={0} />
  
  <button onClick={() => state.count.value++}>
    Count: {state.count.value}
  </button>
</Counter>
Get Started Read the Docs
0 Imports needed
~2KB Runtime
Possibilities

Everything you need.
Nothing you don't.

🤖

AI-Native

Built-in Agent components for Claude integration. Full chat UI in one line of code.

<Agent.Chat purpose="You are helpful" />
🧠

Persistent Memory NEW

Agents remember conversations across sessions. One prop enables memory that persists.

<Agent.Chat memory={true} />

Zero Imports

Components auto-discover each other. Just use <MyComponent /> anywhere.

🎯

Fine-Grained Reactivity

Powered by Preact Signals. Only what changes re-renders. No virtual DOM diffing.

🛣️

Built-in Router

Client-side routing with dynamic params. No extra packages needed.

Async Made Easy

<async>, <then>, <catch>, <loading> — handle promises declaratively.

🧩

Slots & Props

Flexible composition with named slots and prop spreading. Build complex UIs easily.

Code that speaks for itself

<Counter>
  <state count={0} />
  
  <div class="counter">
    <h2>{state.count.value}</h2>
    <button onClick={() => state.count.value--}>-</button>
    <button onClick={() => state.count.value++}>+</button>
  </div>
</Counter>

Reactive State

Declare state with <state name={value} />. Access via state.name.value. Updates are instant.

<UserList>
  <state users={["Alice", "Bob", "Charlie"]} />
  
  <ul>
    <loop of={state.users.value} let={user}>
      <li>{user}</li>
    </loop>
  </ul>
</UserList>

Simple List Rendering

Iterate with <loop of={array} let={item}>. No .map() callbacks needed.

<App>
  <Router>
    <route path="/">
      <HomePage />
    </route>
    
    <route path="/user/:id" let={params}>
      <UserProfile userId={params.id} />
    </route>
  </Router>
</App>

Built-in Routing

Client-side routing with dynamic params. No react-router needed. Just <Router> and <route>.

<DataLoader>
  <async promise={fetch('/api/data').then(r => r.json())}>
    <loading>
      <p>Loading...</p>
    </loading>
    
    <then let={data}>
      <p>Got: {data.name}</p>
    </then>
    
    <catch let={error}>
      <p>Error: {error.message}</p>
    </catch>
  </async>
</DataLoader>

Declarative Async

Handle promises with <async>. Built-in loading, success, and error states. No useEffect gymnastics.

<ChatBot>
  <Agent.Chat purpose="You are a helpful assistant" />
</ChatBot>

<!-- That's it. Full chat UI with:
   - Input field
   - Submit button
   - Streaming responses
   - Chat history
   - Error handling -->

AI-Native with Agent Components

Full chat UI in one line. No state management, no boilerplate. Just <Agent.Chat /> and you're done.

<SmartBot>
  <Agent.Chat
    id="my-assistant"
    purpose="You are a helpful assistant"
    memory={true}
  />
</SmartBot>

<!-- Now your agent remembers:
   - Previous conversations
   - User preferences
   - Context across sessions
   - Persists through page refreshes -->

Persistent Agent Memory

Add memory={true} and your agent remembers everything. Conversations persist across browser sessions. Zero configuration.

Less code. More clarity.

React
import { useState } from 'react';
import Button from './Button';
import Header from './Header';

export default function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <Header />
      <p>Count: {count}</p>
      <Button onClick={() => setCount(c => c + 1)}>
        Increment
      </Button>
    </div>
  );
}
⚡ Speck.js
<Counter>
  <state count={0} />
  
  <div>
    <Header />
    <p>Count: {state.count.value}</p>
    <Button onClick={() => state.count.value++}>
      Increment
    </Button>
  </div>
</Counter>

Ready to build something amazing?

Join the future of web development. AI-native. Zero imports. Pure magic.