eduardweb.
Navigație & StateAvansat#react-native#android#ios#deep-linking#expo-router

Deep linking universal cu Expo Router: De la Custom Schemes la Universal Links

De Ștefan Iliescu, 3 aug. 2026 · 10 vizualizări · 2 like-uri

Postat 3 aug. 2026
json
{
  "expo": {
    "name": "MyApp",
    "scheme": "myapp",
    "ios": {
      "bundleIdentifier": "com.company.myapp",
      "associatedDomains": [
        "applinks:myapp.ro"
      ]
    },
    "android": {
      "package": "com.company.myapp",
      "intentFilters": [
        {
          "action": "VIEW",
          "autoVerify": true,
          "data": [
            {
              "scheme": "https",
              "host": "myapp.ro",
              "pathPrefix": "/product"
            }
          ],
          "category": [
            "BROWSABLE",
            "DEFAULT"
          ]
        }
      ]
    }
  }
}

Am mutat recent un proiect cu peste 20k utilizatori activi pe Expo Router v3 și am avut de configurat deep linking universal. În postarea asta vă arăt exact unde ne-am blocat, cum am configurat app.json și ce trucuri am folosit ca să facem iOS și Android să deschidă aplicația instant din WhatsApp sau Mail.

Dacă ai lucrat vreodată cu React Navigation clasic, știi ce coșmar era să scrii manual linking config, cu prefixes și getStateFromPath pentru 30 de rute imbricate. Cu Expo Router, fișierele tale din folderul app/ devin automat rute de deep link. Dar provocarea reală nu e în React Native, ci în sistemul de operare și validarea domeniilor.

Custom Schemes vs. Universal Links

Să le separăm clar din start:

  1. Custom Scheme (myapp://product/42): Se configurează în 2 minute. E excelent pentru mediul de dezvoltare sau integrări locale de OAuth. În producție e riscant — dacă altă aplicație instalată pe telefon își declară același scheme, sistemul o să întrebe userul ce aplicație vrea să deschidă sau, mai rău, o deschide pe cea greșită.
  2. Universal Links (iOS) / App Links (Android) (https://myapp.ro/product/42): Folosesc domenii reale pe HTTPS. Dacă userul are app-ul instalat, se deschide app-ul. Dacă nu, se deschide site-ul tău în browser. Zero popups hidoase pe iOS.

Unde pică 80% din developeri: fișierele din .well-known

Am pierdut vreo 2 zile întregi pe un proiect încercând să ne dăm seama de ce iOS refuza să deschidă link-urile de stocare, deși totul părea corect. Capcanele clasice sunt întotdeauna pe server:

  • Apple Site Association (apple-app-site-association): Serverul tău TREBUIE să livreze fișierul din https://domeniu.ro/.well-known/apple-app-site-association cu header-ul Content-Type: application/json. Nu redirecționa HTTP către HTTPS (iOS CDN refuză să urmărească 301/302). Vezi că Apple își face cache la fișierul ăsta pe serverele lor CDN. Dacă ai greșit un appID (TeamID.BundleID), poate dura și 24h până când iOS încearcă să-l descarce din nou pe dispozitivul de test.
  • Android Asset Links (assetlinks.json): Aici capcana e amprenta SHA256. Dacă folosești Google Play App Signing, amprenta generată de keystore-ul tău local de release NU e aceeași cu cea pe care o folosește Google după ce procesează AAB-ul. Trebuie să copiezi SHA256-ul direct din consola Google Play (secțiunea App Signing).

Routing-ul automat în Expo Router

Aici vine partea mișto. Dacă ai o structură de fișiere de tipul app/product/[id].tsx, când un utilizator dă click pe https://myapp.ro/product/99, Expo Router știe direct să monteze ecranul respectiv și să-ți ofere id: "99" în hook-ul useLocalSearchParams(). Nu mai e nevoie de cod de legătură scris de mână.

Trade-off-uri și realitatea din producție

Configurarea Universal Links e un pain masiv la debugging, dar experiența utilizatorului este de 10 ori mai bună decât la custom schemes. Pe de altă parte, dacă nu ai un site web oglindă pe același domeniu, un utilizator fără aplicație instalată va vedea o eroare 404 în browser când dă click pe link. Soluția noastră a fost să punem un script simplu pe web care redirecționează automat către App Store sau Google Play în funcție de User-Agent.

Voi cum gestionați hosting-ul pentru AASA și AssetLinks? Folosiți servicii terțe gen Branch/AppsFlyer sau preferați să aveți control total prin Cloudflare / Vercel?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.