The Tattoo Flash Design System I Built for My Dev Brand
I got tired of every developer site looking like a Stripe clone. So I built a design system inspired by tattoo flash sheets, notebook doodles, and the chaos of a well-loved sketchbook. Here's how doodles.css works, why it exists, and how you can steal it.
1. Why Every Dev Site Looks the Same
Go look at ten indie dev portfolios right now. I'll wait. You'll find: a dark background (probably #0a0a0a), an Inter or Geist font stack, perfectly rounded cards with subtle borders, a gradient purple-to-blue hero, and maybe a grid of bento boxes if they're feeling adventurous.
It's all beautiful. And it all looks like it was generated from the same Figma template. Which, often, it was.
I'm not here to trash the SaaS aesthetic. It works. It converts. It communicates "I am professional and I ship software." But when I started building dashbuilds.dev, I wanted something that communicated something different: "I am a person who made this by hand, and I had fun doing it."
That's how I landed on tattoo flash.
2. The Aesthetic — Tattoo Flash Meets Dark IDE
Tattoo flash sheets are those pre-drawn designs you see on the walls of a tattoo parlor. Bold outlines, limited color palettes, small imperfections that make them feel alive. They're art, but they're also functional — each design exists to be picked up and used.
That felt right for a dev brand. My site is a collection of tools, templates, and ideas. Each one should feel like a little design on the wall: grab it, use it, make it yours.
The other half of the equation is the dark IDE. I spend most of my life staring at a code editor with a dark theme. That deep near-black background, monospace fonts, syntax highlighting in purple and teal. Combining those two worlds — the sketchbook and the terminal — gave me something that felt genuinely mine.
If your design system doesn't make you smile when you open your own site, you built the wrong one.
3. The Design Tokens
Color Palette
Everything starts with #08070e — a purple-black that's warmer than pure black and easier on the eyes at 2 AM. The accent is #a78bfa, a muted lavender that reads as "purple" without screaming. Supporting cast:
Typography
Four fonts, each with a job:
The interplay between DM Serif Display (elegant, editorial) and Caveat (messy, human) is what gives the system its personality. One says "I know what I'm doing." The other says "I drew this during a meeting."
4. The Sketchy Card System
This is where the personality really shows. Here's a standard SaaS card next to a sketchy card, rendered live:
API Dashboard
Monitor your API usage, track rate limits, and manage keys in real time.
API Dashboard
Monitor your API usage, track rate limits, and manage keys in real time.
The differences are small but they compound: dashed borders instead of solid, a slight rotation (rotate(-.4deg)), the serif heading font, and a subtle background shift. The card looks hand-drawn without being cartoonish.
In the full system, nth-child rules give each card a slightly different tilt:
.card:nth-child(2n) { transform: rotate(.3deg); }
.card:nth-child(3n) { transform: rotate(-.4deg); }
.card:nth-child(5n) { transform: rotate(.6deg); }
.card:nth-child(7n) { transform: rotate(-.2deg); }
No two cards sit at the same angle. It's subtle enough that you don't consciously notice it, but it makes the whole page feel less rigid.
Washi Tape + Margin Notes
Some cards get the full treatment: a washi tape strip across the top and a handwritten margin note:
Brain Kit
The toolkit I use to organize my second brain — Notion templates, automation scripts, and the thinking frameworks behind every build.
The washi tape is just a semi-transparent rectangle with rgba(167,139,250,.18) background, rotated 2 degrees. The margin note uses Caveat and sits in position: absolute off the right edge. Resize your browser — on mobile, the note disappears gracefully.
5. The Doodle Library
Six hand-drawn SVG doodles float around the edges of every page. They're the heart of the brand — small enough to be ambient, distinctive enough to be memorable. Here they are at full size:
Each doodle is pure SVG — no images, no external files, about 200 bytes each. They use fill="rgba(...,.05)" for that faint wash of color behind the strokes, which mimics the way marker ink bleeds slightly on paper. The strokes themselves use stroke-linecap="round" because tattoo flash lines taper at the ends.
Every doodle gets its own animation. The skull floats. The heart wobbles. The eye pulses. They're positioned with position: fixed and pointer-events: none so they drift in the margins without interfering with content.
6. Generating Icons with AI
The doodles are hand-coded SVGs, but the product icons across the site (20 total) were generated with Gemini's image model and post-processed with Python. Here's the pipeline.
The Prompt
Finding the right prompt took about 40 iterations. Too vague and you get clip art. Too specific and the AI freezes up. This is what I landed on:
"Hand-drawn tattoo flash style icon. Bold PURPLE and MAGENTA marker outlines with visible diagonal hatching fill strokes in purple/violet. Subtle neon purple glow around edges. A few tiny sparkle dots and rough energy lines. Sophisticated but raw, not childish not corporate. ALL lines and fill in purple/magenta/violet tones (NOT black). White background, square icon, no text."
"NOT black" — without this, every icon comes out with black outlines that clash on dark bg
"diagonal hatching" — gives the fill a hand-drawn quality instead of flat color
"not childish not corporate" — narrows the style window to exactly where I want it
"no text" — AI loves adding random text to icons
The Post-Processing
Raw Gemini output comes on a white background with inconsistent sizing. I wrote a Pillow script that handles the cleanup:
# Smart white background removal
# Lightness > 220 AND color spread < 30 = transparent
# This catches off-whites and near-whites without
# eating into the purple artwork
from PIL import Image
import numpy as np
img = Image.open(path).convert("RGBA")
data = np.array(img)
r, g, b, a = data[:,:,0], data[:,:,1], data[:,:,2], data[:,:,3]
lightness = np.maximum(np.maximum(r, g), b)
spread = (np.maximum(np.maximum(r,g),b).astype(int)
- np.minimum(np.minimum(r,g),b).astype(int))
mask = (lightness > 220) & (spread < 30)
data[mask] = [0, 0, 0, 0]
The lightness > 220 AND spread < 30 threshold is the key insight. Pure white is easy to remove, but Gemini outputs have gray speckles, slightly blue whites, shadow gradients. Checking both lightness (is it bright?) and spread (is it colorless?) catches all the near-whites without accidentally nuking the light purple tones in the actual artwork.
Final output: 128-200px transparent PNGs for the site, plus 512x512 white-background JPEGs (auto-cropped and squared) for Stripe product images. 20 icons total — 9 product icons, 4 feature icons, 6 build category icons, and the site logo.
7. The Little Details
The big pieces get the attention, but the small things are what make the system feel cohesive.
body::before.
filter: blur(80px) and low opacity. The page breathes.
.cursor-sketch class — just a 12px radial-gradient cursor PNG. Tiny touch, but it sells the hand-drawn feel.
.ruled class adds faint horizontal rules via repeating-linear-gradient. Looks like lined notebook paper. Used on blog posts and long-form content.
Highlighter Markers
Four colors, each with a gradient that mimics a real highlighter — heavier on the left edge, fading at the ends:
Yellow for key facts and callouts
Magenta for things that matter emotionally
Teal for technical details and specs
Purple for brand-voice moments
The trick is the linear-gradient(104deg, ...) with opacity ramps at both ends. A flat background color looks like a selection highlight. The gradient looks like someone dragged a marker across the text.
Color Splashes in Action
^ those are just blurred divs. that's it. that's the whole trick.
Squiggly Underlines
Links and emphasis text use a hand-drawn squiggly underline instead of a straight text-decoration. It's an inline SVG path encoded in the background-image — a sine-wave-ish line that repeats horizontally. Cost: zero HTTP requests, about 180 bytes.
8. The Doodle Pack — Free Download
Everything described in this post is free to use. Below are all six SVG doodles at copy-paste size, plus the animation CSS. Grab what you need.
All 6 SVGs — Copy and Paste
Each SVG below is self-contained. Copy the code, drop it into your HTML, done. They're designed to work on dark backgrounds (#08070e to #1a1a2e range).
Animation CSS
Drop this into your stylesheet to animate the doodles:
@keyframes dFloat {
0%, 100% { transform: translateY(0) rotate(0deg); }
50% { transform: translateY(-10px) rotate(3deg); }
}
@keyframes dPulse {
0%, 100% { opacity: .2; transform: scale(1); }
50% { opacity: .4; transform: scale(1.12); }
}
@keyframes dWobble {
0%, 100% { transform: rotate(-3deg); }
50% { transform: rotate(3deg); }
}
@keyframes dSpin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
The full doodles.css file also includes the sketchy card system, highlighter markers, washi tape, margin notes, noise grain overlay, color splashes, notebook ruled lines, and the custom cursor. It's one file, no dependencies, no build step.
9. Should You Do This?
Honest answer: it depends.
This style works when:
- You're building a personal brand, not a corporate product
- Your audience values personality and craft (devs, designers, indie hackers)
- You want to be memorable more than you want to be "safe"
- You're comfortable maintaining a design system that has opinions
- You actually enjoy the aesthetic — if you're forcing it, people will feel that
This style doesn't work when:
- You're building a SaaS product that needs to feel "enterprise-ready"
- Your users expect conventional UI patterns (dashboards, forms, data tables)
- You need to hand the design system to a team of 10 who all need to contribute
- Accessibility is paramount and your users need high contrast ratios (the low-opacity doodles and noise grain can be problematic)
- You don't want to explain your design choices in every portfolio review
The real question isn't "is this good design?" It's "does this feel like me?" I spent years copying whatever design trend was popular. Neumorphism, glassmorphism, the Vercel look. They were all fine. None of them felt like opening my own site and thinking "yeah, this is mine."
The tattoo flash system does. Every time I see that little skull floating in the corner, I grin. That's worth more than any conversion rate optimization.
Build something that makes you want to visit your own site. The people who get it will find you.
The doodles.css file is free to download and use in any project. If you want the thinking frameworks and note-taking system behind how I organize builds like this, check out Brain Kit — it's the same system I used to plan, document, and ship dashbuilds.dev.
Thanks for reading. Now go draw on your website.