Remix Booth
convention-driven full-stack production studio
Pro-grade state management. Zero compromises.
Rails conventions meet DJ mixing. Unmatched flexibility.
Master-level precision for your server/client state.
Sin bloatware, sin sobrecarga, solo rendimiento puro con una huella mínima que no ralentizará tu aplicación.
Crea estado derivado reactivo que se actualiza automáticamente cuando cambian las dependencias, con soporte completo de TypeScript.
Seguimiento basado en señales para un rendimiento óptimo, actualizando solo lo que cambió, con seguimiento automático de dependencias.
Usa objetos directamente - sin acciones, reductores o código repetitivo para gestionar tu estado. Muta y suscríbete con facilidad.
Obtén instantáneas de estado serializables bajo demanda con json() - perfecto para APIs, persistencia y depuración temporal.
Inspecciona tu estado en cualquier momento, con seguimiento de historial integrado y capacidades de depuración temporal.
Simple. Reactivo. Potente.Edita los valores a continuación y observa cómo jods se actualiza de forma reactiva con el sistema de estado reactivo integrado
import { store, json, computed, onUpdate } from "jods";
// Create a reactive store
const user = store({
firstName: "Burt",
lastName: "Macklin",
mood: "curious"
});
// Add computed property
user.fullName = computed(() =>
`${user.firstName} ${user.lastName}`
);
// Subscribe to changes
const unsubscribe = onUpdate(user, () => {
console.log("Store updated:", user.fullName);
// Update UI or trigger other actions
});
// Get a JSON snapshot at any time 📸
console.log("📸 Snapshot:");
console.log(json(user));
JSON snapshot of your store from json(user)
. Updates automatically when values change.
Integra jods sin problemas con React, Preact y Remix usando adaptadores dedicados
Integración perfecta con el ciclo de vida de componentes de React
Integración ligera para aplicaciones Preact
Integración especializada para aplicaciones Remix
import { store } from 'jods';
import { useJods } from 'jods/react';
const contador = store({ cuenta: 0 });
function Counter() {
const state = useJods(contador);
return (
<button onClick={() => contador.cuenta++}>
Contador: {state.cuenta}
</button>
);
}
💎Capa de Datos Moderna para Remix:
reactiva, tipada y lista para persistencia
Estado del servidor y cliente sin hidratación manual
Para actualizaciones optimistas de UI
Para validación de tipos en tiempo de ejecución y excelente DX
(Prisma, MongoDB, SQLite, etc.)
Patrón uniforme en toda tu aplicación
// Traditional Remix Approach (without jods)
// loader.ts
export async function loader() {
const todos = await db.getTodos();
return json({ todos });
}
// action.ts
export async function action({ request }) {
const form = await request.formData();
const title = form.get("title");
await db.createTodo({ title });
return redirect("/todos");
}
// Component.tsx
function Todos() {
const { todos } = useLoaderData<typeof loader>();
return (
<div>
<h1>Todos ({todos.length})</h1>
<Form method="post">
<input name="title" placeholder="New todo..." />
<button type="submit">Add</button>
</Form>
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.title}
{todo.completed ? " ✓" : ""}
</li>
))}
</ul>
</div>
);
}
// todos.jods.ts
import { j, defineStore } from "jods/remix";
// Define schema with Zod
const todoSchema = j.object({
id: j.string(),
title: j.string().min(1),
completed: j.boolean().default(false)
});
export const todos = defineStore({
name: "todos",
schema: j.object({
items: j.array(todoSchema)
}),
loader: async () => {
return { items: await db.getTodos() };
},
handlers: {
async addTodo({ current, form }) {
const title = form.get("title");
const newTodo = await db.createTodo({ title });
return {
...current,
items: [...current.items, newTodo]
};
}
}
});
// Export for route
export const loader = todos.loader;
export const action = todos.action;
// todos.tsx
import { todos } from "~/todos.jods";
import { useJods } from "jods/remix";
export default function TodosPage() {
// Type-safe access to your state and behavior
const { stores, actions, loaderData } = useJods(todos, "addTodo");
return (
<div>
<h1>Todos ({loaderData.items.length})</h1>
<ul>
{loaderData.items.map(todo => (
<li key={todo.id}>
{todo.title}
{todo.completed ? " ✓" : ""}
</li>
))}
</ul>
{/* Form with automatic action integration */}
<actions.addTodo.Form>
<input name="title" placeholder="New todo..." />
<button type="submit">Add</button>
</actions.addTodo.Form>
</div>
);
}
Brillantez en bytes — código compacto con capacidades de escala cósmica 💠
Característica | jods | Zustand | Redux | Preact Signals |
---|---|---|---|---|
📦 Tamaño del Bundle | 1 KB | 3.4 KB | 16.4 KB + Redux Toolkit | 4.2 KB |
🔗 Dependencia de Framework | 🌱 None | ⚛️ React-only | 🔌 Framework-agnostic | ⚡ Preact-only |
🔑 Acceso al Estado | Objeto proxy (store.foo) | Hook (useStore) | A través de selectores | Signal.value o JSX unwrap |
✏️ Mutaciones Directas | ✅ | ✅ | 👨💻 (requiere creadores de acciones) | signal.value = x |
🧮 Valores Calculados | 🧠 via computed() | 🔧 with selector functions | 🔧 (requires selectors) | ✨ via computed() |
📸 Instantáneas JSON | ✅ (built-in) | 📝 (manual) | ✅ (manual) | 📝 (manual) |
🔄 Diff Integrado | ✅ | 🤷 | 🤷 | 🤷 |
⏮️ Depuración Temporal | ✅ | ✅ | ✅ | ⏱️ |
🧠 Simplicidad Conceptual | ✅ small mental model | ✅ (no actions/selectors) | 🧠 (complex patterns) | 🎓 (steep learning curve) |
🖥️ Integración con Servidor | 💿 Remix | 🔍 None | ✅ (manual) | 🔍 None |