+
+```
+
+::callout{icon="i-heroicons-light-bulb" color="blue"}
+Proxied function calls are silently dropped when a script fails to load. This means your app won't throw errors, but the functionality simply won't be available. Always provide a fallback UI for critical features.
+::
+
+## Registry Contribution Checklist
+
+If your custom integration is useful to others, consider contributing it to the [Script Registry](/scripts). Each registry entry follows a consistent structure.
+
+### Required Files
+
+For a script called `my-service`, create the following files:
+
+| File | Purpose |
+| --- | --- |
+| `src/runtime/registry/my-service.ts` | Composable using `useRegistryScript()` |
+| `src/runtime/registry/schemas/my-service.ts` | Valibot schema for options validation |
+| `src/runtime/components/ScriptMyService.vue` | (Optional) Facade component |
+| `docs/content/scripts/analytics/my-service.md` | Documentation page |
+
+### Composable Structure
+
+Registry composables use `useRegistryScript()` instead of `useScript()` directly. This helper handles runtime config, schema validation, and the initialization lifecycle:
+
+```ts [src/runtime/registry/my-service.ts]
+import type { RegistryScriptInput } from '#nuxt-scripts/types'
+import { useRegistryScript } from '../utils'
+import { MyServiceOptions } from './schemas'
+
+export type MyServiceInput = RegistryScriptInput
+
+export interface MyServiceApi {
+ track: (event: string, properties?: Record) => void
+}
+
+export function useScriptMyService(
+ _options?: MyServiceInput,
+) {
+ return useRegistryScript('my-service', options => ({
+ scriptInput: {
+ src: `https://cdn.example.com/sdk.js?key=${options?.apiKey}`,
+ },
+ schema: import.meta.dev ? MyServiceOptions : undefined,
+ scriptOptions: {
+ use: () => window.myService as T,
+ },
+ }), _options)
+}
+```
+
+### Contribution Steps
+
+1. **Check for existing requests** -- Search the [issues](https://github.com/nuxt/scripts/issues) for your script. If there's an open request (like [#604](https://github.com/nuxt/scripts/issues/604)), comment that you're working on it.
+2. **Create the schema** -- Define a [Valibot](https://valibot.dev/) schema in `src/runtime/registry/schemas/`. Validate required fields like API keys or token lengths.
+3. **Implement the composable** -- Follow the structure above. Use `clientInit` for any global setup code that needs to run before the script loads.
+4. **Write documentation** -- Add a docs page under `docs/content/scripts/` in the appropriate category. Include usage examples and a list of available options.
+5. **Add tests** -- Registry scripts have end-to-end tests in `test/`. Check an existing test like `google-analytics.test.ts` for the pattern.
+6. **Open a PR** -- Reference the issue, describe the integration, and include a screenshot of the docs page if applicable.
diff --git a/docs/content/docs/3.api/1.use-script.md b/docs/content/docs/3.api/1.use-script.md
index 76237405..e1279df4 100644
--- a/docs/content/docs/3.api/1.use-script.md
+++ b/docs/content/docs/3.api/1.use-script.md
@@ -114,3 +114,9 @@ watch(() => route.path, () => reload())
::callout{icon="i-heroicons-light-bulb" color="blue"}
Many third-party scripts have their own SPA support (e.g., `_iub.cs.api.activateSnippets()`{lang="ts"} for iubenda). Check the script's documentation before using `reload()`{lang="ts"} - their built-in methods are usually more efficient.
::
+
+## See Also
+
+- [Custom Script Patterns](/docs/guides/custom-script-patterns) - Common integration patterns for wrapping third-party scripts, including API typing, consent management, and error handling.
+- [Key Concepts](/docs/guides/key-concepts) - How proxied functions and script singletons work.
+- [Registry Scripts](/docs/guides/registry-scripts) - Pre-configured integrations for popular third-party scripts.