You are browsing as a guest. Sign up (or log in) to start making projects!

Site-Slap

  • 5 Devlogs
  • 6 Total hours

does your site slap? paste a url and find out. site slap takes a screenshot of your live site, throws it at an ai that actually has opinions, and comes back with a score out of 100, a one line verdict, and three things you should probably fix. it's not tracking your seo or checking your load time. it's looking at your design the way a person would, and being honest about it. built this because i kept seeing sites that worked fine but just felt dead. nobody was saying anything. site slap says something. enjoy :)

Ship #1

Shipped: Site Slap

Paste a URL. Get a score out of 100. Get roasted.

Site Slap is an AI design critic. It screenshots any live website, shows it to a vision model, and judges the visual design the way a person with taste
would. No SEO metrics, no performance audit. You get a score, a one-sentence verdict, three specific roasts, and three fixes that would actually move the
number.

Then the part I'm proudest of: hit View Upgraded and a draggable, mac-style popup opens with your site rebuilt, fixes applied, rendered live inside a
sandboxed iframe. Both versions start generating in the background while you're still reading your roast, so the popup usually opens already loaded. Minor
upgrade or full redesign, your choice.

The whole app ships in three skins: basic, decent, and fire. Same tool, three levels of design effort. Fire is the one worth seeing, with an aurora hero
built in pure CSS, snap scrolling, and a score that counts up. The skin switcher is a live demonstration of what the scoring scale actually means.

The technicals, briefly: Next.js and TypeScript on Vercel. Microlink handles screenshots, so there is no headless browser to babysit. Groq's Llama 4 Scout
does the judging for free, and Claude Haiku writes the upgraded site as a single self-contained HTML file, about three cents per render with a daily cap.
The generated pages contain no JavaScript, and the iframe's empty sandbox attribute makes sure none could run regardless.

The scoring is deliberately harsh. Minimal is not the same as designed, and blank is not the same as clean.

Go slap your own site before someone else does: https://site-slap-topaz.vercel.app

  • 5 devlogs
  • 6h
  • 17.93x multiplier
  • 116 Stardust
Try project → See source code →
Open comments for this post

42m 21s logged

Site Slap Devlog #5 (it ships today)

TL;DR

  • the popup got its brain: it renders your actual upgraded site now, written by Claude Haiku, shown in a sandboxed iframe
  • went through three ai models to kill the slop. the free ones couldn’t write html
  • final polish landed: tab name, hand favicon, pulsing dots pulling people to the better skins
  • found out the site was invisible to everyone except me. fixed an hour before shipping
  • site slap is live. link at the bottom. go get roasted.

the upgrade renderer

the moment your slap result lands, two requests fire in the background, one per tier. by the time you scroll down and hit view
upgraded, the redesign is already sitting there.

Claude Haiku gets the screenshot plus the fixes and writes your site back as one self-contained html file. no javascript allowed,
and the iframe’s empty sandbox attribute makes sure it wouldn’t matter anyway. prompts are requests. sandboxes are enforcement.

the roasts still run free on groq. scoring doesn’t need the muscle, writing html does. about three cents per render, daily capped
so a viral day costs me a dollar and not my whole balance.


three models and a thumbnail trick

groq’s scout wrote the first upgrades. overlapping headlines, floating color blocks. i gave it a page of design rules. still slop.
maverick was better and slower. haiku ended the argument.

the other half of “broken” renders was my fault: the model writes desktop css and i was rendering it in a 670px frame. now the
iframe is actually 1280px wide and a css transform scales it to 52%, like a thumbnail. layout at real size, display at small size.

best bug of the week: one render had perfect nav links next to three giant ugly buttons. turns out buttons don’t inherit fonts.
browsers give buttons their own default font unless you write button { font: inherit }. that reset is now a mandatory line the
model must paste, not a rule it might remember.


the launch blocker nobody saw

an hour before shipping, i checked the live url from outside my account.

login page.

vercel’s deployment protection was walling everything, production included. i’d been looking at my site logged in for days, seeing
it fine, while every public url served a vercel login screen. the site worked perfectly and nobody on earth could see it.

one setting flipped, one clean domain added, and then a real test from the outside: curl the live api, no cookies, no login.
example.com came back with a 40 and “barely functional, utterly forgettable.” the renderer returned real html with the viewport
meta exactly where the prompt demands it. green across the board.

you and the public do not see the same internet. test logged out.


thank you

this project went from “paste a url, get roasted” scribbled in a chat to a three-skin app with an ai design critic and a popup that
redesigns your site in front of you. five devlogs, three dead heroes, two ai providers, one rem/em bug i will never make again.

