Skip to content
WebViewGold Vibe Coding to App Store
English
Get WebViewGold

Claude Code + deep links

Universal Links and App Links with Claude Code: open your WebViewGold app from any link

A link to your domain in an email, a chat or a magic-link login should open the app on the right screen, not a browser tab. That takes two small JSON files on your server, one capability in Xcode, one intent filter on Android and a couple of WebViewGold switches. Claude Code writes, serves and checks the files; you add the IDs and test on real phones.

From $109 one-time per platform, or let our team do it all from $698.

  • Approval guarantee – or money back within 14 days
  • No coding needed
  • One-time payment, free updates
  • 24/7 human support
  • Made in Germany since 2014 · ISO 27001

Which link type you need

Universal Links (iOS) make normal https links to your domain open the app. They need an apple-app-site-association (AASA) file on your server, the Associated Domains capability in Xcode and ShowExternalLink set to true in Config.swift (Universal Links docs).

App Links (Android) do the same on Android. They need an assetlinks.json file that proves the domain belongs to your app, an intent filter for your host in AndroidManifest.xml and IS_DEEP_LINKING_ENABLED set to true in Config.java (App Links docs).

Custom schemes such as myapp:// also exist, with different syntax per platform: on iOS myapp://url?link=https://app.example.com/page after changing the URL scheme in Info.plist, on Android myapp://https://app.example.com/page with IS_CUSTOM_SCHEME_ENABLED and CUSTOM_DEEPLINK_SCHEME matching the manifest. The iOS docs advise choosing either Universal Links or the custom scheme, not both. For links people click, https is the better choice: when the app is not installed, the same link simply opens your website.

No guideline demands deep links, but they decide whether a reviewer can sign in. A magic link or password reset that opens Safari instead of the app leaves the session in the wrong place and the reviewer stuck on your login screen. The magic links guide explains that case in detail.

What Claude Code does and what you do

Claude Code

Writes both JSON files, the hosting headers and middleware exclusions, makes every linked route work on a cold load, and builds a check script it runs against your deployment with curl and Node.

You

Provide the Team ID, bundle ID, package name and signing fingerprints, add Associated Domains in Xcode, edit the Android manifest host, flip the WebViewGold switches and build.

Apple and Google

Fetch and verify your files on their own schedule. Apple serves the file through its CDN, so changes are not instant; plan a little time for that.

iOS and Android side by side

iOS Universal LinksAndroid App Links
Server file/.well-known/apple-app-site-association, no file extension/.well-known/assetlinks.json
App identity in the fileTeam ID + bundle IDPackage name + SHA-256 of the signing certificate
Native projectAssociated Domains: applinks:app.example.com (add www separately if you use it)Intent filter with your host in AndroidManifest.xml, verified automatically
WebViewGold switchShowExternalLink = trueIS_DEEP_LINKING_ENABLED = true
Quick testTap the link in Notes or Messagesadb shell pm get-app-links and a tap in Gmail or Messages

Great work! Never coded anything but managed to work with this. Easy and fast! Also with great help from the creators!

Lucas Dubois · CodeCanyon

The Claude Code prompt

Fill in your IDs first. The check script in item 5 is worth keeping: run it after every hosting or middleware change, or ask Claude Code to register it as a hook with /hooks.

Paste into Claude Code
Set up Universal Links (iOS) and App Links (Android) for our WebViewGold apps on https://app.example.com. First read the Universal Links API and the App Links and Deep Linking API sections in https://www.webviewgold.com/llms-full.txt.

Values: Apple Team ID ABCDE12345, iOS bundle ID com.example.myapp, Android package name com.example.myapp, SHA-256 fingerprints: [app signing key from Play Console] and [upload key for local test builds].

