#llmsmap.me

Audit technique indépendant

state-in-url.dev

state-in-url.dev

Score global de préparation IA

Résultat combiné de tous les signaux de l’audit.

83sur 100Excellent
Audit de préparation IA: 21/07/2026Données techniques publiques

Évaluation globale de préparation IA

Niveau de préparation de state-in-url.dev pour les systèmes d’IA

83/100

state-in-url (state-in-url.dev) a obtenu 83/100 lors de l’audit technique automatisé de préparation à l’IA. llms.txt était accessible, llms-full.txt était introuvable et ai.txt était introuvable. L’analyse de robots.txt a trouvé 0 robots IA explicitement autorisés, 0 bloqués et 1 sitemap déclaré. La complétude du balisage de la page d’accueil atteint 80% ; types Schema.org détectés : SoftwareApplication. Balises OpenGraph détectées : 10. Les résultats correspondent aux réponses publiques observées le 2026-07-21T05:47:11.824Z.

Contexte de l’évaluation

L’audit combine les fichiers lisibles par les machines, les règles des robots, les sitemaps et le balisage de la page d’accueil. llms.txt est accessible et contient 2 702 jetons.

robots.txt est disponible ; robots IA bloqués : 0. Sitemaps déclarés : 1. Types Schema.org : SoftwareApplication.

Profil Lighthouse mobile : performance 83/100, accessibilité 100/100, SEO 100/100.

Points forts confirmés

  • llms.txt est accessible
  • La structure publique du site a été vérifiée
  • 1 sitemap(s) déclaré(s)
  • Schema.org : SoftwareApplication

Améliorations prioritaires

  1. 1Ajouter llms-full.txt pour fournir un contexte plus riche.
Jetons llms.txt2 702
Jetons llms-full.txt
ai.txt
sitemap.xml

Profil technique Google Lighthouse

Une mesure Lighthouse mobile. La catégorie expérimentale Agentic Browsing est présentée séparément et ne remplace pas le score global de LLMSMap.

Mobile · Lighthouse
83

Performance

100

Accessibilité

100

Bonnes pratiques

100

SEO technique

100

Agentic Browsing

Interprétation des résultats

La performance mobile est de 83/100 ; le plus grand contenu visible est apparu en 4.1 s et le thread principal a été bloqué pendant 220 ms. Le décalage de mise en page est de 0. Les tâches longues retardent les actions des utilisateurs et des agents de navigateur.

Accessibilité : 100/100, bonnes pratiques : 100/100, SEO technique : 100/100. La catégorie expérimentale Agentic Browsing atteint 100/100 et reste distincte du score global de LLMSMap.

1

Libérer le thread principal et accélérer le premier écran

Découpez les longues tâches JavaScript, différez les scripts et styles non critiques et réduisez les chaînes de requêtes bloquantes.

2

Réduire le code chargé inutilement

Supprimez le CSS et le JavaScript inutilisés, chargez les widgets lourds à la demande et limitez les scripts tiers.

FCP1.0 s

Premier contenu

LCP4.1 s

Contenu principal

CLS0

Stabilité visuelle

TBT220 ms

Temps de blocage

SI2.8 s

Vitesse visuelle

Glossaire des métriques
FCP · Premier contenu
Moment où le premier texte ou la première image apparaît.
LCP · Contenu principal
Moment où le plus grand élément visible est affiché.
CLS · Stabilité visuelle
Déplacements inattendus pendant le chargement ; une valeur basse est préférable.
TBT · Temps de blocage
Durée pendant laquelle le thread principal ne pouvait pas répondre rapidement.
SI · Vitesse visuelle
Vitesse à laquelle la zone visible s’est remplie de contenu.
21/07/2026Lighthouse 13.4.0Profil mobile

Vérifications de préparation IA

Fichiers lisibles par les machines, règles des robots, découverte et balisage de la page d’accueil.

llms.txt

Fichier trouvé et accessible

https://state-in-url.dev/llms.txt
llms-full.txt

La version complète est introuvable

ai.txt

Le fichier ai.txt est introuvable

robots.txt

Fichier trouvé

https://state-in-url.dev/robots.txt
Sitemap dans robots.txt1

1 sitemap trouvé

