Create a link. Send it. Watch them say yes.
Ribbon embraces opinionated maximalism,early 2000s internet aesthetics meets modern glassmorphism. Bold gradients, chunky borders, playful animations, and that signature aero glass blur that makes everything feel tactile and alive.
It's a digital page wrapped in nostalgic Y2K vibes.
In a sense those new generated websites aren't being created we have the same website but different data
Identity (nanoid): we call nanoid(8), which generates a random, URL-safe string like k3J9f2Lm. Database Entry: send that string (the slug) to Supabase along with the names and theme choice. The database now has a row that says: "Whenever someone visits the link with slug 'k3J9f2Lm', show them names X and Y." Dynamic Route: vercel app is set up with a dynamic folder (likely app/be-mine/[slug]/page.tsx). When a user visits that URL, the page looks at the URL, grabs the slug, asks Supabase for the data matching that slug, and renders it on the fly.
In short: No, not for a long time. Collisions (The Math): Using nanoid(8) gives you a massive pool of possible combinations (281 trillion). To have a 1% chance of a collision, you would need to generate roughly 2 million links. Even then, your Supabase unique constraint would just throw an error, preventing a duplicate.
Database Speed: PostgreSQL (Supabase) handles thousands of rows like a champion. Once you hit millions of rows, you just need to ensure your slug column is "Indexed" (which it likely is if it's your Primary Key) to keep lookups instant.
Storage Space (The Real Bottleneck): This is where you might hit a limit first. You are resizing images to 400x400 JPEGs. Supabase’s free tier typically caps storage at 1GB.
Instead of sending massive 5MB photos to the server, I resize them to 400×400px before uploading using Canvas API. This saves bandwidth, speeds up uploads, and keeps the UI snappy. Plus, I auto-crop to a perfect square so every image looks polished — no weird stretching or broken layouts.
const resizeImage = (file: File): Promise<Blob> => {
// Canvas magic: crop to square, resize to 400x400, convert to JPEG
// Bandwidth saved: ~80% on average
}Getting that Windows Vista-inspired aero glass effect to look identical across Chrome, Safari, and Firefox was a challenge. I used layered backdrop-filter with custom opacity and brightness adjustments to compensate for browser rendering differences. The result? Dreamy, frosted glass that actually works everywhere.
.aero-glass {
background: rgba(255, 255, 255, 0.55);
backdrop-filter: blur(24px) saturate(180%) brightness(1.1);
/* Chrome needs brightness boost, Safari doesn't — this balances both */
}- Glassmorphism is hard. Making it work across browsers took way more tweaking than expected.
- Image optimization matters. Client-side resizing cut upload times by 80%.
- Body background tricks. Sometimes you need to break out of component boundaries to get pixel-perfect design.
- Fun design > perfect design. The playful animations and nostalgic vibes make this project feel special, not just look pretty.
- Frontend: Next.js 14
- Animations: CSS-only magic
- Database: Supabase
- Styling: Tailwind CSS
links {
id: UUID
slug: ShortID (e.g., site.com/be-mine/abc123)
recipient_name: String
creator_name: String
theme_id: Integer
image_url: String (Supabase Storage)
is_anonymous: Boolean
response: String
responded_at: Timestamp
}Because asking someone out is scary. But it's also exciting, hopeful, and kinda magical.
Built with way too much CSS


