Project: Nefis Food
Website: nefisfood.kz (prev: nefis-fork.vercel.app)
GitHub: đ
Nefis Food is a company founded by my relatives which produces sugar, coffee and other HoReCa related products. They needed a digital presence for their company in the form of a website, and I helped them with that.
Nefis Food had a website before, which was created using some no-code tool. But my relatives wanted a refresh, and theyâve recently updated the company logo so website needed update as well.
About the project
They had a few wishes about the end result of the website:
- Website should showcase companyâs products, details page, images.
- Design should match the logo and brand colors.
- Website should support multiple languages.
- Website should appear on search results when searching for companyâs name.
As for everything else, I had the freedom of choice.
So, after a few discussions with them, I began exploring the ways to build the website. And firstly, when it comes to choosing the correct way to build something it maybe best to start thinking about what we are trying to achieve and what are the requirements/constraints.
Similar ideas Iâve learned from this article: https://philipcdavis.com/apple.
Start
So, what are the requirements/constraints? what is the end goal?
- Website showcasing companyâs products, details page, images.
- Website with relevant design to the companyâs brand.
- Website supporting multiple languages.
- SEO
And also some things to consider:
The company is based in Kazakhstan, more specifically in suburbs of Shymkent, where generally internet connection quality is poor. And, the website acting as a digital storefront, being visited by potential customers should load fast, be responsive, so visitors do not leave because of slow loading times.
This also impacts SEO
So:
- Speed, performance, responsiveness of the website.
Website will not be updated frequently, the types of content also wonât change much, so optimizing for easy to make updates and maintainability is helpful because in the future, when something needs to be updated or added, it should be easy to open project repo, understand the written logic/code and make necessary changes.
So:
- Easy to update, maintain code and content.
And lastly, the cost of managing website should be as low as possible, it should not cost much to run.
So:
- Hosting and maintenance cost.
Technical choices
With these almost-defined requirements, it was pretty clear that website will be fully static, being fully static has its own tradeoffs, but in this very case, it was the right fit.
At work we mostly build client-side rendered websites, single page applications, and I was curious to try out this way of building websites. Because Iâve known that in the early days of web websites were mostly static, browser, web and html APIs were implemented to suit static website needs(form and anchor elements behavior for example) and yeah it was interesting to learn how it feels to build in an old school way.
I mentioned in my previous post, that I maintain a list of tools/technologies to try out, and one of them was Astro. Based on user reviews(twitter, hacker news etc.) Astro seemed just right for all the requirements!
Design
Colors and fonts really make a difference when it comes to delivering a message/communicating with user, they can set the mood, create associated feelings. Oh, and of course copywriting too, but I dont have enough experience in that yet, so the copywriting part couldâve been improved(which is also a part of reason that Iâm writing this blog post xD)
So, after some brainstorming in Figma and doing some research following *vibes*, *associations* felt good:
- Calm, warm, welcoming, unsaturated, slow(in a sense of information density). These are adjectives that seemed to fit nicely with the website.
- Base font: Inter. And some other decorative, handwritten-ish fonts for special occasions.
- Colors: company main color is green(#7cb82e)
Development
So Astro comes with some goodies, like <Image />
and <Picture />
components which help with image optimization, jsx-like syntax, pre-fetching/rendering techniques, i18n routing, client directives, managing content with content collections. All of these features were used in project and led to a nice development experience.
- Image optimization: for images
<Picture />
was such a lifesaver, it automatically converted original images to avif and webp formats at build-time, and also generated different sizes of images for different screen sizes. This was a huge win for performance, because images are the biggest part of the website, and they are the biggest bottleneck for performance. The main part is that it was all automatic, I just had to specify a few props and thatâs it.
<Picture
src={img}
widths={[240, 540, 720, 1080, 1200, img.width]}
formats={["avif", "webp"]}
alt=""
/>
-
Pre-fetching/rendering: Astro provides a way to prefetch a page(on hovering a link for that page for example) so when user hovers a link, the page is fetched and when user clicks on it, the page is already there, no loading time.
-
Multiple language support: Astro has a built-in i18n routing configuration, with it you can structure your project files in an understandable way. With that, I was able to support multiple languages, have different routes for different languages, and also manage different content for different languages.
-
Content collections: this feature helped to manage content in a structured way, it is important to have a clear structure for content, because it can get messy quickly as you scale. Using a config file(with Typescript, Zod support) I was able to define strict shapes/rules/types for content.
-
Client directives: Iâve used React components for some parts of the website. Client directives helped to choose how to render those components, when for example I needed to render a component only on client-side, or SSR it.
So basically Astroâs features hit right on the spot for the requirements.
Font optimization
Did you know that you can load only needed subset of a font? For example, if you only need cyrillic characters, you can load only those characters, and not the whole font. If you use Google Fonts, you can set subset
parameter in the url, and it will load only those characters. Example:
https://fonts.googleapis.com/css?family=Roboto+Mono&subset=cyrillic
Moreover, remember that I mentioned I needed some decorative, handwritten-ish fonts for special occasions? I needed decorative font only for this headline âWe make the world sweeterâ. So I was loading whole font for just one headline, but reading Google Fonts docs I found out that you can load only needed characters of a font, like this:
https://fonts.googleapis.com/css?family=Inconsolata&text=Hello%20World
In this case, only characters âHello Worldâ will be loaded, and not the whole font. Docs say - âIn some cases, this can reduce the size of the font file by up to 90%.â(link)
SEO
For SEO, Astro has a sitemap integration, which generates a sitemap.xml and robots.txt file at build-time. In addition to that, I used @astrolib/seo
package to generate page metadata, like title, description, OG tags, and other meta tags. Also, during development I learned about structured data, which is a way to provide search engines with information about the content on your website. It should be added to the page as a script tag with relevant data.
Hosting
The TLD of the website is â.kzâ, which is the top-level domain for Kazakhstan. By law, websites with â.kzâ TLD should be hosted in Kazakhstan. Initially, I wanted to host the website on Vercel or Cloudflare, but because of this constraint, I had to look for hosting providers in Kazakhstan. I found a hosting provider that was offering cheap hosting(~$1/month) suited for static websites, this option had some limitations too, like: no ssh access; limited disk space/capacity; limited server-side configurations. But this hosting provider had one handy feature - remote git repository deployment, so I was able to push changes to the git repository(GitHub) and the website was automatically updated via webhooks. Also one thing I had to do before pushing changes was to build the project locally and push the build folder to the repository.
Google Alerts
And one lil thing that I did was setting up Google Alerts for the company name, so I can get notified when something is posted about the company on the internet.
Analytics
For analytics, I wanted to self-host Plausible Analytics(thought it would be an interesting experience!), but because of time constraints, I had to delay it. And I ended up using Cloudflare Web Analytics.
Contact Form
The website has a contact form, where visitors can send messages to the company. To optimize the cost, I created an HTTP endpoint in Val Town that receives form data and sends it to the companyâs email through Resendâs SDK. With Resend I was able to configure the look of an email. This whole implementation was very simple and straightforward, both Val Town and Resend provide excellent DX.
OG Image generation
To generate OG images for each page, I used astro-selfie
Astro integration. It works by iterating over list of pages and rendering a page in a headless browser and taking screenshot of the top section of page using Playwright. Then that screenshot is used as an OG image for the page. One thing to note is that this process is slow, iterating over all pages and rendering them in a headless browser takes time, and with every change I was regenerating OG Images even though they were already created. So I âpatch-packageâdâ astro-selfie to add a skip option, so I can skip generating OG images when needed.
UPDATE: The home page is slightly updated, previous version is here, and the new version is here.