Website2026-08-21
Aleksa Insajder — a creator website with broadcast tools and a content panel
A sports creator with an audience on Instagram, TikTok and YouTube who needed a page that explained the brand to the end, and another that he loaded from his phone. Underneath that is a panel on a separate subdomain, its own cookie-free stats, and a self-managing cache, so no one ever has to do a hard refresh. All in own PHP code, no platform and no monthly subscription.
- Client
- Aleksa Insajder (Aleksa Dinić)
- Business
- Sports content and video production
- Area
- Serbia, online
- Brand of
- 4. July 2021
- Type
- One-page brand site with transfer page and panel
- Technologies
- PHP 8.3 · SQLite · Service Worker · nginx
- Status
- Live site, under active maintenance
- Technology
- PHP 8.3 · SQLite · Service Worker / PWA · nginx
Problem and context
Who is Aleksa Insajder
Aleksa Insajder is the brand of Aleksa Dinić, a sports content creator from Serbia. He publishes video stories from the world of sports on Instagram, TikTok and YouTube, and there is also a Discord community around the brand. The site is not a store or a catalog of services — it is the place where the brand stands whole, with its story and principles, and the place to which the audience is sent from social media when they need more than one shot.
The brand has existed since 4. July 2021and that date is written on the website, in the section about the brand. The sentence that carries it is "I'm not special. I just don't stop," and above the title are three words: truth, character, discipline. It's not a text that someone typed in to fill in — it's what Alexa wrote about her own work, and the site is built around that.
What he publishes is described in his words: authentic stories from the world of sports, good deeds of athletes, faith and character, and content that should motivate young people not to give up. Along with that comes the promise of verified information and quality over quantity. These are his claims about his own work and that is how they are conveyed here.
What needed to be solved
The request was not "make a business card". There were four hard points that had to work together:
- One page read in one scroll — the audience comes on a phone, from the link in the profile description, and stays exactly as long as they need to understand who he is and what he does.
- The transmission page that the owner fills — without me, on a phone, during the break, while the match is going on.
- Visit measurement without third parties — the owner wants to know what people are really looking at, without setting cookies for visitors.
- A site that survives a bad connection — traffic comes from the mobile network and arrives in waves as soon as something is published.
Along with that came legal texts, a cookie bar, and one rule that determined the rest of the architecture: everything published must be changed from the panel, never from the code. A site whose owner has to call a developer to change one tab is a site that doesn't change after a month.
There was also an invisible part, which later consumed the most time: the panel must work exactly when it is needed, which is usually Saturday evening. Anything that can fail silently at that moment — session, cache, external source — will fail right then.
One page and the order on it
The title is one page, but not one block of text. It goes in this order: a hero with a brand name and a sentence that carries it, three short promises below it (verified information, original videos, quality work), then two buttons — Live and Learn more.
Then My story, where it says why the brand exists and since when. So My approach, four cards with principles: authenticity, information checks, emotions and messages, consistency and quality. So My focus, a list of topics it covers, with counters that count down when you arrive at a section. Then a quote from Viktor Frankl as a break, and finally contact.
Navigation are anchors to those units, plus two links that lead outside the homepage — to broadcasts and to Discord. Next to "Transmissions" in the navigation is a pulsating red dot, the same one used for the live badge. It's the only element on the site that keeps moving, and it's the only one on purpose.
Contact is a form with four fields, plus three channels and an email address. Successful sending is counted as a goal in the statistics — so the panel shows not only how many people were on the site, but also how many wrote a message. The cookie bar is common to the whole fleet of sites, but here it is coordinated with the brand red, since it was the only thing on the page outside the palette.
Transmission page - what it is and what it is not
The second part of the site is Transmission page. There are cards on it with content that makes Alexa stand out at that moment, no more than ten at a time, in an arrangement that adjusts itself to the number of cards: one card is wide across the entire page, two go in a pair, four in a square, more than that in three columns. When there is nothing, there is an empty state with a message to come back later — which is, realistically, the state the page is in for most of the week.
What the site doesn't do is important here, because it was a conscious decision made at the beginning. The content is not on our server. The site embeds publicly available sources of third parties and there is a clear notice about this on the page itself, together with the assertion that the copyright belongs to the content owners and with an invitation to contact anyone who believes that something has been posted without authorization, with the obligation to remove it.
In the data of the site, only the source URL, title and time added are stated. The server does not download, store or transmit anything. The proposal to create an intermediary that would download and rebroadcast content from the server was considered once and rejected — such a server becomes a distributor of other people's material, with everything that goes with it, and that on a machine that has several dozen client sites. The risk was nowhere near the value of the function.
That decision also has a technical consequence: since the server never calls the pasted address itself, there is no class of attack in which the input field forces the server to open something in its own network. The link type is recognized by reading the text of the address, without any request.
Click-to-play: zero request before click
The first version of the page loaded embedded content immediately upon opening. It worked, but it had two problems that can only be seen in live traffic: the page was waiting for other people's scripts to be displayed, and the visitor got what the page brought with it — in two minutes of measurement, twelve empty tabs were opened, popunders opened by the source itself.
That's why click-to-play was introduced. Next to the click in the card is our black poster: badge live, name and red button. Verified by measuring network requests — no request goes to a third party before a click. Only when the visitor clicks does the player load. This opens the homepage quickly and, more importantly, no one gets someone else's scripts until they ask for them.
Where the source tolerates it, the built-in framework gets restrictions that turn off popups. It cannot be applied globally, as some sources refuse to show up in the restricted box, so there is a list of domains for which the restriction is enabled. After that change, twenty seconds on the page did not open any new tabs.
The name is above the poster, below the badge, and it did the most damage on the phone: it was tied to a fixed font size, so the long name on a narrow card ran into three lines and covered the entire video. Now the size is calculated from the tab width, not from the screen width, text is cut to two lines, and long names are shortened already when adding. The card has a button for full screen, and a bar with backup sources when there are several links for the same event.
Panel on a separate subdomain
The panel is not on the address of the main site but on a separate subdomain, with its own server configuration. It shares the same directory with the site, so what the panel writes is immediately read by the site, but only one script is executed on that subdomain — everything else returns a 404. The page is indexed and cached, because the cached panel can show a list from an hour ago and convince the owner that the change didn't go through.
Login goes through a password that is not stored in a readable form, each entry carries a token that proves that the request comes from the panel, and the origin of the request is additionally checked. Above all that is a counter of attempts per IP address.
That counter was also the place where the real hole was found. It worked in a read-modify-write pattern, without locking. Five parallel attempts all read zero before any of them wrote their track, so the limit of five attempts in fifteen minutes did not exist in practice. It's fixed on two levels: the counter now holds an exclusive lock on its file through the entire cycle, and the attempt is written before the password check and cleared only when the login succeeds. Underneath that is a server-level limit that only counts login attempts, not regular panel openings. Checked: fifteen parallel attempts, nine were rejected on the server, and of the remaining six exactly five entered as wrong password and one as limit exceeded.
In addition, a log of failed logins with a reason was introduced — wrong password, limit exceeded, session expired — so the next time a "can't log in" message arrives, the answer is looked for in it, not guesswork. The retention period is ninety days and this is described in the privacy policy, because the record contains the IP address and browser tag.
Three failures that looked like one
In the middle of August, a report arrived with two symptoms: sometimes you can't enter the panel at all, and the site shows transmissions from a few days ago. There were three independent causes.
First. The sessions were sitting in a shared system directory that the operating system cleans every thirty minutes, deleting anything older than twenty minutes. The application expected a two-hour session, but the system cleanup made that setting ineffective. Consequence: constant logout in the middle of work, and at the next login a message about an expired request, which looks like the password does not work. Sessions are moved to their own directory outside of the scope of that cleanup, with their own collector turned on — because the default installation disables its own collector, figuring it's a system task doing the job.
Second. Opening the panel triggered three parallel requests, one of which was synchronously checking the availability of external sources. PHP holds an exclusive lock on the session file until the end of the request, so when the source was slow, all three requests lined up behind that lock and the panel looked dead — then appeared to recover when the cache got warm. Fix: session is closed for writing as soon as the user is found to be logged in, wait times are reduced, and resource failure is remembered for five minutes.
Third. A broadcast card never disappeared automatically. A finished match remained on the site until the owner manually deleted it — it was literally "streams that ended days earlier". First, a deadline was introduced, so the owner chose a different rule: no automatic expiry, but with a clear indication of age. The panel now says how much time has passed since it was added, and after twelve hours the label turns yellow with a note to check if it's still up to date.
In addition, the browser cache kept the old list even though the server specifically requested that page not be cached — that header is not respected in the cache. That page now bypasses the cache entirely.
Site with no CSS and self-managing cache
Separate login, which has been recurring for months: site sometimes loads bare, without styles. It seemed like a server crash. The server was innocent — twelve hundred successful responses over styles and no errors in the log.
The root was in the browser helper. He kept a copy of the style at /css/style.css and the page was looking for /css/style.css?v= with the version number. Address comparisons are full by default, so there was never a match — which meant the style was purely network dependent. One glitch in the mobile connection and the page is without styles until the next refresh. Most often, it appeared immediately after the changes, because then the version number changes and the browser does not have a copy either.
The repair takes place in three steps: the cache miss is first repeated with a new attempt after half a second; if that also fails, a previous version of the same file is taken from the cache instead of the error; only then is it given up. Old versions clean themselves up, but a copy without a version number is deliberately kept as a last backup for the first offline entry. Checked with network off: page still has full styling and its own font.
Also, caching on the server has been fixed. The pages are no longer kept in the browser for an hour, but are always checked, while the server cache of finished pages is still running underneath them. Static is kept for thirty days as immutable, because its addresses carry a version number — and now sends one caching header instead of two that overlapped. The goal was simple: that no visitor should ever be instructed to do a hard refresh.
Cookieless statistics
The owner wanted to see what people were really looking at, but without setting cookies on visitors. That's why the site has its own, anonymous statistics, embedded in the same panel as the broadcasts.
The data is stored in a SQLite database on the server. A visitor is recognized as an abbreviated fingerprint calculated from a monthly salt, IP address and browser tag — no cookies, and the salt rotates monthly, so the trail cannot be tracked over time. The receiver accepts only POST, always responds with the same empty response, is limited in size and number of requests, and only accepts pre-known paths. The transfer mark is counted only if that transfer actually exists in the site data, so fictitious names cannot be inserted from the browser.
In the panel you can see who is online at the moment and on which page they are, and six basic numbers — views, visitors, visits, viewing time, the most viewers at the same time and the number of messages from the form. Below that are hourly or daily charts and tables: pages, arrival sources, countries, devices, browsers. A special table measures viewership per transmission.
The details that keep that part on its feet: the state is read from the local database on the server, without any external service; viewing time is entered conditionally, so that two open tabs do not count the same time twice; and the recording of the current highlight is made for a maximum of ten seconds, because during a big match, recording every beat would become a bottleneck.
In addition, Google Analytics works on the site, but with consent according to the Consent Mode v2 standard and default rejection — until consent without cookies. The privacy policy has been corrected by the way, because at one time it claimed that third-party analytics were not used, while it was already on the site. Text that doesn't agree with what the code does is worse than no text at all.
SEO, Legal and Security
The homepage title was reduced to just the brand name, because name search is the only way people get here — a five-word addition was just wasting space in the result. The site carries structured data of the type Person, Organization and WebSite, with the brand's founding date and links to all its channels, so that search engines see the site and profiles as the same entity, and not as four unrelated things.
In robots.txt, the rules for language model robots are written, and the site also has security.txt with the address for reporting security findings. The certificate has CAA records set, the site is listed to force HTTPS at the browser level, and received the highest rating for connection setup in the May 2026 check.
From the same passage is a finding that is not visible in the code: the domain had an IPv6 address, but the server listened only on IPv4. Visitors arriving via IPv6 received someone else's default certificate and a warning that the connection was not secure — to them, the site looked like it had been hacked. Fixed by adding IPv6 listening, so both addresses now respond with the same certificate.
Sensitive parts are closed at the server level and checked by request, not by assumption: data directory, access data file, internal code, and file backups — all return rejection.
The legal part is two pages written for this site, not copied: privacy policy, which describes both internal statistics and security records, and Terms of use, which states what the site is, what is allowed, and the limitation of responsibility for content from external sources.
Outcome
What the client received
A site the client owns. Code and data are on the server, they can be copied and moved; no monthly subscription to the platform, no plugins that break on the next update, no third party service to pay to see a visit.
Practically, the day looks like this. When she wants to select something that's playing that night, Alexa opens the panel from her phone — it's installed as an app on the home screen — pastes a link or selects it from a list, and the tab is on the site. When the match is over, he deletes it, or leaves it until the panel beeps with a reminder to check if it's still current. When he wants to see how it went, he opens the same panel, tab further.
The site is still under active maintenance. It went through several passes that are seen in the text as fixed bugs: sessions, cache, login, speed, resource limits. The addresses of external sources are deliberately in the settings, not in the code, because such things are shut down and changed without notice — when this happens, it changes a single line, not a new site.
All changes go directly to the live site, with a backup before each one, and with clearing the cache and refreshing the PHP process right after, because otherwise the owner is served the version he just replaced for an hour. It is a lesson from this project that is now applied to all sites on that server.
FAQ
Frequently asked questions
Are the transmissions stored on your server?
No. Cards on the broadcast page embed publicly available third-party sources, and the site data only shows the source URL, title and time added. The server does not download, store or rebroadcast video. On the page itself, there is a note that the copyright belongs to the owners of the content, with an invitation to contact anyone who believes that something has been uploaded without authorization.
Why does the server not proxy the media instead of the visitor loading it directly?
Because it was a conscious decision not to do so. A server that downloads and rebroadcasts other people's material becomes a distributor, with everything that goes with it, and there are several dozen client sites on the same machine. The proposal was considered once and rejected.
Can the owner himself add and delete cards?
He can, from the panel, on a phone. The panel is on a separate subdomain and is installed as an app on the home screen, so it opens in two taps. None of that requires a code change.
Why own stats and not just an out-of-the-box tool?
Because of two things. The first is that it works without cookies and that the data remains on the site's server. The second is that it measures exactly what makes sense here — how many people are watching which broadcast at the same time and for how long — which the ready-made tool does not provide without additional setup. Google Analytics exists in addition, but only with the consent of the visitor.
Why one page and not a site with ten subpages?
Because the content lives on networks, and the site has another job: to tell in one place who is behind the brand, what it does and how to get in touch. Ten subpages would mean nine blank. The transfer side is separate because it does a completely different job and has its own rules.
What happens when an external source stops working?
The source addresses are in the settings, not in the code, so they are changed in one line. The panel also shows if the source returns anything at all before the owner tries to add the card — an earlier version of that check counted what the source promises, not what it actually delivers, so it showed green even when there was nothing.
Next step
Have a project that needs to work better?
Send me your goal and current situation. I will reply with a concrete scope proposal.
Start a project