Oct 25, 2024
I rarely mention or use my last name, Lijić, when introducing myself because it’s a bit of a tongue twister, not just for my international friends, but even for Croatians. I’ll never forget the first time I had to say it out loud.
I was 6 years old, at my first swimming practice. I changed quickly and ran from the dressing room to the pool, not realizing I had joined the wrong group, the one that was actually finishing its training just before mine was set to start. So, I jumped into the pool, spent about 10 minutes there, and then went back to the dressing room, thinking practice was over. When I went outside, my mum wasn’t there (she probably went home or grabbed a coffee, expecting the session to last an hour, not 10 minutes). I panicked and started crying. A kind lady, probably the club’s secretary or some kind of employee, asked what was wrong, and I told her I was left alone. When she asked for my name, I said quickly, “Toni Lić (leech)”, instead of "Lijić (lee-yeech)". I later learned how to spell it properly, which definitely helped me down the line.
Error Pages
I was looking for a place where I could pay a small homage to my last name, and I stumbled upon the idea of using a 404 page (or any error page). These pages aren’t visited frequently, and when they are, it’s usually because something has gone wrong. Most people don’t put much effort into designing them, often treating them as an afterthought and hoping no one ever sees them, assuming everything will run smoothly and error-free.
Honestly, I’m pretty sure this is the first time I’ve designed and implemented a custom 404 page. The only other time I remember working on one was when I was creating concepts for Dribbble, back when it was popular.
Starting Point
I’m originally from Croatia. Part of my family is from Istria, and the other part from Dalmatia. My family name comes from a small village in Dalmatia. There are many theories about its origin, but most suggest that it comes from an old Croatian word for “fox,” while some sources even mention it could mean “wolf.” In modern Croatian, it translates to “little fox.”
The phrase “little fox/wolf” gave me enough juice to work with.
A simple layout featuring a big illustration of the fox character in the middle, along with some supporting text that you usually find on error pages.
The Process
I usually capture my initial thoughts quickly and messily in my pocket notebook, as they often come to me out of the blue, typically during train rides.
Once I’m satisfied with the direction, I usually move to Procreate on my old iPad Pro 10.5. However this time, since my partner needed it for her conference-thingy, I had to go old school, and use pen and paper.
I hadn’t drawn this way in a long time, and I really missed that double-tap gesture from Procreate to undo. As a result, it took me longer than I expected.
The big idea was to have a fox-like character either sleeping or digging/looking for something in its foxhole, surrounded by items that represent my hobbies: Yugi’s Millennium Puzzle (from Yu-Gi-Oh!), books, a guitar, a camera, a pump (for cycling)..
As I was sketching, I made multiple variants of that layout but couldn’t nail the right proportions of the character. I kept worrying about whether it was feasible to turn such a complex sketch into a simple SVG. Since I really wanted to create this illustration as an SVG for easy manipulation—not just for coloring, but also for future use if I decide to animate it—I decided to abandon my initial idea and go for something really simple, but still enough to convey the message.
I settled on a simple but cute fox-like character with an awkward facial expression borrowed from manga. As I’m also a big anime and manga fan, especially shōnen. I wanted to showcase that part of me as well. Since most people know me not only for my illustration skills but also for always choosing citrus fruits over chocolate, especially cold oranges, I decided to have my character holding an orange.
That worked perfectly for the light theme, but as I was thinking about which color palette to use for the dark mode, it dawned on me to adjust my fox-like character to also resemble a small wolf. Since my brand color for the dark theme is purple, I ran into a problem, a purple orange doesn’t exist. So, I started searching for a purple fruit. I’m also a bit obsessed with grapes and good wine (mostly white, though), so I tried to tweak the fruit to keep the traits of an orange-like fruit while making it resemble a grapefruit. Then I let the idea sit for a few days.
In the meantime, I had dinner with friends, and one of them, who really enjoys baking, kept talking about how he prefers to use passion fruit in his cheesecake, since cheesecake is basically the only cake I eat. As I had never tried it, he promised to make it for me next time. He described its taste as quite sour but with just enough sweetness. I figured I’d probably like it, and the best part is that it has a purple-ish exterior. So, let’s say that the fruit the “wolf” holds is a passion fruit, but if it looks more like a plum or a grape to you, that’s okay too.
Page Layout and Its Build
Instead of jumping straight into vectorization, which is probably the most time-consuming part, especially since I didn’t want to rely on any AI tools for it, I decided to take a break from illustrating and switched to coding for a bit.
My site is built with Next.js and deployed via Vercel. Starting with Next.js 13.3, managing custom 404 pages and handling unmatched routes has become much simpler.
All you need to do is create a not-found.js or not-found.tsx file in your app directory.
//not-found.js
export default function NotFound() {
return (
<main className="flex flex-col items-center justify-center h-full">
<div className=" size-48 md:size-60 mt-16 mb-20 md:mb-24 mr-5">
<Illustration />
</div>
<div className="flex flex-col gap-4 text-center mb-16">
<h2 className="text-xl sm:text-2xl font-semibold">
Sorry, Foxed Again!
</h2>
<p className="text-toni-text-light/60 dark:text-toni-text-dark/60 text-pretty text-base max-w-[275px] sm:max-w-[400px] ">
It seems I haven’t built this page yet, or I used some odd naming that
caused the confusion.
</p>
</div>
</main>
);
}
Vectorization
My tool of choice for this case is Sketch. For any non-web-related illustrations, I usually use Adobe Illustrator (when I have a license).
Why not Figma? While it’s certainly possible to create vector art in Figma, I find Sketch more convenient, particularly when it comes to handling SVG exports. The SVGs from Sketch are cleaner and easier to work with.
I also prefer Sketch for non-product-related tasks because I truly admire its attention to detail and the high level of polish in its UI. Sketch was my gateway into the world of UI design, and even though I hadn’t used it for nearly four years, I’ve recently been drawn back to it, especially for app icons, icons, and web illustrations. Plus, their stance on AI resonates deeply with me.
When vectorizing, I usually start with the outlines and then add the base fills and shadows. It’s important to keep the fills and outlines on separate layers, as it provides more flexibility for adjustments later.
I typically avoid applying an offset path or converting strokes into paths unless I’m absolutely sure I’ll only need that specific thickness. In this case, I left it untouched.
I treat every detail as a separate individual—like the eyes, the fruit, and the little fox body—because it makes it easier to apply fixes or changes later if needed.
If I have multiple types of shadows or base fills within a single item, I usually name them semantically. For example, I might use names like “fur,” “fur-shadows,” and so on.
The cool thing about Sketch (and maybe Figma does this too) is that each group folder is assigned a unique ID. While I primarily rely on classes for styling since I use Tailwind, having these IDs as a starting point really simplifies navigation through the SVG file.
Optimizing SVG
Before I start manipulating an SVG, I usually run it through an optimization tool, as SVG files often contain a lot of redundant information. This includes editor metadata, comments, hidden elements, default or suboptimal values, and other items that can be safely removed or converted without affecting rendering.
I came across an open-source solution, SVGO, that does this perfectly and provides a high level of control. You can install a Node library or adjust your SVG directly via the playground.
Preparing SVG for Tailwind
As I mentioned earlier, I use Tailwind CSS for styling. Since SVG files don’t support Tailwind by default, I created a separate React component that returns my SVG. This way, I can use Tailwind, primarily for dark and light themes.
<!-- RAW -->
<path
id="furr-shadows"
fill="#C6BCA9"
d="m1309.24...-43.766Z"
/>
<!-- TAILWIND -->
<path
className="furr-shadows fill-toni-label-light/15 dark:fill-toni-text-light/15"
d="m1309.24...-43.766Z"
/>
And that’s it! The only thing left to do is animate the character, but I’ll save that for another time and for another blog post.
You can also check out the live version here.
Until next time!