Skip to content
D. Svilenković
01Work02Services03Industries04Guides053D06Check your site07Contact

HomeWorkHalo City Leskovac

Halo City Leskovac

phone sales and repair on a website of its own

A three-person shop in central Leskovac that has been selling and repairing phones for twelve years, yet was practically invisible in search. It needed five pages covering what people actually type, one-tap calling instead of a contact form, and a look that doesn't come across as cheaper than competitors with a real domain.

  • Multi-page website
  • Leskovac
  • August 2026
  • 13 min read
  • Next.js 16
  • React 19
  • Tailwind 4
  • TypeScript
  • CSS animations
Customer
Halo City Leskovac
Industry
Mobile phone sales and repair
Area
Leskovac and the Jablanica District
Type
Multi-page website, five public pages
Technologies
Next.js 16 · React 19 · Tailwind 4 · TypeScript
Website
halocity.svilenkovic.rs
Status
Live since May 2026, on our subdomain
Home page of the Halo City Leskovac website with the heading Mobile phones and repairs in Leskovac
Home page: call and Viber right below the heading, next to a video of phone parts

01 / 11

What Halo City does

Halo City Leskovac is a mobile phone shop and repair service at Bulevar Oslobođenja 1, right in the center of Leskovac. The shop has been in business since August 2014, has three employees and holds a 4.3 rating from 41 reviews on Google Maps (as of September 3, 2026).

The business stands on two legs. The first is sales: new phones from popular brands (iPhone, Samsung, Xiaomi, Huawei, Honor, OPPO), checked used devices, and accessories such as cases, screen protectors, chargers, cables, headphones and holders. The second is repairs: screen and battery replacement, charging ports, liquid and moisture damage, software and system issues, cameras and speakers, all the way to micro-soldering on the motherboard when a phone shows no signs of life.

Customers don't come only from Leskovac. Vlasotince, Lebane, Vladičin Han, Bojnik and Medveđa all look to the city: places people travel from with a broken phone to reach the nearest larger town. That is exactly why a website matters to a shop like this: someone whose screen has just cracked asks a search engine first, not a neighbor. If the shop isn't in the results, it doesn't exist for that person.

Everything the shop offers was already there: twelve years in business, a rating, regular customers and an address in the center. The only thing missing was an address on the internet.

Products page on the Halo City website with instructions for checking the model before buying
Products — check the model first, then call; the site shows no stock or prices

02 / 11

Why the site lives on our subdomain

We should be upfront here. halocity.svilenkovic.rs is our subdomain, not the client's domain. The shop is real and the site has been live since May 2026, but the business doesn't have its own domain, so the site runs on our infrastructure, on a host named after the shop.

This is not a parked page waiting for something to happen. The site has its own HTTPS certificate that renews automatically, its own sitemap and robots.txt, its own analytics with cookie consent, its own property in Google Search Console and in Bing Webmaster Tools, and its own IndexNow key for reporting changes to search engines. It works like any other website; its address just happens to be a subdomain.

Where it does cost something is local SEO. A domain of its own, with the business name in the address, starts from a better position for searches like “phone repair Leskovac” than a subdomain does, and it's fair to say so rather than pretend there's no difference.

The move is prepared and has already been rehearsed once. In July 2026 the site was moved from the old working host to the current one, and the old address got a permanent single-hop redirect that kept the path: /servis went to /servis, not to the home page. The same procedure awaits the real domain once there is one: DNS record, certificate, updated canonical URLs and a 301 from the subdomain. That's half a day's work, not a new site.

Service page on the Halo City website with instructions on what to report before coming in
Service — what to send before you come in and how to describe the fault

03 / 11

What needed solving

The task wasn't “make the shop a website” but four concrete things:

  • Show up in search for two different lines of business. Someone buying a phone and someone with a cracked screen are not the same visitor, and they don't type the same thing. One page can't rank first for both searches.
  • One-tap calling. The owner and two employees are behind the counter all day. A contact form nobody opens is worse than no form at all.
  • Look serious. There is already a competitor in town with a real domain and a longer track record online. A three-person shop can't beat it on volume, so it has to win on looks and clarity.
  • Don't promise a price that changes. The price of a screen depends on the model and on the exchange rate. A number on the site that doesn't hold is worse than no number at all.

