Building an NFT Web App Fast: My 7-Day Unitok Template Review
Coding Journal: Building a Static NFT Frontend in One Week
Last week, an indie gaming studio hired me to build a simple, clean catalog site. They are launching a set of in-game collectible items as NFTs and needed a frontend webpage to showcase them to their players. They already had their smart contracts and web3 wallet integrations figured out, but they had absolutely no design or front-end interface.
Because they wanted to host this statically on a budget-friendly cloud storage server, a basic HTML and CSS setup was the ideal route. They did not need a massive framework like React or Next.js just to show a list of items.
To save time and keep costs low, I decided to use a pre-made design. After looking through a few options, I settled on the Unitok – NFT Marketplace HTML Template because its dark-themed, modern style fit the game's aesthetic beautifully.
Here is my day-by-day journal of how I built the site, optimized the code, and solved a frustrating layout bug on mobile phones.
Day 1: Scaffolding and Cleaning Up the Code
On Day 1, I unzipped the template files and studied the folder structure. It is built with Bootstrap 5, modern CSS custom properties, and vanilla JavaScript. The code structure was clean, with folders for CSS, JS, fonts, and images.
To make my editing work fast and easy, I set up a quick local workspace. I initialized a private Git repository and used a basic Node.js setup with BrowserSync so my browser would automatically refresh every time I saved a file.
My first task was cleaning up. The template came packed with several different page variations, login forms, and modal windows. The gaming studio only needed three pages: the homepage, the item detail view, and an author profile page.
I deleted the extra pages, stripped out unused image files, and removed several third-party JavaScript libraries that we did not need. This reduced the template's overall file size by about 40% before I even wrote my first line of code.
Day 3: Fixing the Safari Mobile Masking Bug
On Day 3, I ran into my first real headache. I loaded the homepage on my personal phone and an old iPhone to test responsiveness.
On desktop, the digital art images on the NFT preview cards had an artistic, rounded border mask that gave them an organic shape. But on mobile Safari, this masking completely failed. The images reverted to plain, sharp squares that overlapped the card's dark borders. It looked messy and unprofessional.
Looking into the stylesheet, I found that the template used an SVG-based clipping path to achieve the shape. Mobile Safari can be notoriously picky about SVG clipping paths inside absolute-positioned elements.
To fix this, I decided to replace the inline SVG path technique with a standard CSS mask-image rule. I added vendor prefixes and a fallback format to make sure it worked across all browsers.
Here is the exact CSS code I wrote to fix the card borders:
/ Custom fix for NFT preview image masks on Safari mobile /
.nft-card-image-wrap {
position: relative;
width: 100%;
aspect-ratio: 1 / 1;
overflow: hidden;
/* Cross-browser mask support */
-webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect rx='20' width='100' height='100'/></svg>");
mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect rx='20' width='100' height='100'/></svg>");
-webkit-mask-size: cover;
mask-size: cover;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
}
By switching to a base64 encoded SVG directly inside the CSS mask property, the browser rendered the curves nicely on both Android and iOS devices. The cards now looked identical across all mobile screens.
Day 5: Replacing the Heavy Filter JS with Vanilla Script
On Day 5, I turned my attention to the interactive features. The template had a filter system on the gallery page. Users could click categories like "Weapons," "Armor," or "Potions" to filter the items displayed in the grid.
The default template used a heavy, jQuery-dependent sorting script. This plugin added an extra 75KB of JavaScript and was causing tiny layout stutters on low-end mobile devices when rendering a lot of cards at once.
Since we were already using Bootstrap 5, which does not require jQuery, I decided to remove the heavy sorting plugin completely. I wrote a short, lightweight script in vanilla JavaScript to handle the card filtering instead.
Here is the simple script I implemented:
document.addEventListener('DOMContentLoaded', () => {
const filterButtons = document.querySelectorAll('.filter-btn');
const nftCards = document.querySelectorAll('.nft-grid-item');
filterButtons.forEach(button => {
button.addEventListener('click', (e) => {
e.preventDefault();
// Remove active class from all buttons and add to clicked one
filterButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
const targetCategory = button.getAttribute('data-filter');
nftCards.forEach(card => {
const cardCategory = card.getAttribute('data-category');
if (targetCategory === 'all' || cardCategory === targetCategory) {
card.style.display = 'block';
// Trigger a tiny fade-in effect
card.style.opacity = '0';
setTimeout(() => { card.style.opacity = '1'; }, 50);
} else {
card.style.display = 'none';
}
});
});
});
});
This replacement cut down our active JavaScript execution time by almost 200 milliseconds and made the filtering feel fast and instantaneous.
Day 7: Speed Tweaks and Launch
On the final day, I focused on speed optimization and launching the site. Because the client was hosting this on a cloud VPS running Nginx, I wanted to configure the server to deliver the static HTML pages as fast as possible.
I ran a quick test on PageSpeed Insights. Our initial score was good, but we had a warning about render-blocking assets. To solve this, I inline-loaded the critical CSS required to render the top hero area of the page, then loaded the main Bootstrap styles asynchronously.
Finally, I wrote an optimized Nginx configuration file for the client to use on their server. This setup enables Gzip compression and tells the browser to store static images and fonts locally so the site loads instantly on repeat visits.
Here is the Nginx config snippet I used:
# Optimize delivery of NFT marketplace static files
server {
listen 80;
server_name my-nft-catalog.com;
root /var/www/nft-catalog;
# Gzip settings to compress files before sending over mobile networks
gzip on;
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
gzip_min_length 1024;
# Browser caching rules for images and web fonts
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|svg)$ {
expires 1y;
add_header Cache-Control "public, no-transform";
access_log off;
}
location / {
try_files $uri $uri/ =404;
}
}
When I ran the performance tests again, the mobile speed score climbed to 94 out of 100, and the desktop score hit 98. The pages load in under a second even on slow mobile connections.
Honest Pros and Cons
After spending a full week working with the code, here is my honest take on this product.
The Good: Very Clean Code: The CSS classes are organized logically and follow standard Bootstrap naming conventions, which made customization easy. Modern Design: The layout is visually striking. The dark-mode styling fits the gaming and crypto space perfectly. * Lightweight Foundations: The structure is easy to adapt, modify, and strip down for simple static hosting.
The Bad: SVG Masking Issues: The CSS layout relied on clipping paths that broke on mobile iOS Safari, requiring a custom CSS fallback. Heavy Defaults: The initial package had unnecessary JavaScript libraries that needed cleaning to achieve maximum performance.
Final Thoughts
Overall, using a pre-made frontend layout was a major win for this project. It allowed me to deliver a complete, highly polished catalog site in just 7 days without blowing the client's budget.
If you plan to use this layout, just make sure to keep your mobile fallback styles in mind and prune the extra files you do not need. Your site will load much faster, and your users will thank you for the smooth experience.
评论 0