Aleksa Insajder — jednostrani brend sajt sa stranom prenosa i panelom
Sportski kreator sa publikom na Instagramu, TikToku i YouTube-u kome je trebala jedna strana koja brend objašnjava do kraja, i još jedna koju sam puni sa telefona. Ispod toga stoji panel na posebnom poddomenu, sopstvena statistika bez kolačića i keš koji se sam sređuje, da niko nikada ne mora da radi tvrdo osvežavanje. Sve u sopstvenom PHP kodu, bez platforme i bez mesečne pretplate.
- Klijent
- Aleksa Insajder (Aleksa Dinić)
- Delatnost
- Sportski sadržaj i video produkcija
- Područje
- Srbija, online
- Brend od
- 4. jul 2021.
- Tip
- Jednostrani brend sajt sa stranom prenosa i panelom
- Tehnologije
- PHP 8.3 · SQLite · Service Worker · nginx
- Sajt
- aleksainsajder.rs
- Status
- Živ sajt, u aktivnom održavanju
U ovom tekstu
- Ko je Aleksa Insajder
- Šta je trebalo rešiti
- Jedna strana i redosled na njoj
- Strana prenosa — šta ona jeste, a šta nije
- Klik-da-pusti: nula zahteva pre klika
- Panel na posebnom poddomenu
- Tri kvara koja su izgledala kao jedan
- Sajt bez CSS-a i keš koji se sam sređuje
- Statistika bez kolačića
- SEO, pravni deo i bezbednost
- Šta klijent na kraju ima
Ko je Aleksa Insajder
Aleksa Insajder je brend Alekse Dinića, sportskog kreatora sadržaja iz Srbije. Video priče iz sveta sporta objavljuje na Instagramu, TikToku i YouTube-u, a oko brenda postoji i Discord zajednica. Sajt nije prodavnica ni katalog usluga — on je mesto na kome brend stoji celovito, sa svojom pričom i načelima, i mesto na koje se sa društvenih mreža šalje publika kada joj treba više od jednog snimka.
Brend postoji od 4. jula 2021 i taj datum stoji ispisan na sajtu, u sekciji o brendu. Rečenica koja ga nosi je „Nisam poseban. Samo ne stajem.", a iznad naslova stoje tri reči: istina, karakter, disciplina. To nije tekst koji je neko dopisao radi popune — to je ono što je Aleksa napisao o sopstvenom radu, i sajt je složen oko toga.
Šta objavljuje, opisano je njegovim rečima: autentične priče iz sveta sporta, dobra dela sportista, vera i karakter, i sadržaj koji treba da pokrene mlade da ne odustanu. Uz to ide obećanje o proverenim informacijama i o kvalitetu ispred kvantiteta. To su njegove tvrdnje o sopstvenom radu i tako se ovde i prenose.
Šta je trebalo rešiti
Zahtev nije bio „napravi vizit-kartu". Bile su četiri tvrde tačke koje moraju da rade zajedno:
- Jedna strana koja se pročita u jednom skrolu — publika dolazi sa telefona, iz linka u opisu profila, i ostaje tačno onoliko koliko joj treba da shvati ko je i šta radi.
- Strana prenosa koju vlasnik sam puni — bez mene, sa telefona, u pauzi, dok meč traje.
- Merenje posete bez trećih lica — vlasnik hoće da zna šta ljudi zaista gledaju, a da za to ne postavlja kolačiće posetiocima.
- Sajt koji preživi lošu vezu — saobraćaj dolazi sa mobilne mreže i stiže u talasu, čim se nešto objavi.
Uz to su išli pravni tekstovi, traka za kolačiće i jedno pravilo koje je odredilo ostatak arhitekture: sve što se objavljuje mora da se menja iz panela, nikada iz koda. Sajt čiji vlasnik mora da zove programera da bi promenio jednu karticu je sajt koji se posle mesec dana više ne menja.
Postojao je i deo koji se ne vidi, a koji je kasnije pojeo najviše vremena: panel mora da radi baš onda kada zatreba, a to je po pravilu subota uveče. Sve što u tom trenutku može tiho da otkaže — sesija, keš, spoljni izvor — otkazaće upravo tada.
Jedna strana i redosled na njoj
Naslovna je jedna strana, ali nije jedan blok teksta. Ide ovim redom: hero sa imenom brenda i rečenicom koja ga nosi, tri kratka obećanja ispod nje (proverene informacije, originalni videi, kvalitetan rad), pa dva dugmeta — Prenosi uživo i Saznaj više.
Zatim Moja priča, gde stoji zašto brend postoji i od kada. Pa Moj pristup, četiri kartice sa načelima: autentičnost, provere informacija, emocija i poruka, doslednost i kvalitet. Pa Moj fokus, spisak tema koje pokriva, sa brojačima koji se odbroje pri dolasku na sekciju. Onda citat Viktora Frankla kao predah, i na kraju kontakt.
Navigacija su sidra ka tim celinama, plus dva linka koja vode van naslovne — na prenose i na Discord. Uz „Prenosi" u navigaciji stoji crvena tačka koja pulsira, ista ona koja se koristi za uživo bedž. To je jedini element na sajtu koji se stalno pomera, i namerno je jedini.
Kontakt je forma sa četiri polja, plus tri kanala i mejl adresa. Uspešno slanje se u statistici broji kao cilj — tako se u panelu vidi ne samo koliko je ljudi bilo na sajtu, nego i koliko ih je napisalo poruku. Traka za kolačiće je zajednička za celu flotu sajtova, ali je ovde usklađena sa brend crvenom, jer je bila jedina stvar na strani van palete.
Strana prenosa — šta ona jeste, a šta nije
Drugi deo sajta je strana Prenosi. Na njoj stoje kartice sa sadržajem koji Aleksa u tom trenutku izdvaja, najviše deset odjednom, u rasporedu koji se sam prilagođava broju kartica: jedna kartica je široka preko cele strane, dve idu u par, četiri u kvadrat, više od toga u tri kolone. Kada nema ničega, stoji prazno stanje sa porukom da se svrati kasnije — a to je, realno, stanje u kome je strana veći deo nedelje.
Ovde je važno šta sajt ne radi, jer je to bila svesna odluka doneta na početku. Sadržaj se ne nalazi na našem serveru. Sajt ugrađuje javno dostupne izvore trećih strana i o tome na samoj strani stoji jasna napomena, zajedno sa tvrdnjom da autorska prava pripadaju vlasnicima sadržaja i sa pozivom da se javi svako ko smatra da je nešto postavljeno neovlašćeno, uz obavezu da se ukloni.
U podacima sajta stoji samo adresa, naziv i vreme dodavanja. Server ne preuzima, ne čuva i ne preemituje ništa. Predlog da se napravi posrednik koji bi sa servera preuzimao i ponovo emitovao sadržaj razmatran je jednom i odbijen — takav server postaje distributer tuđeg materijala, sa svime što uz to ide, i to na mašini na kojoj stoji još nekoliko desetina klijentskih sajtova. Rizik nije bio ni blizu vrednosti funkcije.
Ta odluka ima i tehničku posledicu: pošto server nikada sam ne poziva zalepljenu adresu, ne postoji ni klasa napada u kojoj se preko polja za unos tera server da otvara nešto u sopstvenoj mreži. Tip linka se prepoznaje čitanjem teksta adrese, bez ijednog zahteva.
Klik-da-pusti: nula zahteva pre klika
Prva verzija strane učitavala je ugrađeni sadržaj odmah po otvaranju. Radila je, ali je nosila dva problema koja se vide tek na živom saobraćaju: strana je čekala tuđe skripte da bi se prikazala, a posetilac je dobijao ono što ta strana nosi sa sobom — u dva minuta merenja otvorilo se dvanaest praznih tabova, popundera koje otvara sam izvor.
Zato je uvedeno klik-da-pusti. Do klika u kartici stoji naš crni poster: bedž uživo, naziv i crveno dugme. Provereno merenjem mrežnih zahteva — pre klika ka trećim stranama ne odlazi nijedan zahtev. Tek kada posetilac klikne, učitava se plejer. Prva strana se time otvara brzo i, što je važnije, niko ne dobija tuđe skripte dok ih nije tražio.
Gde izvor to trpi, ugrađeni okvir dobija ograničenja koja gase iskačuće prozore. To se ne može primeniti globalno, jer neki izvori odbijaju da se prikažu u okviru sa ograničenjima, pa postoji spisak domena za koje se ograničenje uključuje. Posle te izmene, dvadeset sekundi na strani nije otvorilo nijedan nov tab.
Naziv stoji preko postera, ispod bedža, i on je na telefonu pravio najviše štete: bio je vezan za fiksnu veličinu slova, pa je dug naziv na uskoj kartici prelazio u tri reda i pokrivao ceo video. Sada se veličina računa iz širine kartice, a ne iz širine ekrana, tekst se seče na dva reda, a dugi nazivi se skraćuju već pri dodavanju. Kartica ima i dugme za ceo ekran, i traku sa rezervnim izvorima kada za isti događaj postoji više linkova.
Panel na posebnom poddomenu
Panel ne stoji na adresi glavnog sajta nego na posebnom poddomenu, sa sopstvenom konfiguracijom servera. Deli isti direktorijum sa sajtom, tako da ono što panel upiše sajt odmah čita, ali se na tom poddomenu izvršava samo jedna skripta — sve ostalo vraća 404. Strana nosi zabranu indeksiranja i zabranu keširanja, jer panel koji se kešira ume da pokaže listu od pre sat vremena i da vlasnika ubedi da mu izmena nije prošla.
Prijava ide preko lozinke koja se ne čuva u čitljivom obliku, svaki upis nosi token koji dokazuje da zahtev dolazi sa panela, a poreklo zahteva se dodatno proverava. Iznad svega toga stoji brojač pokušaja po IP adresi.
Taj brojač je bio i mesto gde je nađena prava rupa. Radio je po obrascu pročitaj — izmeni — upiši, bez zaključavanja. Pet paralelnih pokušaja svi pročitaju nulu pre nego što ijedan upiše svoj trag, pa granica od pet pokušaja u petnaest minuta u praksi nije postojala. Popravljeno je na dva nivoa: brojač sada drži isključivu bravu nad svojim fajlom kroz ceo ciklus, a pokušaj se upisuje pre provere lozinke i briše tek kada prijava uspe. Ispod toga stoji i ograničenje na nivou servera koje broji samo pokušaje prijave, a ne i obično otvaranje panela. Provereno: petnaest paralelnih pokušaja, devet odbijeno na serveru, a od preostalih šest tačno pet upisano kao pogrešna lozinka i jedan kao prekoračen limit.
Uz to je uveden zapis neuspelih prijava sa razlogom — pogrešna lozinka, prekoračen limit, istekla sesija — pa se sledeći put kada stigne poruka „ne mogu da uđem" odgovor traži u njemu, a ne u nagađanju. Rok čuvanja je devedeset dana i to je opisano u politici privatnosti, jer zapis sadrži IP adresu i oznaku pregledača.
Tri kvara koja su izgledala kao jedan
Sredinom avgusta stigla je prijava koja je zvučala kao jedan problem: povremeno se uopšte ne uđe u panel, a na sajtu stoje prenosi od pre nekoliko dana. Bila su tri nezavisna uzroka.
Prvi. Sesije su stajale u zajedničkom sistemskom direktorijumu koji operativni sistem čisti svakih trideset minuta, brišući sve starije od dvadesetak minuta. Aplikacija je verovala da joj sesija traje dva sata — ta postavka nije značila ništa. Posledica: stalna odjava usred posla, a pri sledećoj prijavi poruka o isteklom zahtevu, koja izgleda kao da lozinka ne radi. Sesije su preseljene u sopstveni direktorijum van dosega tog čišćenja, uz uključen sopstveni sakupljač — jer podrazumevana instalacija svoj drži isključenim, računajući da posao radi sistemski zadatak.
Drugi. Otvaranje panela ispali tri paralelna zahteva, a jedan od njih je sinhrono proveravao dostupnost spoljnih izvora. PHP drži isključivu bravu nad fajlom sesije do kraja zahteva, pa kada je izvor bio spor, sva tri zahteva su se poređala iza te brave i panel je izgledao mrtav — da bi se sam popravio kada keš postane topao. Popravka: sesija se zatvara za pisanje čim se utvrdi da je korisnik prijavljen, vremena čekanja su skraćena, a neuspeh izvora se pamti pet minuta.
Treći. Kartica se nikada nije sklanjala sama. Odigran meč je stajao na sajtu dok ga vlasnik ručno ne obriše — to je bukvalno bilo „prenosi od pre nekoliko dana". Prvo je uveden rok, pa je vlasnik izabrao suprotno: bez roka, ali sa jasnom oznakom starosti. U panelu sada piše koliko je vremena prošlo od dodavanja, a posle dvanaest sati oznaka požuti uz napomenu da se proveri da li je još aktuelno.
Uz sve to, keš u pregledaču je čuvao staru listu iako server izričito traži da se ta strana ne kešira — to zaglavlje se u kešu ne poštuje. Strana sada ide isključivo na mrežu.
Sajt bez CSS-a i keš koji se sam sređuje
Odvojena prijava, koja se povremeno ponavljala mesecima: sajt se ponekad učita go, bez stilova. Delovalo je kao kvar servera. Server je bio nevin — u dnevniku hiljadu i dvesta uspešnih odgovora nad stilovima i nijedna greška.
Koren je bio u pomoćnom radniku u pregledaču. On je čuvao kopiju stila pod adresom /css/style.css, a strana je tražila /css/style.css?v= sa brojem verzije. Poređenje adresa je podrazumevano potpuno, pa poklapanja nikada nije bilo — što je značilo da je stil zavisio isključivo od mreže. Jedan kiks mobilne veze i strana ostane bez stilova do sledećeg osvežavanja. Najčešće se javljalo odmah posle izmena, jer se tada promeni broj verzije pa ni pregledač nema kopiju.
Popravka ide u tri koraka: promašaj u kešu se prvo ponovi jednim novim pokušajem posle pola sekunde; ako i to padne, uzima se prethodna verzija istog fajla iz keša umesto greške; tek onda se odustaje. Stare verzije se čiste same, ali se kopija bez broja verzije namerno čuva kao poslednja rezerva za prvi ulaz bez mreže. Provereno sa isključenom mrežom: strana i dalje ima pun stil i svoj font.
Uz to je sređeno i keširanje na serveru. Strane se u pregledaču više ne drže po sat vremena nego se uvek proveravaju, dok ispod njih i dalje radi serverski keš gotovih strana. Statika se drži trideset dana kao nepromenljiva, jer njene adrese nose broj verzije — i sada šalje jedno zaglavlje o keširanju umesto dva koja su se preklapala. Cilj je bio jednostavan: da nijedan posetilac nikada ne dobije uputstvo da uradi tvrdo osvežavanje.
Statistika bez kolačića
Vlasnik je hteo da vidi šta ljudi zaista gledaju, ali bez postavljanja kolačića posetiocima. Zato sajt ima sopstvenu, anonimnu statistiku, ugrađenu u isti panel kao i prenosi.
Podaci stoje u SQLite bazi na serveru. Posetilac se prepoznaje kao skraćeni otisak koji se računa iz mesečne soli, IP adrese i oznake pregledača — bez kolačića, a so se rotira mesečno, tako da se trag ne može pratiti kroz vreme. Prijemnik prima isključivo POST, uvek odgovara istim praznim odgovorom, ograničen je po veličini i po broju zahteva, i prihvata samo unapred poznate putanje. Oznaka prenosa se broji jedino ako taj prenos zaista postoji u podacima sajta, pa se iz pregledača ne mogu ubaciti izmišljeni nazivi.
U panelu se vidi ko je online u ovom trenutku i na kojoj je strani, pa šest osnovnih brojeva — pregledi, posetioci, posete, vreme gledanja, najviše gledalaca u isto vreme i broj poruka sa forme. Ispod toga idu grafikon po satu ili po danu i tabele: strane, izvori dolaska, države, uređaji, pregledači. Posebna tabela meri gledanost po prenosu.
Detalji koji taj deo drže na nogama: država se čita iz lokalne baze na serveru, bez ijednog spoljnog servisa; vreme gledanja se upisuje uslovno, tako da dva otvorena taba ne broje isto vreme dvaput; a snimak trenutnog vrhunca se pravi najviše na deset sekundi, jer bi pri velikom meču upis na svaki otkucaj postao usko grlo.
Pored toga na sajtu radi i Google Analytics, ali sa pristankom po standardu Consent Mode v2 i podrazumevanim odbijanjem — do pristanka bez kolačića. Politika privatnosti je usput ispravljena, jer je jedno vreme tvrdila da se analitika trećih strana ne koristi, dok je ona već bila na sajtu. Tekst koji se ne slaže sa onim što kod radi je gori od nepostojećeg teksta.
SEO, pravni deo i bezbednost
Naslov naslovne strane sveden je na samo ime brenda, jer je pretraga po imenu i jedini put kojim ljudi ovde dolaze — dodatak od pet reči je samo trošio prostor u rezultatu. Sajt nosi strukturirane podatke tipa Person, Organization i WebSite, sa datumom osnivanja brenda i sa vezama ka svim njegovim kanalima, tako da pretraživači sajt i profile vide kao isti entitet, a ne kao četiri nepovezane stvari.
U robots.txt su upisana i pravila za robote jezičkih modela, a sajt ima i security.txt sa adresom za prijavu bezbednosnih nalaza. Za sertifikat su postavljeni CAA zapisi, sajt je na spisku za prinudni HTTPS na nivou pregledača, a u proveri iz maja 2026. dobio je najvišu ocenu za podešavanje veze.
Iz istog prolaza je i nalaz koji se ne vidi u kodu: domen je imao IPv6 adresu, ali je server slušao samo na IPv4. Posetioci koji dolaze preko IPv6 dobijali su tuđi podrazumevani sertifikat i upozorenje da veza nije bezbedna — za njih je sajt izgledao kao da je provaljen. Popravljeno je dodavanjem IPv6 slušanja, pa obe adrese sada odgovaraju istim sertifikatom.
Osetljivi delovi su zatvoreni na nivou servera i provereni zahtevom, ne pretpostavkom: direktorijum sa podacima, datoteka sa pristupnim podacima, unutrašnji kod i rezervne kopije fajlova — sve vraća odbijanje.
Pravni deo su dve strane pisane za ovaj sajt, ne prekopirane: politika privatnosti, koja opisuje i internu statistiku i bezbednosni zapis, i Uslovi korišćenja, gde stoji šta sajt jeste, šta se sme, i ograničenje odgovornosti za sadržaj sa spoljnih izvora.
Šta klijent na kraju ima
Sajt koji je njegov. Kod i podaci stoje na serveru, mogu se prekopirati i preseliti; nema mesečne pretplate platformi, nema dodataka koji se raspadnu pri sledećem ažuriranju, nema tuđeg servisa kome se plaća da bi se videla poseta.
Praktično, dan izgleda ovako. Kada hoće da izdvoji nešto što se te večeri igra, Aleksa otvori panel sa telefona — instaliran je kao aplikacija na početnom ekranu — zalepi link ili ga izabere iz liste, i kartica je na sajtu. Kada meč prođe, obriše je, ili je ostavi dok mu panel ne požuti uz podsetnik da proveri da li je još aktuelno. Kada hoće da vidi kako je prošlo, otvara isti panel, tab dalje.
Sajt je i dalje u aktivnom održavanju. Kroz njega je prošlo nekoliko prolaza koji se u tekstu vide kao popravljeni kvarovi: sesije, keš, prijava, brzina, ograničenja izvora. Adrese spoljnih izvora namerno stoje u podešavanjima, a ne u kodu, jer se takve stvari gase i menjaju bez najave — kada se to desi, menja se jedan red, ne pravi novi sajt.
Sve izmene idu direktno na živi sajt, sa rezervnom kopijom pre svake, i sa čišćenjem keša i osvežavanjem PHP procesa odmah posle, jer se u suprotnom vlasniku po sat vremena servira verzija koju je upravo zamenio. To je nauk sa ovog projekta koji se sada primenjuje na svim sajtovima na tom serveru.
Sajt u slikama
Aleksa Insajder
Priča o brendu, načela iza sadržaja i strana sa aktuelnim prenosima koje Aleksa izdvaja.
aleksainsajder.rsČesto postavljana pitanja
Da li se prenosi čuvaju na vašem serveru?
Zašto server ne preuzima sadržaj umesto posetioca?
Može li vlasnik sam da dodaje i briše kartice?
Zašto sopstvena statistika, a ne samo gotov alat?
Zašto jedna strana, a ne sajt sa deset podstrana?
Šta se dešava kada spoljni izvor prestane da radi?
Treba vam ovakav sajt?
Recite mi čime se bavite i šta sajt treba da uradi za vas — dobijate fiksnu ponudu i rok, u pisanoj formi.