thanks to Hack Club and Stardance for the reason to ship instead of endlessly polish. thanks to everyone who read these devlogs and
watched the thing grow. and thanks to arngren.net for being the calibration anchor no prompt could do without.

it ships.


Tip of the Day

open your deployed site in an incognito window before you share it anywhere. logged-in you and the public are two different
visitors, and only one of them matters on launch day.


🖐️ go slap your site

https://site-slap-topaz.vercel.app

0
0
1
Open comments for this post

1h 22m 53s logged

Site Slap Devlog #4 (pasted it twice, rendered it never)

TL;DR

  • fire skin got its upgrade wave: cinematic slow timing, snap scrolling between full-height panels, three tabs replaced by one
    pulsing button, and a draggable popup window
  • the popup drags at 60fps because React never hears about it. position lives in a ref and writes straight to the dom
  • my paste of the popup duplicated 12 lines of jsx, and the line that actually renders it never existed. the button flipped state
    into the void
  • next: the popup stops showing a fix list and starts showing your actual upgraded site

the upgrade wave

four changes in one session.

the window expands first, then the text rises in. everything slowed to about half its old speed, long delays between each element,
so switching to fire feels like a scene opening instead of ui popping in.

the page now snap-scrolls between full-height panels: hero, score, screenshot, roast, fixes. one flick per section.

the og / quick fix / full fix tabs are gone from fire. in their place, one button at the end of the fixes that pulses a sonar ring
and says view upgraded.


the floating window

clicking it opens what looks like another mac window. traffic lights, a title bar, and the red dot actually closes it. you can grab
the title bar and drag it anywhere on screen.

inside: your current score for contrast, the upgraded score in the big serif, and a minor / full toggle that swaps both the number
and the fix list.

it works.


what i learned

dragging with react state is a trap. pointermove fires around 60 times a second, and putting the position in state would re-render
the whole component on every single event.

instead the position lives in a ref. pointerdown records where you grabbed and where the window already was. pointermove computes
the offset and writes style.transform directly onto the dom node. React never re-renders during the drag, so it stays smooth.

the other half is setPointerCapture. without it, dragging fast outruns the title bar, the cursor leaves the element, and the
window gets dropped mid-drag. capture pins every pointer event to the bar until you let go.

also learned the dumb way that pasting a component in is not the same as shipping it. my paste duplicated a 12 line block of jsx,
and i never added the line that renders the window when the state flips. state going true means nothing if nothing reads it.


what’s next

  • the popup body swaps the fix list for the upgraded site itself. Groq’s vision model looks at the screenshot plus the fixes and
    writes a new version of the page as one self-contained html file, rendered inside a sandboxed iframe
  • both upgrade tiers start generating in the background the moment the slap result lands, so the popup opens already loaded
  • push it, then check the Vercel deploy

Tip of the Day

if a button does nothing, check whether the thing it opens is ever rendered. flipping state to true is only half the job. something
has to read that state and put pixels on screen.

0
0
3
Open comments for this post

1h 52m 44s logged

Site Slap Devlog #3 (the hero that died twice before it shipped)

TL;DR

  • fire skin is done. the third and final tier, dark cinematic, animated aurora hero in pure css
  • the original plan was an ai-generated image hero, then an ai video. both died. the final version uses zero assets
  • three motion moments: staggered word reveal on load, score count-up, roast lines fading in on scroll
  • one bug in the results css: rem where em should be. the “/100” rendered at 4 pixels tall

the plan kept dying

fire was supposed to have a generated image hero. i made the image, it came out painterly instead of real, i liked it anyway. then i tried animating it into a looping video. the videos came out static, then the download button stopped working, and my credits were almost gone.

so i dropped the whole thing.

the replacement is an aurora effect built entirely in css. no image, no video, no library, nothing to download. rose, amber and teal glows drifting over near-black. it loads instantly and it can’t break.


how the aurora works

two repeating linear gradients stacked on one div. the first paints thin diagonal stripes of rose, amber and teal. the second paints stripes of the background color on top, so it cuts gaps into the first one.

then filter: blur(42px) melts the stripes into soft bands of light.

the movement is one keyframe. the background is sized at 300% width, and background-position slides from 50% to 350% over 26 seconds on a loop. the stripes drift sideways like slow northern lights. that’s the entire trick, one animated property, gpu-composited, no jank.


the motion

the headline is five words, each wrapped in its own span with a staggered animation-delay. they rise 28px and fade in one after another on load.

when results land, the page auto-scrolls down and the score counts up from 0 with a requestAnimationFrame loop and a cubic ease-out, so it sprints early and settles slow.

the roast and fix lines start invisible. an IntersectionObserver adds a class when each one enters the viewport, staggered 80ms apart.

it works.


what i learned

em and rem are not interchangeable, and the difference is exactly one letter.