Schema.org (JSON-LD)

Types : SoftwareApplication

OpenGraph80%

10 balises OpenGraph trouvées

Accès des robots IA

D’après l’analyse de robots.txt

GPTBotNon mentionné
OAI-SearchBotNon mentionné
ChatGPT-UserNon mentionné
Google-ExtendedNon mentionné
ClaudeBotNon mentionné
Claude-SearchBotNon mentionné
Claude-UserNon mentionné
BytespiderNon mentionné
CCBotNon mentionné
PerplexityBotNon mentionné
Perplexity-UserNon mentionné

Sitemaps

Parcours de découverte déclarés pour les robots et les agents.

Balises OpenGraph

Métadonnées d’aperçu social détectées sur la page d’accueil.

Complétude du balisage: 80%
og:titlestate-in-url - store state in URL like in JSON, type-safe
og:descriptionStore any user state in query parameters; imagine JSON in a browser URL, while keeping types and structure of data. For Next.js, React-router and pure JS
og:urlhttps://state-in-url.dev
og:site_namestate-in-url.dev
og:localeen_US
og:image:width1280
og:image:height640
og:image:altstate-in-url library image
og:typewebsite

Balisage Schema.org

Entités et propriétés structurées exposées sur la page d’accueil.

Types : 1 · Propriétés : 5
SoftwareApplication
namestate-in-url
urlhttps://state-in-url.dev
descriptionNPM Library to store complex state objects in browser URL, while preserving types and structure, solution for deep links and URL state synchronization, for Next.JS 14-16 and React-router, hooks for pure React.
sameAshttps://state-in-url.netlify.app
authorhttps://asmyshlyaev177.dev/
# state-in-url

A React hook library for storing typed, JSON-serializable state in URL query parameters. ~2 KB, zero runtime deps.

## For AI coding agents — preferred path

