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

Deep linking universal în Expo Router: Cum setezi Universal Links fără bătăi de cap

De Alexandru Matei, 28 iul. 2026 · 11 vizualizări · 2 like-uri

Postat 28 iul. 2026
javascript
// app.config.js - Configurare Universal Links & Schemes în Expo
module.exports = {
  expo: {
    name: "My App",
    slug: "my-app",
    scheme: "myapp",
    ios: {
      supportsTablet: true,
      bundleIdentifier: "ro.myecommerce.app",
      associatedDomains: ["applinks:myecommerce.ro"]
    },
    android: {
      package: "ro.myecommerce.app",
      intentFilters: [
        {
          action: "VIEW",
          autoVerify: true,
          data: [
            {
              scheme: "https",
              host: "myecommerce.ro",
              pathPrefix: "/produs"
            }
          ],
          category: ["BROWSABLE", "DEFAULT"]
        }
      ]
    }
  }
};

Am integrat recent deep linking universal într-o aplicație de e-commerce cu peste 50k utilizatori activi lunari. Dacă folosești Expo Router, reclama spune că „totul merge de la sine” datorită structurii de fișiere din folderul app, dar în producție dai repede de capcane. În postarea asta îți arăt cum configurezi scheme-urile custom și Universal Links (iOS) / App Links (Android) fără să-ți prinzi urechile în cache-ul Apple sau în stările de autentificare.

Custom Scheme vs. Universal Links: Trade-off-ul real

Multe echipe încep cu un Custom Scheme gen myapp://produs/123. E simplu de setat în app.json, testezi în 5 minute pe simulator și ești bucuros. Dar problema apare în lumea reală: dacă userul dă click pe un astfel de link dintr-un email sau WhatsApp și NU are aplicația instalată, browserul afișează o eroare urâtă de tipul "Safari cannot open the page". Experiență mizerabilă pentru utilizator.

Aici intervin Universal Links (iOS) și App Links (Android). Ele folosesc domenii HTTPS standard (https://myecommerce.ro/produs/123). Dacă aplicația e pe telefon, sistemul de operare o deschide direct, ocolind browserul. Dacă nu e instalată, utilizatorul aterizează pe site-ul tău sau e trimis elegant în Store. Trade-off-ul? Treci printr-un proces chinuitor de configurare pe server (fișierele apple-app-site-association și assetlinks.json), iar debug-ul e frustrant din cauza cache-ului agresiv pe iOS.

Configurarea corectă în Expo Config

În Expo Router, sistemul file-based mapază automat rutele. Dacă ai fișierul app/produs/[id].tsx, rutei îi corespunde URL-ul /produs/123. Totuși, trebuie să specifici în app.config.js domeniile asociate și filtrarea de intenții pentru Android.

Pe iOS, fișierul apple-app-site-association (AASA) trebuie servit neapărat cu Content-Type: application/json la adresa https://domeniul-tau.ro/.well-known/apple-app-site-association. Atenție: NU pune extensia .json în URL-ul de iOS! Am pierdut aproape două ore la un proiect vechi din cauza acestei mici diferențe.

Pe Android, pui assetlinks.json la https://domeniul-tau.ro/.well-known/assetlinks.json. Aici ai nevoie de amprenta SHA256 din keystore-ul de producție (sau din Google Play Console, dacă folosești App Signing).

Nightmare-ul cu AASA Caching și Auth Guard

Apple folosește un CDN propriu pentru a verifica fișierele AASA. Asta înseamnă că atunci când schimbi ceva pe server, Apple poate dura până la 24 de ore să preia noul fișier pe dispozitivele utilizatorilor. Sfatul meu: testează pe staging folosind domenii separate și activează flag-ul de developer pe iOS pentru a forța re-descărcarea AASA în modul de dezvoltare.

A doua mare problemă pe care am întâlnit-o este Auth Guard-ul. Ce faci când un user dă click pe https://myecommerce.ro/comanda/999, dar token-ul lui de logare a expirat?

Expo Router procesează deep link-ul înainte ca starea ta de Auth (ex. Zustand sau React Query) să fie complet hidratată din AsyncStorage sau SecureStore. În proiectul nostru, făceam un redirect orbește către /login, iar parcursul inițial al userului se pierdea. Am rezolvat prin interceptarea URL-ului de intrare și salvarea rutei ca parametru redirectTo pe ecranul de Login. Am scăzut drop-off-ul cu 18% pe fluxul de invitații din campaniile de email doar optimizând retenția acestui URL inițial.

Concluzie

Expo Router ușurează mult lucrurile pe partea de JS/TS, dar greul rămâne la validarea domeniilor pe sistemele de operare. Dacă îți configurezi AASA și AssetLinks corect din primul minut, ai scăpat de 80% din probleme.

Voi cum gestionați invalidarea de cache AASA pe iOS în pipeline-ul de CI/CD când adăugați subdomenii noi?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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