1. Create public/.well-known/apple-app-site-association (no file extension) in the applinks format with appIDs and components. Open in the app: /app/*, /auth/callback*, /invite/*, /reset-password*. Exclude /blog/* and /pricing (place excludes first) so marketing pages stay in the browser.
2. Create public/.well-known/assetlinks.json with the relation delegate_permission/common.handle_all_urls for our package name and both fingerprints.
3. Serve both files with status 200 and Content-Type application/json, without redirects, auth middleware, password protection or bot challenges. Make sure our SPA catch-all route and middleware do not intercept /.well-known/. Configure the headers for whatever host this project uses (next.config.js headers, vercel.json, netlify _headers or similar).
4. Every route listed in item 1 must work on a cold load from the URL alone: deep links land on a URL, not on client state. Protected routes redirect to login and then back to the original path.
5. Create scripts/check-deep-links.mjs: takes a base URL, fetches both files, checks status, content type, absence of redirects, valid JSON and that the IDs match the values above. Add npm run check:links and run it against the preview deployment.
6. Write docs/deep-links.md: the manual steps for Xcode (Associated Domains capability with applinks:app.example.com, ShowExternalLink true in Config.swift) and Android Studio (intent filter host and android:autoVerify in AndroidManifest.xml, IS_DEEP_LINKING_ENABLED in Config.java), plus a list of sample links for each pattern that I can paste into Notes or send to myself, and the adb commands to test them.

Do not edit the native projects. Report what you changed and the output of the check script.

apple-app-site-association

The current format with appIDs and components. Components are evaluated in order and the first match wins, which is why the excludes come first. The app ID is your Team ID, a dot and the bundle ID.

json
{
  "applinks": {
    "details": [
      {
        "appIDs": ["ABCDE12345.com.example.myapp"],
        "components": [
          { "/": "/blog/*", "exclude": true, "comment": "Marketing pages stay in the browser" },
          { "/": "/pricing", "exclude": true },
          { "/": "/app/*", "comment": "Everything inside the web app" },
          { "/": "/auth/callback*", "comment": "Magic links and OAuth returns" },
          { "/": "/invite/*" },
          { "/": "/reset-password*" }
        ]
      }
    ]
  }
}

assetlinks.json

With Play App Signing, Google signs the builds users install, so the fingerprint that matters is the app signing key shown in the Play Console under App integrity. Add your upload key as well if you test locally signed builds.

json
[
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.example.myapp",
      "sha256_cert_fingerprints": [
        "APP_SIGNING_KEY_SHA256_FROM_PLAY_CONSOLE",
        "UPLOAD_KEY_SHA256_FOR_LOCAL_BUILDS"
      ]
    }
  }
]

Serving the files with the right headers (Next.js)

Static hosts often send a file without an extension as a download type, which Apple ignores. On Vercel without Next.js, use the headers section of vercel.json; on Netlify, a _headers file.

javascript
// next.config.js  (files live in public/.well-known/)
module.exports = {
  async headers() {
    return [
      {
        source: "/.well-known/apple-app-site-association",
        headers: [{ key: "Content-Type", value: "application/json" }],
      },
      {
        source: "/.well-known/assetlinks.json",
        headers: [{ key: "Content-Type", value: "application/json" }],
      },
    ];
  },
};

// Also check middleware.ts: exclude "/.well-known" from auth and locale redirects.

The manual steps, in order

Final IDs first: the bundle ID, package name and domain are baked into these files.

  1. Settle domain and IDs

    Deep links tie your domain to your app identity, so decide both before you start. See custom domain first and choosing the bundle ID once.

  2. Collect the values

    Apple Team ID from the membership details in your developer account, the bundle ID from Xcode, the package name, and the SHA-256 of the app signing key from the Play Console.

  3. Run the prompt and deploy

    Then run npm run check:links https://app.example.com against production. Both files must pass before you touch the native projects.

  4. iOS project

    In the Apple Developer portal, enable Associated Domains for the App ID. In Xcode, select the WebViewGold target, open Signing & Capabilities, add Associated Domains with applinks:app.example.com (and the www variant if you link to it), and set ShowExternalLink to true in Config.swift.

  5. Android project

    In AndroidManifest.xml, replace the sample host in the deep-link intent filter with your domain and make sure it carries android:autoVerify="true". Set IS_DEEP_LINKING_ENABLED to true in Config.java.

  6. Build and install

    TestFlight and internal testing. Install from the store tracks so the Android build carries the Play signing certificate that your assetlinks.json names. The Cloud Builder can produce both builds if you do not have the IDEs installed.

Verification checklist

  • curl -sI https://app.example.com/.well-known/apple-app-site-association returns 200, application/json and no redirect. Apple fetches the file through its CDN; https://app-site-association.cdn-apple.com/a/v1/app.example.com shows the version Apple currently has.
  • Google's Digital Asset Links API (digitalassetlinks.googleapis.com/v1/statements:list with your site and the handle_all_urls relation) returns your statement.
  • iPhone: paste a link into Notes or send it to yourself in Messages and tap it: the app opens on that page. A long press offers to open it in your app. Typing the URL into Safari's address bar does not open the app; that is by design.
  • Android: adb shell pm get-app-links com.example.myapp shows your domain as verified. A tap in Gmail or Messages opens the app; adb shell am start -a android.intent.action.VIEW -d "https://app.example.com/app/orders/42" com.example.myapp lands on the right page.
  • With the app uninstalled, the same links open the website normally.
  • Request a magic link or password reset inside the app, open the email on the same phone: the app opens and the user is signed in.
  • A push notification whose url points to /app/orders/42 opens the same page; see the push guide.

Pitfalls

  • Redirects. If app.example.com redirects to www (or the other way), the file request fails verification. Serve the file on every host you list, with no redirect.
  • The wrong fingerprint. The upload key is not the key users' builds are signed with under Play App Signing. Copy the app signing key from the Play Console.
  • The SPA answers instead of the file. A catch-all route returns your index.html with status 200 for /.well-known/apple-app-site-association. The check script catches it because the JSON parse fails.
  • Security layers. Password-protected previews, auth middleware and bot challenges block Apple's and Google's fetchers just like a stranger.
  • Caching. Apple's CDN does not pick up a changed AASA file instantly. Reinstall the app on your test device after changes and allow time before concluding it is broken.
  • PKCE magic links across contexts. A magic link requested in desktop Safari and opened in the app cannot complete a PKCE login, because the code verifier lives in the browser that requested it. Request the link from where you will open it.

Frequently asked questions

Universal Links or a custom URL scheme?

Universal Links and App Links for anything a person clicks, because they fall back to your website when the app is missing. Custom schemes are useful for app-to-app calls or QR codes that should only work inside the app.

Do I need a new build when I change the paths?

Not for the paths in the AASA file or assetlinks.json, which live on your server. You do need a new build when you add a domain, because the domain is part of the Associated Domains entitlement and the Android manifest.

Why does the link open Safari when I tap it on my own website?

Inside Safari, a tap on a link to the same domain stays in the browser. Test from Notes, Messages or Mail, which is where real users click.

Can Claude Code test deep links on my phone?

It can verify the server side with curl and the check script, and it writes the adb commands for Android. The tap on a real device is your job, and it takes two minutes.

Do deep links help with App Review?

Indirectly. They make magic links, password resets and shared links work inside the app, which keeps the reviewer signed in and in the app instead of stranded in a browser.

Three ways to get your app into the stores

Same result, different amount of work on your side. All three come with the approval guarantee and 24/7 human support.

Do it yourself

$109 per platform, one-time

The WebViewGold license: a finished Xcode or Android Studio project. Paste your URL, set name and icon, switch on features, build and submit. Free updates forever.

See plans on the main page

Cloud Builder

$349 per license, one-time add-on

No Mac, no Xcode, no Android Studio: configure in the browser, we build both apps in the cloud and hand them to App Store Connect and the Play Console.

How the Cloud Builder works Try the free demo

Full Service

$698 per platform $798

Send us your URL and icon. Our team configures, builds and delivers your app within 72 hours, white-label, with source projects. Both platforms for $1,158.

Full Service details Powered by WeSetupYourWebViewApp

Winter Sale prices valid until December 31, 2026.

Ready to ship your app?

App Store & Google Play approval guarantee – or your money back within 14 days

Rather hand it over? Full Service: we configure, build and deliver within 72 hours, from $698 per platform. Questions? Chat with us 24/7.

Refunds are granted under the conditions listed in our FAQ: a non-content rejection by Apple and/or Google, claimed within 14 days after purchase.