La conținut
Type — API pentru site
Secțiuni

Adresele paginilor și redirecționări

Adresa obiectului: slug și slugs

Fiecare obiect are un slug (adresă lizibilă) în fiecare limbă. Îl păstrează CRM-ul:

CâmpCe înseamnă
slugslug-ul în limba răspunsului (lang); dacă pentru limbă nu există slug — cel românesc
slugsslug-urile în toate limbile: { ro, ru, en } — pentru linkurile spre alte limbi și hreflang
  • Slug-ul se stabilește o dată și nu se schimbă la redenumirea obiectului, așa că linkurile și rezultatele căutării nu se strică.
  • Slug-ul este unic printre obiectele companiei în fiecare limbă. Dacă denumirea coincide cu una existentă, CRM-ul adaugă un sufix (-2).
  • Dacă managerul totuși schimbă slug-ul manual, adresa anterioară intră în tabelul de redirecționări (mai jos) — linkul vechi nu va da 404.

Exemplu de rută pe site: /{lang}/apartament/{slug}. Schema adreselor o alegeți dvs.; CRM-ul oferă doar slug-ul.

tsx
// linkuri spre alte limbi
<link rel="alternate" hrefLang="ro" href={`https://site.example.com/ro/apartament/${u.slugs.ro}`} />
<link rel="alternate" hrefLang="ru" href={`https://site.example.com/ru/apartament/${u.slugs.ru}`} />

Tabelul de redirecționări: legacyUrls()

GET /legacy-urls întoarce lista adreselor vechi. Fiecare element este un SiteLegacyUrl:

CâmpCe înseamnă
urladresa veche: pagina produsului WooCommerce sau slug-ul anterior al obiectului
pathcalea adresei vechi (/ro/product/<slug>/) — cheia pentru comparația cu cererea
langlimba adresei vechi
unit_idobiectul
slugslug-ul curent al obiectului în limba lang; null — obiectul a fost șters
gonetrue — obiectul a fost șters

Ce să răspundeți la cererea unei adrese vechi:

CazRăspuns
obiectul există în units()301 spre /{lang}/apartament/{slug}
obiectul e arhivat (lipsește din units(), dar gone: false)301 spre catalog
gone: true410 Gone — pagina nu mai există, motoarele de căutare o vor scoate din rezultate

Comparați calea fără / final și fără a ține cont de majuscule; caracterele chirilice din linkurile vechi pot veni atât codificate procentual, cât și decodificate.

Next.js: redirects() la build

Potrivit dacă adresele vechi nu se mai schimbă.

ts
// next.config.ts
import { createSiteClient } from '@type/site-client';

export default {
  async redirects() {
    const crm = createSiteClient({ baseUrl: process.env.TYPE_API_URL!, apiKey: process.env.TYPE_API_KEY! });
    const { units } = await crm.units({ lang: 'ro' });
    const live = new Set(units.map((u) => u.id));
    return (await crm.legacyUrls())
      .filter((l) => !l.gone)
      .map((l) => ({
        source: l.path,
        destination: live.has(l.unit_id) && l.slug ? `/${l.lang}/apartament/${l.slug}` : `/${l.lang}/apartamente`,
        permanent: true,
      }));
  },
};

Adresele cu gone: true răspundeți-le cu 410 din middleware sau dintr-o rută catch-all: redirects() știe doar să redirecționeze.

Next.js: fără rebuild

Țineți tabelul în middleware.ts sau într-o rută catch-all (app/product/[...slug]/page.tsx cu permanentRedirect()): puneți legacyUrls() în cache prin unstable_cache cu eticheta rental:units și goliți-o prin webhook — redirecționările noi apar fără rebuild-ul site-ului.

Fotografii

photos[].url este un link permanent de forma /api/modules/rental/site/photos/…. Nu are nevoie de cheie, poate fi pus direct în <img> (prin crm.photoUrl(url) — adresa absolută). Linkul răspunde cu 302 spre o previzualizare WebP cu lățimea de până la 1920 px fără EXIF, Cache-Control: public, max-age=3000. Dacă fotografia a fost ștearsă sau obiectul e arhivat — 404; dacă previzualizarea încă se construiește — 503 cu Retry-After.