diff --git a/apps/docs/src/config/llmsCustomSets.ts b/apps/docs/src/config/llmsCustomSets.ts
index 54b4bd2ed..4d5b57625 100644
--- a/apps/docs/src/config/llmsCustomSets.ts
+++ b/apps/docs/src/config/llmsCustomSets.ts
@@ -66,6 +66,7 @@ Plugin Native Purchases|in-app purchases and subscriptions plugin|docs/plugins/n
Plugin Navigation Bar|Android navigation bar customization plugin|docs/plugins/navigation-bar/**
Plugin NFC|NFC reading and writing plugin|docs/plugins/nfc/**
Plugin Pay|Apple Pay and Google Pay integration plugin|docs/plugins/pay/**
+Plugin Passkey|browser-style WebAuthn passkey plugin with native shims and generated platform configuration|docs/plugins/passkey/**
Plugin Privacy Screen|privacy screen plugin for hiding app content in system previews and screenshots|docs/plugins/privacy-screen/**
Plugin PDF Generator|PDF generation plugin|docs/plugins/pdf-generator/**
Plugin Pedometer|step counting pedometer plugin|docs/plugins/pedometer/**
diff --git a/apps/docs/src/config/sidebar.mjs b/apps/docs/src/config/sidebar.mjs
index 1f5267835..be825aeb5 100644
--- a/apps/docs/src/config/sidebar.mjs
+++ b/apps/docs/src/config/sidebar.mjs
@@ -133,6 +133,11 @@ const pluginEntries = [
['Navigation Bar', 'navigation-bar'],
['NFC', 'nfc'],
['Pay', 'pay'],
+ [
+ 'Passkey',
+ 'passkey',
+ [linkItem('iOS setup', '/docs/plugins/passkey/ios'), linkItem('Android setup', '/docs/plugins/passkey/android'), linkItem('Backend notes', '/docs/plugins/passkey/backend')],
+ ],
['Privacy Screen', 'privacy-screen', [linkItem('iOS behavior', '/docs/plugins/privacy-screen/ios'), linkItem('Android behavior', '/docs/plugins/privacy-screen/android')]],
['PDF Generator', 'pdf-generator'],
['Pedometer', 'pedometer'],
diff --git a/apps/docs/src/content/docs/docs/plugins/passkey/android.mdx b/apps/docs/src/content/docs/docs/plugins/passkey/android.mdx
new file mode 100644
index 000000000..8c5abbb80
--- /dev/null
+++ b/apps/docs/src/content/docs/docs/plugins/passkey/android.mdx
@@ -0,0 +1,59 @@
+---
+title: Android Setup
+description: Configure passkeys on Android for @capgo/capacitor-passkey with Digital Asset Links and assetlinks.json.
+sidebar:
+ order: 4
+---
+
+On Android, passkeys work with your website when the app and the relying-party domain are connected through Digital Asset Links.
+
+## What the plugin handles
+
+After you add the plugin config and run `bunx cap sync`, the plugin patches the generated Android host project:
+
+- injects the `asset_statements` manifest metadata
+- writes the generated string resource referenced by that metadata
+
+## What you still need to host
+
+You must publish `assetlinks.json` on the relying-party domain:
+
+```text
+https://signin.example.com/.well-known/assetlinks.json
+```
+
+Example:
+
+```json
+[
+ {
+ "relation": [
+ "delegate_permission/common.handle_all_urls",
+ "delegate_permission/common.get_login_creds"
+ ],
+ "target": {
+ "namespace": "android_app",
+ "package_name": "app.capgo.passkey.example",
+ "sha256_cert_fingerprints": [
+ "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99"
+ ]
+ }
+ }
+]
+```
+
+## Checklist
+
+1. Set `origin` and `domains` in `plugins.CapacitorPasskey` in `capacitor.config.*`.
+2. Run `bunx cap sync`.
+3. Use your real Android package name in `assetlinks.json`.
+4. Add every signing certificate fingerprint you need, including debug or internal signing keys if you test those builds.
+5. Host the file on the same domain you use as the relying-party ID.
+
+## Important behavior difference from a browser
+
+With Digital Asset Links configured, Android can use the same relying party and passkeys as your website. The remaining difference is the literal origin reported in native `clientDataJSON`.
+
+- A normal Android app does not behave like a privileged browser.
+- The assertion origin can be tied to the Android app signature instead of your website origin.
+- If your backend strictly validates `clientDataJSON.origin`, accept the Android app origin alongside the website origin.
diff --git a/apps/docs/src/content/docs/docs/plugins/passkey/backend.mdx b/apps/docs/src/content/docs/docs/plugins/passkey/backend.mdx
new file mode 100644
index 000000000..5f6151ca9
--- /dev/null
+++ b/apps/docs/src/content/docs/docs/plugins/passkey/backend.mdx
@@ -0,0 +1,57 @@
+---
+title: Backend Notes
+description: Understand the backend contract for @capgo/capacitor-passkey, including WebAuthn challenge handling and Android origin validation.
+sidebar:
+ order: 5
+---
+
+Your backend still owns the normal WebAuthn ceremony:
+
+- generate registration and authentication challenges
+- verify attestation and assertion responses
+- enforce relying-party ID and challenge validation
+- store credentials and counters the same way you would for a browser flow
+
+## What stays the same
+
+The plugin is designed to preserve the front-end shape of your existing WebAuthn code.
+
+- On the web, it forwards to the real browser WebAuthn API.
+- On native Capacitor, it returns browser-like credential objects backed by native passkey APIs.
+- Your backend can keep the same challenge and verification pipeline.
+
+## What changes on Android
+
+Android native passkeys are not identical to a browser trust model.
+
+- Digital Asset Links let Android share the same relying party and credential ecosystem as your website.
+- The literal `clientDataJSON.origin` value can still differ from the website origin.
+- If your server rejects anything except `https://your-domain`, Android native assertions can fail even when the passkey is otherwise valid.
+
+## Recommended backend rule
+
+Allow the expected browser origin and the expected Android app origin for the same relying party when you support native Android passkeys.
+
+That gives you:
+
+- browser support for the website
+- native passkey support in the Capacitor app
+- one passkey ecosystem for the same relying-party domain
+
+## If you need direct JSON-safe calls
+
+If your backend already returns `PublicKeyCredentialCreationOptionsJSON` and `PublicKeyCredentialRequestOptionsJSON`, you can also use the direct plugin API instead of the browser-style shim:
+
+```ts
+import { CapacitorPasskey } from '@capgo/capacitor-passkey';
+
+const registration = await CapacitorPasskey.createCredential({
+ origin: 'https://signin.example.com',
+ publicKey: registrationOptionsFromBackend,
+});
+
+const authentication = await CapacitorPasskey.getCredential({
+ origin: 'https://signin.example.com',
+ publicKey: requestOptionsFromBackend,
+});
+```
diff --git a/apps/docs/src/content/docs/docs/plugins/passkey/getting-started.mdx b/apps/docs/src/content/docs/docs/plugins/passkey/getting-started.mdx
new file mode 100644
index 000000000..a61fa19ab
--- /dev/null
+++ b/apps/docs/src/content/docs/docs/plugins/passkey/getting-started.mdx
@@ -0,0 +1,96 @@
+---
+title: Getting Started
+description: Install @capgo/capacitor-passkey, configure the plugin once, and keep your browser-style WebAuthn code in a Capacitor app.
+sidebar:
+ order: 2
+---
+
+import { Steps, Card, CardGrid } from '@astrojs/starlight/components';
+import { PackageManagers } from 'starlight-package-managers'
+
+
+1. **Install the package**
+
+
+2. **Sync native projects**
+
+
+3. **Add the plugin config**
+
+ ```ts
+ import type { CapacitorConfig } from '@capacitor/cli';
+
+ const config: CapacitorConfig = {
+ appId: 'app.capgo.passkey.example',
+ appName: 'My App',
+ webDir: 'dist',
+ plugins: {
+ CapacitorPasskey: {
+ origin: 'https://signin.example.com',
+ autoShim: true,
+ domains: ['signin.example.com'],
+ },
+ },
+ };
+
+ export default config;
+ ```
+
+4. **Import the shim once**
+
+ ```ts
+ import '@capgo/capacitor-passkey/auto';
+ ```
+
+5. **Keep your normal WebAuthn flow**
+
+ ```ts
+ const registration = await navigator.credentials.create({
+ publicKey: registrationOptions,
+ });
+
+ const authentication = await navigator.credentials.get({
+ publicKey: requestOptions,
+ });
+ ```
+
+
+## What the plugin config does
+
+The config is read from `plugins.CapacitorPasskey` in `capacitor.config.*`.
+
+- `origin`: primary HTTPS relying-party origin used by the shim and direct API
+- `domains`: extra relying-party hostnames to patch into native config during sync
+- `autoShim`: defaults to `true` when you use `@capgo/capacitor-passkey/auto`
+
+## What sync patches for you
+
+When you run `bunx cap sync`, the plugin updates the generated native host project:
+
+- iOS: associated domains entitlements and Xcode entitlements wiring when needed
+- Android: `asset_statements` metadata and the generated resource used by the manifest
+
+The hook does not publish your website trust files for you. You still need to host:
+
+- `https://your-domain/.well-known/apple-app-site-association`
+- `https://your-domain/.well-known/assetlinks.json`
+
+## Platform guides
+
+
+
+
+ Associated Domains and `apple-app-site-association`.
+
+
+
+
+ Digital Asset Links and `assetlinks.json`.
+
+
+
+
+ Origin validation and Android caveats.
+
+
+
diff --git a/apps/docs/src/content/docs/docs/plugins/passkey/index.mdx b/apps/docs/src/content/docs/docs/plugins/passkey/index.mdx
new file mode 100644
index 000000000..6b9a54574
--- /dev/null
+++ b/apps/docs/src/content/docs/docs/plugins/passkey/index.mdx
@@ -0,0 +1,38 @@
+---
+title: "@capgo/capacitor-passkey"
+description: Passkeys for Capacitor with a browser-style WebAuthn shim, minimal JavaScript changes, and native setup generated during sync.
+tableOfContents: false
+next: false
+prev: false
+sidebar:
+ order: 1
+ label: "Introduction"
+hero:
+ tagline: Keep your browser-style WebAuthn code in a Capacitor app while the plugin handles native passkey calls and native host patching.
+ actions:
+ - text: Get started
+ link: /docs/plugins/passkey/getting-started/
+ icon: right-arrow
+ variant: primary
+ - text: GitHub
+ link: https://github.com/Cap-go/capacitor-passkey/
+ icon: external
+ variant: minimal
+---
+
+import { Card, CardGrid } from '@astrojs/starlight/components';
+
+
+
+ Keep `navigator.credentials.create()` and `navigator.credentials.get()` in your app instead of rewriting your passkey flow around a custom API.
+
+
+ Add plugin config once, import `@capgo/capacitor-passkey/auto`, and keep the rest of your WebAuthn code close to the browser implementation.
+
+
+ The plugin patches the generated iOS and Android host projects during sync so you do not need to keep hand-editing those files.
+
+
+ Follow the [Getting Started](/docs/plugins/passkey/getting-started/), [iOS setup](/docs/plugins/passkey/ios/), [Android setup](/docs/plugins/passkey/android/), and [backend notes](/docs/plugins/passkey/backend/).
+
+
diff --git a/apps/docs/src/content/docs/docs/plugins/passkey/ios.mdx b/apps/docs/src/content/docs/docs/plugins/passkey/ios.mdx
new file mode 100644
index 000000000..a91ee0ea3
--- /dev/null
+++ b/apps/docs/src/content/docs/docs/plugins/passkey/ios.mdx
@@ -0,0 +1,47 @@
+---
+title: iOS Setup
+description: Configure passkeys on iOS for @capgo/capacitor-passkey with Associated Domains and the apple-app-site-association file.
+sidebar:
+ order: 3
+---
+
+On iOS, passkeys only work when the app is associated with the same relying-party domain as the website.
+
+## What the plugin handles
+
+After you add the plugin config and run `bunx cap sync`, the plugin patches the generated iOS host project so you do not need to keep editing it manually:
+
+- adds the `webcredentials:` associated domains entries for the configured domains
+- wires `CODE_SIGN_ENTITLEMENTS` when the generated app target does not already point at an entitlements file
+
+## What you still need to host
+
+You must publish `apple-app-site-association` on the relying-party domain:
+
+```text
+https://signin.example.com/.well-known/apple-app-site-association
+```
+
+Example:
+
+```json
+{
+ "webcredentials": {
+ "apps": ["ABCDE12345.app.capgo.passkey.example"]
+ }
+}
+```
+
+## Checklist
+
+1. Set `origin` and `domains` in `plugins.CapacitorPasskey` in `capacitor.config.*`.
+2. Run `bunx cap sync`.
+3. Confirm your Apple Team ID and app bundle ID, then build the `TEAMID.bundleId` value for the association file.
+4. Host `apple-app-site-association` with HTTP `200` and no `.json` extension.
+5. Make sure the relying-party ID used by your backend matches the associated domain.
+
+## Notes
+
+- The website file must be served from the exact passkey domain you use as the relying-party ID.
+- On iOS 17.4 and newer, the plugin uses the browser-style client-data API so the configured HTTPS origin is reflected in `clientDataJSON`.
+- The plugin can patch native project files during sync, but it cannot create or host the website association file on your domain.
diff --git a/apps/web/src/config/plugins.ts b/apps/web/src/config/plugins.ts
index afd6b5ef6..fd50c63d6 100644
--- a/apps/web/src/config/plugins.ts
+++ b/apps/web/src/config/plugins.ts
@@ -47,6 +47,7 @@ const actionDefinitionRows =
@capgo/capacitor-streamcall|github.com/Cap-go|Integrate video calling and live streaming with Stream SDK for real-time communication|https://github.com/Cap-go/capacitor-streamcall/|Streamcall
@capgo/capacitor-autofill-save-password|github.com/Cap-go|Prompt users to save passwords to device autofill for seamless login experience|https://github.com/Cap-go/capacitor-autofill-save-password/|Autofill Save Password
@capgo/capacitor-social-login|github.com/Cap-go|Authenticate users with Google, Facebook, and Apple Sign-In for easy social login|https://github.com/Cap-go/capacitor-social-login/|Social Login
+@capgo/capacitor-passkey|github.com/Cap-go|Use browser-style WebAuthn passkeys in Capacitor with a native shim and generated platform configuration|https://github.com/Cap-go/capacitor-passkey/|Passkey
@capgo/capacitor-jw-player|github.com/Cap-go|Embed JW Player for professional video streaming with ads and analytics support|https://github.com/Cap-go/capacitor-jw-player/|JW Player
@capgo/capacitor-ricoh360-camera-plugin|github.com/Cap-go|Control Ricoh Theta 360-degree cameras for immersive panoramic photography|https://github.com/Cap-go/capacitor-ricoh360-camera-plugin/|Ricoh360 Camera
@capgo/capacitor-admob|github.com/Cap-go|Monetize your app with Google AdMob banner, interstitial, and rewarded ads|https://github.com/Cap-go/capacitor-admob/|AdMob
@@ -168,6 +169,7 @@ const pluginIconsByName: Record = {
'@capgo/capacitor-streamcall': 'VideoCamera',
'@capgo/capacitor-autofill-save-password': 'UserCircle',
'@capgo/capacitor-social-login': 'UserCircle',
+ '@capgo/capacitor-passkey': 'Key',
'@capgo/capacitor-jw-player': 'PlayCircle',
'@capgo/capacitor-ricoh360-camera-plugin': 'Camera',
'@capgo/capacitor-admob': 'Megaphone',
diff --git a/apps/web/src/content/plugins-tutorials/en/capacitor-passkey.md b/apps/web/src/content/plugins-tutorials/en/capacitor-passkey.md
new file mode 100644
index 000000000..10b2b8f15
--- /dev/null
+++ b/apps/web/src/content/plugins-tutorials/en/capacitor-passkey.md
@@ -0,0 +1,95 @@
+---
+locale: en
+published: true
+---
+# Using @capgo/capacitor-passkey
+
+`@capgo/capacitor-passkey` lets a Capacitor app keep the same WebAuthn flow you already use on the web:
+
+```ts
+await navigator.credentials.create({ publicKey: registrationOptions });
+await navigator.credentials.get({ publicKey: requestOptions });
+```
+
+On native builds, the plugin installs a shim for `navigator.credentials.create()` and `navigator.credentials.get()`, forwards the request to iOS and Android passkey APIs, and returns browser-like credential objects to your app.
+
+## Install the plugin
+
+```bash
+bun add @capgo/capacitor-passkey
+bunx cap sync
+```
+
+## Configure the host app once
+
+Add the plugin config in `capacitor.config.ts` or `capacitor.config.json`:
+
+```ts
+import type { CapacitorConfig } from '@capacitor/cli';
+
+const config: CapacitorConfig = {
+ appId: 'app.capgo.passkey.example',
+ appName: 'My App',
+ webDir: 'dist',
+ plugins: {
+ CapacitorPasskey: {
+ origin: 'https://signin.example.com',
+ autoShim: true,
+ domains: ['signin.example.com'],
+ },
+ },
+};
+
+export default config;
+```
+
+Run sync again after changing the config:
+
+```bash
+bunx cap sync
+```
+
+During sync, the plugin patches the generated native host projects:
+
+- iOS: associated domains entitlements
+- Android: `asset_statements` metadata for Digital Asset Links
+
+## Import the shim once
+
+Import the auto entrypoint in your app bootstrap:
+
+```ts
+import '@capgo/capacitor-passkey/auto';
+```
+
+After that, your existing browser-style passkey code can stay the same.
+
+## Keep your normal WebAuthn flow
+
+```ts
+const credential = await navigator.credentials.create({
+ publicKey: registrationOptions,
+});
+
+const assertion = await navigator.credentials.get({
+ publicKey: requestOptions,
+});
+```
+
+## Native setup still needs website trust files
+
+The plugin reduces app-side work, but passkeys still depend on the website trust files for your relying-party domain:
+
+- iOS needs `/.well-known/apple-app-site-association`
+- Android needs `/.well-known/assetlinks.json`
+
+The detailed setup is documented here:
+
+- [Getting started](/docs/plugins/passkey/getting-started/)
+- [iOS setup](/docs/plugins/passkey/ios/)
+- [Android setup](/docs/plugins/passkey/android/)
+- [Backend notes](/docs/plugins/passkey/backend/)
+
+## Important Android caveat
+
+Android Credential Manager can share the same relying party and passkeys as your website when Digital Asset Links are configured, but the native assertion origin is not identical to a browser origin. If your backend strictly validates `clientDataJSON.origin`, make sure it accepts the Android app origin alongside your website origin.
diff --git a/apps/web/src/data/github-stars.json b/apps/web/src/data/github-stars.json
index 36316fd42..0099bbb01 100644
--- a/apps/web/src/data/github-stars.json
+++ b/apps/web/src/data/github-stars.json
@@ -47,6 +47,7 @@
"https://github.com/Cap-go/capacitor-media-session/": 4,
"https://github.com/Cap-go/capacitor-mux-player/": 4,
"https://github.com/Cap-go/capacitor-pay/": 6,
+ "https://github.com/Cap-go/capacitor-passkey/": 1,
"https://github.com/Cap-go/capacitor-pdf-generator/": 3,
"https://github.com/Cap-go/capacitor-persistent-account/": 5,
"https://github.com/Cap-go/capacitor-photo-library/": 5,
@@ -102,4 +103,4 @@
"https://github.com/Cap-go/capacitor-light-sensor/": 4,
"https://github.com/Cap-go/capacitor-video-thumbnails/": 4,
"https://github.com/Cap-go/capacitor-intent-launcher/": 6
-}
\ No newline at end of file
+}
diff --git a/apps/web/src/data/npm-downloads.json b/apps/web/src/data/npm-downloads.json
index b081fa284..3afb256a7 100644
--- a/apps/web/src/data/npm-downloads.json
+++ b/apps/web/src/data/npm-downloads.json
@@ -52,6 +52,7 @@
"@capgo/capacitor-media-session": 10546,
"@capgo/capacitor-mux-player": 1041,
"@capgo/capacitor-pay": 7144,
+ "@capgo/capacitor-passkey": 40,
"@capgo/capacitor-privacy-screen": 85,
"@capgo/capacitor-pdf-generator": 4011,
"@capgo/capacitor-persistent-account": 13383,