Along with that came a requirement that's easy to overlook: the site has to work on a phone with a weak connection, because it's most often opened by someone with a faulty device who is sitting on a bus. Every decision about speed, including in the end the one to take 3D off the site, follows from that one sentence.

04 / 11

Five pages instead of one long one

The first version was one long page with all the sections, the way it's usually done for small businesses. It soon became clear that this didn't solve the first point of the brief. A page has one title, one description and one main search term, and with that term it competes either for sales or for repairs, never both.

So the site was split into five pages, each with its own title, description and canonical URL:

  • Home — the three shortest routes to information (products, repairs and the address), why people trust the shop, customer feedback and the location.
  • Products — the current range without a catalog or prices: which three details to send to get an answer on the first try, and the questions customers ask about the range.
  • Service — what to send before coming in, what to do before handing over the phone, and the most common questions about repairs.
  • About us — only details that can be verified: founding date, address, company registration number, tax ID (PIB) and registered business activity, with a link to the public business profile.
  • Contact — address, mobile and Viber, landline, email, opening hours and a navigation link.

Titles include the city wherever people search for a term together with the city: the home page is “Mobile phone sales and repair Leskovac” and the service page “Mobile phone repair in Leskovac”. It sounds like a detail, but it's the difference between a page competing for a term with the city and a page competing with all of Serbia.

No page is a dead end. The products and service pages end with a call button, Viber and directions to the address, and the page about the shop leads on to products, service and contact.

05 / 11

Call and Viber instead of a contact form

There isn't a single contact form anywhere on the site. That was a decision, not an oversight.

On a small shop's website, a form works like this: the visitor writes a message, the message lands in an inbox that gets opened in the evening or never, and in the meantime the person calls someone else. A phone rings immediately. A Viber message arrives immediately. That's why the site offers only those two routes, on every screen.

The number in the header is a live link that opens the dialer on a phone. The Viber button opens a chat with a pre-written message: on the products page the message already asks for the model, storage and color, and on the service page for the device model and a description of the problem. The owner gets a message that already says what it's about, instead of an empty “hi”.

The contact page covers the rest: address, mobile and landline numbers, email, opening hours by day with “closed on Sundays” spelled out, and a link that opens navigation. The map is a story of its own. In the first version it had a filter over it, so it looked like a broken image; it was then replaced with a plain embed, and in the second version of the site the embedded map gave way to a navigation link and a link to the shop's Google profile.

A side benefit of going without a form is legal. The site collects no personal data through the web, so the privacy policy can be short and true instead of long and copied.

06 / 11

The price list that was dropped on purpose

For a while the site had a full repair price list with amounts in dinars. It was removed entirely, and that was a good decision.

The cost of a screen replacement depends on the model, on whether an original or a tested part goes in, and on a purchase price that keeps changing. A price list on the site that doesn't keep up with the shop creates two problems: a customer who walks in with a printed number in their head, and a shop that has to explain why that number no longer applies.

The first replacement for the amounts was a description of the process: free diagnostics, a price before the repair, and the repair only once approved. In September 2026 the site got a second version, written so that only what can be verified stays on the page, and that description went too. Today the site promises nothing about price. It says what details to send, and the shop confirms the price, availability and whether it can take the device, by phone or over Viber.

The same principle applied when the business changed. The site had a whole page about buying used phones; when the focus shifted to sales and repairs, that page was removed along with every mention of buying in the menu, descriptions, structured data and sitemap, and the old address was redirected to sales so that no saved or indexed link ends up nowhere. The site follows the shop, not the other way around.

07 / 11

The 3D that didn't survive the second version

This is the part with the most trial and error, and where the most work ended up in the bin.

From the start, the idea was for the site to have a live, three-dimensional background, something that says right away that this isn't a twenty-euro template. The first serious version went a step further: the phone was modeled in Blender from a script and exported as a .glb model of about a hundred kilobytes with no external decoder, then duplicated into a fan of five devices in different colors standing in the hero. A photorealistic background with three phones was rendered from the same model as well.

On screen it looked fake. Not bad — fake. A phone in a video game and a phone on a shop's website are not the same thing: a customer knows what a real iPhone looks like and sees right away that they're looking at a model. That whole layer was deleted the same day, along with the model, the render and the script that produced them.