This package ships task-focused SKILL.md files via [@tanstack/intent](https://tanstack.com/intent/latest/docs/overview). If your agent supports Intent, that is the right surface to load instead of this file:

```bash
# in the user's project, once
npx @tanstack/intent@latest install
# list skills available for installed libraries
npx @tanstack/intent@latest list
# load a specific skill into the current context
npx @tanstack/intent@latest load state-in-url#feature-state-hook
```

Available skills (under `node_modules/state-in-url/skills/`):

| Skill | Type | When to load |
|---|---|---|
| `feature-state-hook` | core | Defining state and wrapping `useUrlState` in a feature-scoped custom hook |
| `input-handling` | core | Text inputs / sliders / fast-changing controls |
| `nextjs-ssr` | framework | Next.js App Router: `searchParams` forwarding, Proxy for layouts |
| `react-router-remix-setup` | framework | React Router v6/v7 or Remix v2 setup |
| `form-library-integration` | composition | Pairing with `react-hook-form` (or formik) |
| `shared-state-no-url` | core | `useSharedState` — cross-component state without URL sync |

The rest of this file is a condensed reference for agents that cannot load Intent skills.

## Package info

- npm: https://www.npmjs.com/package/state-in-url
- repo: https://github.com/asmyshlyaev177/state-in-url
- website: https://state-in-url.dev
- full README: https://raw.githubusercontent.com/asmyshlyaev177/state-in-url/refs/heads/master/README.md

## Supported frameworks

| Framework | Versions | Import path |
|---|---|---|
| Next.js (App Router only) | 14 / 15 / 16 | `state-in-url/next` |
| React Router | v7 | `state-in-url/react-router` |
| React Router | v6 | `state-in-url/react-router6` |
| Remix | v2 | `state-in-url/remix` |
| Framework-agnostic | — | `state-in-url` (`useSharedState`), `state-in-url/encodeState` |

Pages Router is **not** supported.

## Install

```bash
npm install state-in-url
```

In `tsconfig.json`, ensure `"moduleResolution": "Bundler"` (or `"Node16"` / `"NodeNext"`).

## Core rules — read first

1. **Type, never interface.** The hook's generic constraint `JSONCompatible<T>` rejects `interface`. Always declare a `type` AND annotate the const: `const FOO_STATE: FooState = { ... }`.
2. **Default-state object must be a module-scoped `const`.** Never built from props, hook returns, or destructuring inside a component. Sharing is keyed by object identity.
3. **One feature → one shared default-state const → one custom hook.** Components import the hook, never `useUrlState` directly with their own defaults object.
4. **No secrets in URL.** Entity IDs (`jobId`, `memberId`) are fine; tokens, API keys, PII are not.
5. **JSON-serializable only.** Functions, BigInt, Symbol, Map, Set, class instances will not round-trip. Dates are supported.
6. **URL size**: keep total query-string under ~12 KB to stay safe across CDNs (Vercel header limit is 14 KB).

## API: `useUrlState`

```typescript
const { urlState, setState, setUrl, reset } = useUrlState(DEFAULT_STATE, options?);
```

- `urlState` — current state, typed identically to `DEFAULT_STATE`.
- `setState(value)` — updates internal state synchronously; **does not touch URL**.
- `setUrl(value, opts?)` — updates state + URL. URL write is throttled (next tick).
- `reset(opts?)` — sets state and URL back to `DEFAULT_STATE`.

Setter call signatures (both `setState` and `setUrl`):
```typescript
setUrl({ field: 'newValue' });                          // partial patch
setUrl(curr => ({ ...curr, field: 'newValue' }));       // functional with current
setUrl((curr, initial) => initial);                     // reset via callback
setUrl();                                               // flush current state to URL
```

`options` (per-call or as hook-level defaults):
- `replace?: boolean` — `router.replace` (default `true`) vs `router.push`.
- `scroll?: boolean` — Next.js scroll behavior (default `false`).
- React Router / Remix: any `NavigateOptions` (e.g. `preventScrollReset`).

Hook-level options (second arg to `useUrlState`):
- `searchParams` — pass `searchParams` from a Next.js server component or `useSearchParams()` from a client component. **Required for SSR correctness in Next.js App Router.**
- `useHistory?: boolean` — Next.js only. Default `true`. Uses `window.history.pushState` to avoid `_rsc` server round-trips on URL changes. Flip to `false` only when server data must refetch on URL change.

## Recommended pattern: feature-scoped hook

```typescript
// features/jobs/jobsState.ts
export type JobsState = {
  status: '' | 'active' | 'closed';
  tab: 'details' | 'qa' | 'applicants';
  jobId: string;
};

export const JOBS_STATE: JobsState = {
  status: '',
  tab: 'details',
  jobId: '',
};
```

```typescript
// features/jobs/useJobsState.ts
'use client';
import { useSearchParams } from 'next/navigation';
import { useUrlState } from 'state-in-url/next';
import { JOBS_STATE } from './jobsState';

export function useJobsState() {
  const searchParams = useSearchParams();
  return useUrlState(JOBS_STATE, { searchParams });
}
```

Any component calling `useJobsState()` shares the same URL-synced store. No Context, no Provider.

## Next.js App Router — server page forwarding `searchParams`

In **Next.js 15+**, `searchParams` is a `Promise`:

```typescript
// app/jobs/page.tsx  (Server Component)
import { JobsList } from './JobsList';

export default async function Page({
  searchParams,
}: {
  searchParams: Promise<Record<string, string | string[] | undefined>>;
}) {
  const sp = await searchParams;
  return <JobsList searchParams={sp} />;
}

// app/jobs/JobsList.tsx
'use client';
import { useUrlState } from 'state-in-url/next';
import { JOBS_STATE } from 'features/jobs/jobsState';

export function JobsList({ searchParams }: { searchParams: object }) {
  const { urlState, setUrl } = useUrlState(JOBS_STATE, { searchParams });
  // ...
}
```

Without `searchParams`, the first render uses defaults, then a client effect re-syncs from the URL on the next tick — visible flash plus hydration warning.

## Next.js App Router — server layout (Proxy workaround)

Server layouts don't receive `searchParams`. Expose the query string via a Proxy header (Next.js 16+; `middleware.ts` still works as a deprecated alias):

```typescript
// proxy.ts
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';

export function proxy(request: NextRequest) {
  const sp = (request.url.includes('_next') ? '' : request.url).split('?')[1] ?? '';
  const headers = new Headers(request.headers);
  headers.set('searchParams', sp);
  return NextResponse.next({ request: { headers } });
}
```

```typescript
// app/jobs/layout.tsx
import { headers } from 'next/headers';
import { decodeState } from 'state-in-url/encodeState';
import { JOBS_STATE } from 'features/jobs/jobsState';

export default async function Layout({ children }: { children: React.ReactNode }) {
  const sp = (await headers()).get('searchParams') ?? '';
  const initial = decodeState(sp, JOBS_STATE);
  return <>{/* use `initial` */}{children}</>;
}
```

## Input handling — instant feedback, deferred URL write

For text inputs and other fast-changing controls, split `setState` (instant render) and `setUrl` (URL flush):

```typescript
<input
  value={urlState.q}
  onChange={(e) => setState({ q: e.target.value })}
  onBlur={() => setUrl()}
/>
```

`setUrl()` with no args flushes the current state to the URL with content-based diffing — safe to call repeatedly.

## React Router and Remix

API is identical to the Next.js variant; only the import path and `NavigateOptions` differ.

```typescript
import { useUrlState } from 'state-in-url/react-router';   // RR v7
import { useUrlState } from 'state-in-url/react-router6';  // RR v6 (since 6.0.0)
import { useUrlState } from 'state-in-url/remix';          // Remix v2

setUrl({ tab: 'b' }, { replace: false, preventScrollReset: true });
```

## react-hook-form integration

Share one defaults object, hydrate `useForm` from `urlState`, push form changes back via RHF `subscribe()` (not `watch()`):

```typescript
const { urlState, setUrl } = useUrlState(FILTERS_STATE, { searchParams });
const form = useForm<FiltersState>({ defaultValues: urlState });

React.useEffect(() => {
  const sub = form.subscribe({
    formState: { values: true },
    callback: ({ values }) => setUrl(values),
  });
  return () => sub();
}, [form, setUrl]);
```

## `useSharedState` — cross-component state without URL

```typescript
import { useSharedState } from 'state-in-url';

const CART_STATE: CartState = { items: [], isOpen: false };
const { state, setState } = useSharedState(CART_STATE);
```

Same module-scoped default-state-identity rule. Use only when URL sync is explicitly NOT wanted.

## Common mistakes (CRITICAL — fix any agent generating these)

| Mistake | Fix |
|---|---|
| `defaultState` defined inside a React component | Move to a module-scoped `const`, annotated with a `type` |
| `interface FeatureState { ... }` for state shape | Use `type FeatureState = { ... }` |
| `setUrl` inside `useEffect` with `urlState` in deps | Causes infinite loop; gate on the actual change or derive on read |
| Two components each declaring `const DEFAULTS = {...}` | Export one const from a shared file; components import the hook |
| `setUrl`/`setState` called during render | Move into a handler or effect |
| `interface` instead of `type` | Same as above; `type` is required |
| Reading `searchParams` in a Next.js server layout | Use the Proxy + `headers()` + `decodeState` pattern |
| Using `state-in-url/next` in Pages Router | Not supported; use App Router or build a custom hook with `useUrlStateBase` |
| Importing `state-in-url/react-router` in a RR v6 project | Use `state-in-url/react-router6` (moved in 6.0.0) |
| `setUrl({...})` for fast typing inputs | Use `setState` on change, `setUrl()` on blur |
| Mutating `urlState` directly | Always go through `setState`/`setUrl` |
| Storing functions / `BigInt` / `Symbol` / `Map` / `Set` | Not serializable; use plain JSON-compatible values (Date is OK) |
| Storing tokens / API keys / passwords / PII in URL | Use auth storage; URL state is fully public |

## Documentation resources

- Full README (humans): https://github.com/asmyshlyaev177/state-in-url/blob/master/README.md
- URL size limits: https://github.com/asmyshlyaev177/state-in-url/blob/master/Limits.md
- Working examples per framework: `packages/example-nextjs{14,15,16}`, `packages/example-react-router{6,7}`, `packages/example-remix2`
- JSDoc comments are available in IDE for all exported functions
Partager ou poursuivre l’analyse
Partager cet audit
Discuter avec une IA
Ajouté 19/07/2026
state-in-url.dev – audit de préparation IA | llmsmap.me/fr