Find friends who already use the app
Compare normalized phone numbers with accounts in your backend and show "3 of your contacts are here" instead of an empty friends list.
Cursor + contacts
Find-your-friends screens, group invites and split-the-bill apps often want the address book. In a WebViewGold app, your Cursor app asks for permission with requestcontactpermission:// and receives names and phone numbers as JSON in the contacts variable after readcontacts://. The code takes minutes; how you use the data decides whether the app passes review.
From $109 one-time per platform, or let our team do it all from $698.
Compare normalized phone numbers with accounts in your backend and show "3 of your contacts are here" instead of an empty friends list.
The user picks a contact, the app prepares a personal invite and opens the share sheet. No bulk invites, no surprises for the recipient.
CRM, booking and team apps can prefill a new record from a picked contact instead of making users retype names and numbers.
A plain invite link through the native share sheet (shareapp://) needs no permission at all and is the easier path through review. Ask for contacts only when matching or picking adds real value.
Paste this into Cursor to implement the web-app side. Review the result, publish, then test inside the WebViewGold app.
Prompt for the Cursor agent: Implement contacts access for the WebViewGold app wrapper. 1) Create lib/webviewgold/contacts.ts with isWebViewGold() (navigator.userAgent includes my custom WebViewGold token), requestPermission() which navigates to requestcontactpermission://, and readContacts(timeoutMs = 5000) which sets window.contacts = undefined, navigates to readcontacts:// and resolves with the name-to-phone-numbers object or null. 2) Add normalizeNumber() with libphonenumber-js using the user's country. 3) Build a ContactsPicker component: explainer, Continue (permission), Load contacts (read), search, no preselection, no Select all. 4) Add a server endpoint that matches up to 2000 normalized numbers against users, returns only matches, stores and logs nothing, and is rate-limited. 5) Send invites through shareapp://message?=TEXT&url=INVITE_URL. 6) Add tests and document the privacy rules in .cursor/rules.

Great work! Never coded anything but managed to work with this. Easy and fast! Also with great help from the creators!
An hour for the code, a little longer for the privacy texts.
Android: add android.permission.READ_CONTACTS to AndroidManifest.xml, as the WebViewGold docs require. iOS: the contacts usage description in Info.plist must say why, for example "to show which of your contacts already use the app".
Show your own screen that explains the benefit with a Continue button, then navigate to requestcontactpermission://. Never ask on first launch or before the user reaches the feature.
After permission, navigate to readcontacts://. WebViewGold fills the global contacts variable with an object of names and phone-number arrays; without permission it is null.
Show a searchable list with nothing preselected and no Select all button, and show the exact invite text before anything is sent.
For friend matching, normalize the numbers and send them to your backend for a one-time comparison; do not keep unmatched numbers. For invites, send nothing at all: open the share sheet.
Two separate taps: one for the permission, one to load the list. The contacts variable arrives asynchronously. Friend matching, if you need it, runs server side for signed-in users only; in your Cursor project that means: Your own API routes or services.
var IN_APP = navigator.userAgent.indexOf("WebViewGold") !== -1; // your custom user agent token
function waitFor(name, timeoutMs, done) {
var start = Date.now();
(function check() {
if (typeof window[name] !== "undefined") { done(window[name]); }
else if (Date.now() - start < timeoutMs) { setTimeout(check, 100); }
else { done(undefined); }
})();
}
// Tap 1: after your own explainer screen
function askForContacts() {
if (!IN_APP) { showInviteLink(); return; }
window.location.href = "requestcontactpermission://";
}
// Tap 2: "Show my contacts"
function loadContacts() {
window.contacts = undefined;
window.location.href = "readcontacts://";
waitFor("contacts", 5000, function (list) {
if (!list) { showPermissionHint(); return; } // null = no permission
// shape: { "John Appleseed": ["888-555-5512", "888-555-1212"], ... }
var people = Object.keys(list).map(function (n) { return { name: n, phones: list[n] }; });
renderPicker(people); // nothing preselected, no "Select all"
});
}
// Denied earlier? Let the user change it in Settings
function openAppSettings() { window.location.href = "settingsapp://"; }A JSON object keyed by contact name, each with an array of phone numbers, stored in the global contacts variable. Without permission the variable is null. Email addresses, postal addresses and photos are not part of the documented format.
Not for reading them, but often for how. Ask in context with a clear purpose string, let users pick individual people, never invite everyone at once, and do not keep the address book on your server unless the feature needs it and your privacy policy says so.
Often not. A share sheet with a personal invite link reaches WhatsApp, Messages and email without any permission and is far easier to explain in review. Use contacts access when you match friends or build groups from existing contacts.
readcontacts:// then leaves the contacts variable as null. Offer the invite link instead, and if the user changes their mind later, open the app settings with settingsapp:// so they can grant access.
Same result, different amount of work on your side. All three come with the approval guarantee and 24/7 human support.
$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$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$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 byWinter Sale prices valid until December 31, 2026.
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.