rukon-link
rukon-link: QR link hub with gated contact details and first-party analytics
One QR code for every profile, without putting private contact details in the page.
A personal link hub built for a QR code: public social links, and email, phone and WhatsApp released only after a visitor asks through a validated, rate-limited form. It carries its own privacy-first analytics (no third-party trackers, no cookies, no stored IP addresses) and a private admin dashboard with a contact-request inbox and data-retention settings. Next.js 16, TypeScript and Supabase PostgreSQL, deployed on Vercel at link.rukon.dev.
Product, Full-Stack Build, Database, Security & Analytics
Key Highlights & Practical Impact
Executive Scan- Contact details live only in server-side environment variables and are released per request, never shipped in the page
- Contact form with same-site checks, a honeypot, a minimum fill time, validation and a database-backed rate limit
- First-party analytics with no cookies or third-party trackers; addresses are stored only as a daily-rotating salted hash
- Admin dashboard: traffic, sources, devices and locations, per-link clicks, and a contact-request inbox
- Retention settings with a scheduled purge that rolls old events up into daily totals
Ready to explore the build?
A detailed look at the end-to-end architecture, process workflows, key engineering decisions, live production capabilities, challenges, and results.
Writing from this work
Vercel or a Self-Hosted Ubuntu Box? How I Chose Hosting App by App
Eight deployed apps, three hosting shapes: Vercel for pages and serverless APIs, a self-hosted Ubuntu box for a stateful API, and a hybrid for a model Vercel can't run.
Two Ways I Use Supabase Row Level Security: Deny-All Behind a Server, or Per-Owner Policies
Across five projects, RLS does one of two jobs: close the Data API while a trusted server does the work, or let Postgres enforce who owns each row. When to pick which.
Sharing One Supabase Project Between Two Apps Safely
A second app inside an existing Supabase project: prefixed tables, RLS on with no policies, revoked grants, server-only access and an admin check for a shared user list.
One SQL Function for a Whole Analytics Dashboard
Every figure on a small analytics dashboard, totals, a gap-free time series and ranked breakdowns, returned as one JSON document by one PostgreSQL function, in the owner's time zone.
Refreshing a Supabase Session in Next.js 16's proxy.ts, and Not Authorising There
Next.js 16 renamed Middleware to Proxy. Using proxy.ts only to refresh a Supabase session cookie for admin routes, while every page and API route checks authorisation itself.
Keeping Your Email and Phone Off a Public Link Page Until Someone Asks
A QR link page that never ships private contact details in its HTML or JavaScript. Server-only values, a short request form, only the asked-for methods returned, and a 24-hour signed re-reveal.
First-Party Analytics Without Cookies: A Daily-Rotating Salted IP Hash
Page views and link clicks recorded by the site itself, with no third-party tracker and no cookies. A salted IP hash that changes daily, beacons that survive navigation, and what is still stored.
Contact Form Spam Protection Without a CAPTCHA, and Its Honest Limits
A honeypot, a minimum fill time, a same-site check, strict validation and a database-backed rate limit on a Next.js contact form. What each layer stops, and which ones a script can walk past.
Keeping Analytics for 90 Days: Roll Up, Then Delete, With pg_cron
Detailed analytics events kept for a set period, then summarised into daily totals and deleted by a scheduled PostgreSQL function. The retention setting, the job, and the time-zone trade-offs.