The replacement was a single real photo of a phone lineup, cut out with a background removal tool and compressed into a WebP of 46 kilobytes. The result looked better than anything modeled before it and weighed about as much as an icon.

Since November 12, 2026, that spot has held a short looping video: phone parts laid out on a workbench, with a caption saying it's an illustration, not a photo of the shop. The first frame is a plain image that loads right away, and the 0.86 MB video itself isn't preloaded.

After that, the 3D layer lived on for a while as a background: a WebGL scene with sixteen pale, faceted crystals floating in the depth, with dust, fog and a camera that gently followed the mouse and the scroll. In the second version of the site, in early September 2026, that scene was removed entirely, along with three.js and the other 3D libraries, the animation library, smooth scrolling, the intro screen and the strip of brand logos. Today the site's code has no 3D dependencies at all.

Now the browser itself draws the background from a few CSS rules: two soft blobs of color, blue at the top right and a warm yellow at the bottom left, a fine grid that fades downward, and a large irregular ring that completes a turn in thirty-eight seconds. There's no script to wait for and no scene to pause and clean up, and the layer is there from the page's first paint. When reduced motion is turned on in the system settings, the ring stays still.

The rest of the motion is just as modest. Sections rise slightly as they come into view, and on the home page a thin bar at the top shows how much of the page has been read, while on wide screens a signal line on the left fills up as you scroll. These are CSS transitions and two small components, without a single animation library.

08 / 11

Speed — a first screen with no waiting

While the 3D scene existed, the whole build answered to one rule: nothing 3D may happen before the visitor sees the content. The library wasn't imported into the main bundle; it loaded later, only once the page had fully loaded and the browser was idle. Measured before and after that change, the mobile score went from 88 to 92, and the time the main thread was blocked dropped from 380 to 250 milliseconds.

On top of that, the scene paused when the tab wasn't in the foreground, the pixel density was capped, and when the component was removed, all geometries and materials were properly released. With reduced motion turned on, or without WebGL support, the scene didn't start at all.

The second version solved all of that work by removing it. Without a 3D library there's nothing to defer, pause or release when moving between pages, and the background costs no more than a few rules in the stylesheet.

The same care applies to everything else. The hero image loads immediately and with high priority, because it's the first thing the visitor sees. Sections appear on scroll, but they're hidden only by the same script that reveals them: without JavaScript nothing is hidden, with reduced motion everything shows at once, and if something stalls, whatever is left appears after five seconds.

One measurement trap from the first version is worth remembering, because it comes up on every site with a gradient heading. Back then the main heading was colored with a gradient clipped to the text, which technically makes it transparent, so the automated test didn't count it as the largest element on the screen. On text-heavy pages the cookie banner, which appears after loading, became the candidate instead, so the lab result showed five seconds, while an independent measurement in a real browser showed just over one second. The lab number was an artifact, not a fault, and it was treated as one.

09 / 11

SEO and local visibility

Every page went through a pass in which titles were cut to the length a search engine actually displays and descriptions were brought under a hundred and sixty characters. The home page title went from ninety-two characters to fifty-five and starts with the search term, not the business name.

Structured data is the biggest part of the local work. The site carries a linked graph with the mobile phone store, the registered business with its full legal name, company registration number and tax ID (PIB), the website itself and, on subpages, the breadcrumb trail. Alongside these come the address with postal code, geographic coordinates, opening hours by day and the founding date. The rating, the number of employees and the list of nearby towns were part of the graph in the first version and were left out of the second.

One thing had to be fixed along the way. The FAQ block had been set up for the whole site, so it was reported to search engines even on pages with no questions at all. It was changed to appear only on the sales and service pages, where those questions are actually on screen. Data that promises something the visitor can't see is a mistake that comes back to bite sooner or later.

On top of that come hyper-local meta tags that are rarely set: a region code, coordinates, the place name and contact details in a format social networks read. The robots.txt file explicitly lets AI bots in as well, because more and more answers today come from a conversation with an assistant rather than a list of results. The sitemap has six URLs and is submitted to both search engines, and changes are also pushed through IndexNow.

