DEV Community

Diyor
Diyor

Posted on

I built a zero-dependency portfolio template — here's what I learned

Most portfolio templates come with React, Next.js, or at least a build step. I wanted something different: a template that designers can actually understand and modify without touching a terminal (beyond the initial setup).

So I built one from scratch. 300KB. Zero dependencies. Vanilla everything.

Why vanilla?

I'm a product designer who codes. My own portfolio (diyor.design) runs on plain HTML, CSS, and JavaScript. When I decided to turn it into a template, I had a choice: rewrite it in a framework, or keep it simple.

I kept it simple. Here's why:

  • Designers can read it. No JSX, no components, no state management. Just HTML files you can open in a browser.
  • No build step. Edit a file, refresh the browser. Done.
  • It'll work in 10 years. No deprecated packages, no breaking updates, no npm audit warnings.
  • 300KB total. The entire template. Not the JavaScript bundle — the whole thing.

What's inside

  • Bilingual support — Russian and English with a language switcher. Easy to adapt for any two languages.
  • Dark mode — toggle button + automatic system preference, saved in localStorage.
  • Case study template — numbered sections, stats grid, image lightbox with zoom, previous/next navigation.
  • Terminal easter egg — press ~ for a secret terminal with design quotes.
  • Design system overlay — press Shift+G to see the 12-column grid.
  • One-command setup./setup.sh asks your name, generates a favicon, replaces all placeholders.
  • SEO ready — Open Graph, JSON-LD, sitemap, canonical tags, hreflang.
  • Accessible — ARIA, keyboard nav, focus-visible, reduced motion.

The setup experience

git clone https://github.com/diyoriko/portfolio-template.git my-portfolio
cd my-portfolio
./setup.sh
Enter fullscreen mode Exit fullscreen mode

The script asks for your name, domain, email, socials. Then it:

  • Replaces "Jane Smith" everywhere
  • Generates an SVG favicon with your initial
  • Updates CNAME, sitemap, config.json
  • Done. Push to GitHub Pages.

What I'd do differently

The dark mode architecture. I started with just prefers-color-scheme but quickly realized users want a manual toggle. I ended up with a dual system: @media (prefers-color-scheme: dark) { :root:not(.light) { ... } } for auto mode, plus html.dark { ... } for manual. It works, but the CSS is duplicated. Next time I'd use CSS layers or a single class-based approach from the start.

Hardcoded colors. My first pass had rgba(0, 0, 0, 0.08) scattered everywhere for borders and shadows. In dark mode, they were invisible. I had to go back and replace them all with CSS custom properties. Lesson: use variables from day one, even for "obvious" values.

Try it

MIT licensed. If you build something with it, I'd love to see it.


I'm Diyor, a product and brand designer. I write about design systems, automation, and building things from scratch. diyor.design

Top comments (0)