Write less. Build faster. No imports. Pure magic.
<Counter>
<state count={0} />
<button onClick={() => state.count.value++}>
Count: {state.count.value}
</button>
</Counter>
Built-in Agent components for Claude integration. Full chat UI in one line of code.
<Agent.Chat purpose="You are helpful" />
Components auto-discover each other. Just use
<MyComponent /> anywhere.
Powered by Preact Signals. Only what changes re-renders. No virtual DOM diffing.
Client-side routing with dynamic params. No extra packages needed.
<async>, <then>,
<catch>, <loading> — handle
promises declaratively.
Flexible composition with named slots and prop spreading. Build reusable components.
$ npm create speck-app my-app $ cd my-app
# Edit .env
VITE_ANTHROPIC_API_KEY=sk-ant-...
$ npm run dev ✓ Vite server running at http://localhost:5174 ✓ Compiler watching for changes ✓ AI Agent proxy ready
<Counter>
<state count={0} />
<script>
const increment = () => state.count.value++;
const decrement = () => state.count.value--;
</script>
<div>
<h2>Count: {state.count.value}</h2>
<button onClick={decrement}>-</button>
<button onClick={increment}>+</button>
</div>
</Counter>
Declare state with <state> tags. Access values
with .value. Updates are fine-grained — only what
changes re-renders.
<Welcome>
<state isLoggedIn={false} />
<if condition={state.isLoggedIn.value}>
<p>Welcome back!</p>
<Dashboard />
</if>
<if condition={!state.isLoggedIn.value}>
<p>Please log in.</p>
<LoginForm />
</if>
</Welcome>
Use <if condition={...}> for conditional
rendering. Clean, readable, no ternary soup.
<UserList>
<state users={[
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
]} />
<ul>
<loop of={state.users.value} let={user}>
<li>{user.name}</li>
</loop>
</ul>
</UserList>
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>
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>
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 -->
Full chat UI in one line. No state management, no boilerplate.
Just <Agent.Chat /> and you're done.
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>
);
}
<Counter>
<state count={0} />
<div>
<Header />
<p>Count: {state.count.value}</p>
<Button onClick={() => state.count.value++}>
Increment
</Button>
</div>
</Counter>
Join the future of web development. AI-native. Zero imports. Pure magic.