Sisu juurde
cutty.dev
All posts

Auto-prefix URL — pis detail, mis säästab minute

cutty.dev tuvastab, kui kleepid aadressi ilma https:// ja lisab selle ise. See kõlab trivialsena. Tegelikkuses on see erinevus kahe sekundi ja nupule 'proovi uuesti' vajutamise vahel.

Linkide lühendamise vormis sisestate allegro.pl. Enamik lühendajaid ütleb teile, et see ei ole korrektne URL, ja palub sisestada uuesti koos eesosa https:// ile. cutty.dev lisab lihtsalt ise https:// ja jätkab.

See kõlab nagu funktsioon, mis ei vääri peaaegu mainimist. Praktikas on see erinevus:

  • "kleepisin sisse, mul on lühike link, sulan akna" (2 sekundit)
  • "kleepisin sisse, viga, loen teadet, lisan https, uuesti, sain lingi" (15-20 sekundit)

Kordalda kordota selle arv, kui palju korda kuus URL-i kleepid, lisades ette frustratsiooni vead lugemisel ja hetke "ah joo, protseduur". Väike asi, mida mõõdetakse minutites inimese kohta kuus.

Mis täpset teeb cutty.dev

Lippasid teksti vormi. Enne serverile saatmist kontrollib JavaScript, kas see algab mõne protsolliga (http://, https://, ftp://, mailto: jne). Kui see ei ala**<0xC2><0xA0>**<0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2><0xA0><0xC2>

Tähendab:

  • allegro.plhttps://allegro.pl
  • github.com/twoj-profil/projekthttps://github.com/twoj-profil/projekt
  • www.gazeta.plhttps://www.gazeta.pl

A kui sesuatu juba on protokoll (isegi kui see on vale), siis süsteem jätab selle muutmata ja kontrollib edasi:

  • http://example.com → jääb http://example.com (lubatud)
  • ftp://example.com → keelatud (ainult http/https)
  • javascript:alert(1) → keelatud (XSS kaitse)

Miks mul on see ja teistel mitte

Enamik lühendajaid kasutavad standardset URL-i kontrolli läbi new URL(string). Konstruktor URL brauseri/JavaScriptis on strict — kui protokoll puudub, visatakse viga. Vaikimisi väljund new URL("allegro.pl") jaoks on TypeError.

See on enamik rakenduste puhul korrektne käitumine. Kuid linki lühendamise vormi puhul, kus kasutaja kleepib aadressiribalt või muust rakendusest kopeeritud URL-i, on see rangus takistus rather kui abi.

Lahendus võtab viis JavaScripti rida:

function sanitizeUrl(input) {
  const trimmed = input.trim();
  const hasProtocol = /^[a-z][a-z0-9+.-]*:/i.test(trimmed);
  const normalized = hasProtocol ? trimmed : "https://" + trimmed;
  // dalsza walidacja przez new URL(normalized)
}

Viis koodirida, kümne sekundi vähem frustratsiooni iga kasutaja kohta päevas. Ei tea, miks enamik turust seda ei tee. Võib-olla sest "standardselt" tähendab "nii toimib URL-i konstruktor".

UX-i pisidetailid on ebaproportsionaalselt olulised

cutty.dev-il on kümnemakümmend sarnast asja, mis ei ole ükski funktsioonide loettus, sest igaüks eraldi kõlab triviaalne:

  • Trim whitespace enne valideerimist — lõuna tühikuga kleepitud URL ei põhjusta vigu
  • Hash zachowanyhttps://example.com/page#section säilitab lühendamise pärast #section
  • Query strings zachowane?utm_source=test läbib ilma katkestamata
  • Automatic protocol upgradehttp:// muutub https://, kui algne URL toetab TLS-i (planeeritud, veel mitte LIVE)
  • IDN domainsźdźbło.pl konverteeritakse automaatselt punycode'iks
  • Polskie znaki w slug — asendatakse automaatselt ASCII-ga lõpu loomisel (różowy-linkrozowy-link)
  • Detect dangerous protocolsjavascript:, data:, file:, mailto: tõndetakse kindla teatega

Iga detail säästab kedagi 5–30 sekund ja hetke ärritust. Koos on see erinevus tussen "armastan seda rakendust" ja "töötab OK".

Mis edasi detailide UX-iga

Asjad, mida tahan tulevikus teha nimekiri:

  • Smart paste — tuvasta, kui kasutaja kleepib teksti, mis sisaldab URL-i koos teiste sõnadega, ja eralda ainult URL
  • Bulk paste — kleepitud URL-ide loetelu (üks rida kohta) loob korraga mitu lühikest linki
  • Suggested slugs — sihtlehe pealkirja põhjal paku valimiseks 3 brändikatendust
  • Auto-OG preview — näita Open Graph kaardi eelvaadet kohe pärast URL-i kleepmist, enne lühendamise klikkimist

Iga üks neist on samuti "viililine funktsioon, mis ei näata midagi". Kõik koos erinevad tööriha, mis on OK, ja tööriha, mida tahad igapäevaselt kasutada.

Proovi ise

Kleeli midagiallegro.pl või github.com või news.ycombinator.com. Süsteem lisab ise protokolli ja jätkab edasi. Ilma ootamata, ilma veaga, ilma "proovi uuesti".

Kui teid huvitab selline UX-detail — andke teada, millisel suunas edasi liikuda. hello@cutty.dev.