The move to the current host also brought an instructive problem. The search engine crawled the new host the same day it went live, while its content was identical to the old one, and declared the old address canonical. So for a while the new site was tidy, indexed and invisible all at once. The fix was permanent redirects from the old addresses, a manual recrawl request and patience; the technical side was correct the whole time, the search engine just needed to be told which address was the real one. After that pass, every page scored a hundred on the technical part of the audit and passed code validation without a single error.

10 / 11

Analytics that respects the answer

The site measures visits, but only once the visitor allows it. The cookie banner offers three answers (accept, essential only and settings), and analytics is set to denied by default until the visitor decides. Functional cookies always work, because without them the site couldn't display properly.

For a while that setup had a silent bug worth describing, because no test shows it. The banner stored consent under one name, and the part that switches analytics on read it under another. The first time, everything worked: the visitor clicks, measurement starts. But a returning visitor who had already consented doesn't get the banner, so measurement never started for them. The result was statistics that systematically lost exactly the people who come back, the most valuable part of the traffic. The fix was one word in the code; finding it was the whole job.

The privacy policy was written for this site, not copied: it states what is collected (anonymous visit statistics, and only after consent), what isn't collected (no data through a form, since there is no form), and what the visitor can request.

11 / 11

What the shop ends up with

An address on the internet that works without upkeep. The site runs on the server as a standalone application behind the web server that serves it, with a certificate that renews itself and a full set of security headers. No plugins that fall apart at the next update, no monthly platform subscription, no admin panel someone has to log into to keep the site running.

In practice, a day looks like this: someone from Vlasotince searches for where to get a screen replaced, finds the service page, sees what to say about the phone, taps the number or Viber, and knows before setting off whether the shop takes that device. No form, no waiting for a reply, no steps in between.

One thing remains that doesn't depend on code: a real address. The shop has a Google Maps profile with a rating and reviews, and that profile is the strongest lever a local business has. Once this address goes into its website field, the two start working for each other. When the shop gets its own domain, the move is already prepared.

Until then, the site does what it was built for: twelve years behind the counter finally have a place to be seen, on a page that opens instantly even on the weakest connection.

Numbers

Measured, not promised.

100Mobile speed, Google PageSpeed
2026Year launched

On a phone

The same site, in your hand.

Most visitors come from phones, so the layout, buttons and images are arranged for the small screen first.

Halo City Leskovac on a phone

Questions

What clients ask.

Why is the site on a subdomain and not on its own domain?

Because the shop doesn't have its own domain yet, and the site needed to go live. A subdomain has everything a real domain has: a certificate, a sitemap, analytics and a property in the search engines' webmaster tools. The only difference is a weaker starting position for local searches. Moving to a real domain means changing the DNS record, the certificate and the canonical URLs, with a permanent redirect, not building a new site.

Why is there no contact form on the site?

Because in a shop with three people behind the counter, nobody watches the inbox during the day. A message from a form waits; the phone rings right away. Instead of a form, every screen has the phone number, which opens in the dialer with one tap, and Viber with a pre-written message, different for buying and for repairs.

Why are there no repair prices on the site?

Because the price depends on the model and on what the parts cost the shop, so a price list on the site goes out of date faster than it can be updated. Instead of amounts, the site says what details to send: the manufacturer, the exact model and a short description of the problem. The shop confirms the price and whether it can take the device, by phone or over Viber.

Does the animated background slow the site down on an older phone?

No. The browser itself draws the background from a few CSS rules: two soft blobs of color, a fine grid and a slowly rotating ring. It doesn't need a single line of JavaScript or a 3D library, and if reduced motion is turned on in the system settings, the ring stays still. The earlier WebGL scene was removed in September 2026.

Why Next.js and not WordPress?

For speed, and because there is nothing to maintain. Pages are served prebuilt, with no database and no plugins that need updating every week. A site this size on WordPress would mean several plugins for what the framework does on its own here, plus constant attention to security.

How many pages does the site have, and can it grow?

Five public pages plus a privacy policy. A new page is a new route in the code and one line in the sitemap. The site has already grown once, from one long page to five, and has already been trimmed once, when the shop stopped offering one service.

Related projects

From the same field.

Next projectMedica CentarMulti-page website · Niš

→Contact

Have a project? Write to us.

Four short questions, about a minute of your time. We reply within 24 hours.