Renamed: DjangoError → MizanError DjangoHTTPClient → MizanHTTPClient DjangoFormState → MizanFormState DjangoFormsetState → MizanFormsetState createDjangoCSRClient → createMizanCSRClient createDjangoSSRClient → createMizanSSRClient ensureDjangoSession → ensureMizanSession useDjangoCSRClient → useMizanCSRClient TDjangoMessage → TServerMessage Made CSRF configurable: configureCsrf(cookieName, headerName) — defaults to Django conventions but works with any backend that uses CSRF tokens. Cookie name and header name are no longer hardcoded. All old names preserved as deprecated aliases in index.ts exports for backwards compatibility. Removed dead RouterAdapter re-export (file moved to legacy/). 33 React tests pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rythazhur/mizan (TypeScript)
React client for the mizan framework. See the monorepo root for full documentation.
Install
npm install @rythazhur/mizan@git+https://git.impactsoundworks.com/isw/mizan.git#workspace=react
Usage
You don't use this package directly. You use the generated hooks.
1. Configure
// django.config.mjs
export default {
source: {
django: {
managePath: '../backend/manage.py',
command: ['uv', 'run', 'python'],
},
},
output: 'src/api/generated.ts',
}
2. Generate
npx mizan-generate # once
npx mizan-generate --watch # dev mode
3. Wrap your app
import { DjangoContext } from '@/api'
<DjangoContext>
<App />
</DjangoContext>
DjangoContext is the only provider you need. It handles HTTP, WebSocket, CSRF, session init, context auto-fetching, and channel connections.
4. Use generated hooks
import { useCurrentUser, useEcho, useContactForm, useChatChannel } from '@/api'
// Context (SSR-hydrated, auto-refreshed)
const user = useCurrentUser()
// Server function
const echo = useEcho()
const result = await echo({ text: 'hello' })
// Form (Zod + server validation)
const form = useContactForm()
form.set('email', 'test@example.com')
await form.submit()
// Channel (WebSocket)
const chat = useChatChannel({ room: 'general' })
chat.send({ text: 'hello' })
chat.messages // typed, reactive
Generated Files
| File | Contents |
|---|---|
generated.django.tsx |
DjangoContext + typed hooks |
generated.mizan.ts |
Pydantic types |
generated.forms.ts |
Form hooks with Zod |
generated.channels.hooks.tsx |
Channel hooks |
index.ts |
Re-exports everything |
Sub-exports
| Import | When to use |
|---|---|
@rythazhur/mizan |
Core: mizanProvider, hooks, forms, errors |
@rythazhur/mizan/channels |
WebSocket channels |
@rythazhur/mizan/jwt |
JWT token management |
@rythazhur/mizan/client |
HTTP clients (CSR/SSR) |
@rythazhur/mizan/allauth |
Allauth UI components |
These are library internals used by the generated code. You should import from @/api (your generated index), not from the library directly.
Running Tests
# Unit tests (Vitest, jsdom)
npm test
# E2E tests (Playwright, real browser)
# Requires Docker backend running
npx playwright test