diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..10800c2
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 Offload Project
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
index a78dd58..d2f59af 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-
-
-
-
+
+
+
+
# inertiajs-use-api
@@ -18,24 +18,45 @@ await api.get("/api/users", { intoProp: "users" });
await api.post("/users", { reloadProps: ["users", "stats"] });
```
-## Why
+## Features
-Inertia's built-in `router` and `useForm` are great for navigating between Inertia pages, but they expect Inertia responses. For plain JSON API routes (`/api/*`), you typically drop down to `fetch` and lose the ergonomics — processing flag, field errors, abort, lifecycle callbacks, etc.
+- **`useForm`-style ergonomics** — `data`, `errors`, `processing`, `cancel`, and lifecycle callbacks for plain JSON routes
+- **Inertia prop integration** — pipe responses into `page.props` client-side (`intoProp`) or trigger a partial reload (`reloadProps`)
+- **Pluggable error parsing** — adapt any backend's validation envelope into a flat `{ field: message }` map
+- **Pluggable toast hooks** — wire your notification system once at boot
+- **XSRF out of the box** — reads Laravel's `XSRF-TOKEN` cookie by default, fully overridable
+- **AbortSignal-aware** — cancel a single call or all in-flight requests for the hook
+- **Zero runtime dependencies** — native `fetch` under the hood, only `react` and `@inertiajs/core` as peers
+- **Strongly typed** — generic over form shape and response shape
-`useApi` gives you that ergonomics back, and lets you pipe responses into Inertia page props when you want them to live in `usePage()` alongside server-rendered data.
+## Table of Contents
+
+- [Requirements](#requirements)
+- [Installation](#installation)
+- [Quick Start](#quick-start)
+- [Inertia Prop Integration](#inertia-prop-integration)
+ - [`intoProp` — client-side write](#intoprop--write-the-response-into-pageprops-client-side)
+ - [`reloadProps` — server roundtrip](#reloadprops--refresh-props-from-the-server)
+ - [Choosing between them](#choosing-between-them)
+- [Configuration](#configuration)
+- [API Reference](#api-reference)
+- [AI Coding Assistant Skill](#ai-coding-assistant-skill)
+- [Contributing](#contributing)
+- [Security](#security)
+- [License](#license)
+
+## Requirements
-## Install
+- React 18 or 19
+- `@inertiajs/core` 2 or 3
+
+## Installation
```sh
npm install inertiajs-use-api
```
-Peer dependencies:
-
-- `@inertiajs/core@^2 || ^3`
-- `react@^18 || ^19`
-
-## Quick start
+## Quick Start
```tsx
import { useApi } from "inertiajs-use-api";
@@ -72,7 +93,13 @@ function CreateUserForm() {
}
```
-## Inertia prop integration
+## Why
+
+Inertia's built-in `router` and `useForm` are great for navigating between Inertia pages, but they expect Inertia responses. For plain JSON API routes (`/api/*`), you typically drop down to `fetch` and lose the ergonomics — processing flag, field errors, abort, lifecycle callbacks, etc.
+
+`useApi` gives you that ergonomics back, and lets you pipe responses into Inertia page props when you want them to live in `usePage()` alongside server-rendered data.
+
+## Inertia Prop Integration
### `intoProp` — write the response into `page.props` client-side
@@ -178,7 +205,7 @@ configureUseApi({
| `onErrorToast` | `(toast: unknown) => void` | no-op |
| `onResponse` | `(body, status, ok) => void` | no-op |
-## API
+## API Reference
### `useApi(initialData?)`
@@ -234,13 +261,13 @@ try {
}
```
-## Notes
+### Notes
- The hook uses native `fetch` and reads/writes Inertia state only when you ask it to (`intoProp`, `reloadProps`).
- `@inertiajs/react` is **not** a peer dep — only `@inertiajs/core` is. Use whichever Inertia adapter your app uses to read updated props.
- All in-flight requests for a given hook share `processing` and can be cancelled together via `cancel()`.
-## For AI agents
+## AI Coding Assistant Skill
This package ships an [Anthropic Skill](https://docs.claude.com/en/docs/agents-and-tools/skills) at the package root so coding agents (Claude Code, Claude.ai) can use the library correctly without needing to grep through source.
@@ -261,6 +288,17 @@ ln -s "$PWD/node_modules/inertiajs-use-api/SKILL.md" ~/.claude/skills/inertiajs-
Contributors hacking on the library itself should read [`AGENTS.md`](./AGENTS.md) — picked up automatically by Cursor, Windsurf, Cline, and similar in-repo agents.
+## Contributing
+
+Contributions are welcome! Please see the documents below before getting started.
+
+- [Contributing Guide](CONTRIBUTING.md) — setup, workflow, commit conventions, and PR process
+- [Code of Conduct](CODE_OF_CONDUCT.md) — expectations for participation in this project
+
+## Security
+
+- [Security Policy](SECURITY.md) — how to report a vulnerability privately
+
## License
-MIT
+The MIT License (MIT). Please see [License File](LICENSE.md) for more information.