the giant score is clamped up to 168px. next to it, “/100” is sized at 0.28em, which means 28% of the parent’s font size, so it scales with the score. i typed 0.28rem instead. rem means 28% of the root font size, 16px. so “/100” rendered at about 4.5 pixels. invisible.

em looks at the parent. rem looks at the page. one letter, 40 pixel difference.

also, prefers-reduced-motion has a trap. if you just set animation: none on elements that start at opacity 0, they stay at opacity 0 forever. the media query has to force opacity: 1 back on, or reduced-motion users get a blank page.


Tip of the Day

if your css animation “isn’t working”, check whether it already finished. a mount animation runs once in the first second. if you looked away, you missed it, and the end state looks identical to no animation at all.


0
0
1
Open comments for this post

1h 15m 37s logged

Site Slap Devlog #2 (it looks like a real app now)

TL;DR

  • wrapped the whole thing in a mac-style browser window with traffic lights and a skin switcher
  • screenshot buffer so microlink waits for the site to actually finish loading
  • skeleton loaders so the ui doesn’t just sit there looking dead

the window

the app had no personality before. it was just a black page with a text input. it worked but it felt like a prototype.

now the whole thing lives inside a browser-window shell. dark title bar, red yellow green traffic lights top-left, three tabs across the top, basic, decent, fire. those tabs are the skin switcher. click one and the content inside the window changes completely.

only basic is wired up right now. decent and fire both say “coming soon.” but the chrome is done, it’s consistent, and it holds everything together.


the screenshot buffer

microlink was taking the screenshot too early. some sites load fast enough, but anything with javascript rendering would come out half-built. spinners, blank sections, layouts that hadn’t collapsed yet.

added waitFor=2500 to the microlink request. it waits 2.5 seconds after the page loads before grabbing the screenshot. costs a bit of latency but the results are actually what the site looks like.


skeleton loaders

while the slap is processing there’s nothing to show. before this it was just a blank area and a button that said “slapping…” you had no idea if it was working.

now there are ghost blocks that pulse while it loads. one tall block for where the screenshot will be, then smaller ones for the score, verdict, roast, and fixes. the layout mirrors the real result so when it drops in it doesn’t feel like a jump cut.

it works.


what i learned

the shimmer animation is simpler than it looks. it’s one div with a gradient that’s twice the width of the element. background-size: 200% 100% stretches the gradient out. then an animation shifts background-position from 200% 0 to -200% 0, which sweeps the lighter middle band across the div left to right.

no javascript. no opacity toggle. just a moving gradient. the whole thing is one css keyframe and four lines of inline style.


what’s next

decent skin and fire skin. the chrome is ready.

decent is a clean modern redesign of the same tool, same data, different presentation. fire is the stardance premium version with motion. that one needs real thought before any code gets written.


Tip of the Day

screenshot your site at 375px width before you ship anything. most people will see it on a phone first. if it breaks there, nothing else matters.

0
0
2
Open comments for this post

1h 16m 3s logged

Site Slap Devlog #1 V0 (the ai gave arngren.net a 42)

TL;DR

  • built the full backend: screenshot, vision model, score + roast + fixes
  • wired it to a live ui and deployed on Vercel
  • tuned the prompt

the idea

paste a url. get a score. get roasted.

that’s the whole thing. no seo metrics, no performance audit. just a vision model looking at your site the way a person would, and being honest about it.


how the backend works

three steps, one route.

first, microlink takes a screenshot of the live site. it’s a simple GET request, no chromium to manage, no headless browser on the server. just a url in, a screenshot url back.

then that screenshot url goes straight to Groq’s vision model, llama 4 scout. it sees what the site actually looks like, not the html. the prompt tells it to score on visual vibe only, and return raw JSON with a score, a verdict, a roast, and three fixes.

then /api/slap hands that JSON back to the client.

it works.


the markdown fence bug

linear.app broke it on the first test. Groq decided to wrap the JSON in a code block even though the prompt said not to. one line fix: strip the fences before parsing. linear scored fine after that.


what i learned

the model is too generous by default.

arngren.net is one of the most visually chaotic sites on the internet. it got a 42. that’s “meh” territory. the prompt said “0-30 is painful” but the model hedged toward the middle anyway.

turns out you have to anchor the scale with specific examples and tell it to actually use the low end. added “arngren.net level” next to the 0-15 range and “be harsh when it’s bad” as a direct instruction. scores tightened up.

the prompt is the model’s personality. treat it like code.


Tip of the Day

go slap your own site before someone else does. you already know what’s wrong with it.

0
0
1

Delete project?

Are you sure you want to permanently delete this project? This action cannot be undone.

All devlogs, followers, and associated data will be removed.

Followers

Loading…