AI Shorter Link — AI‑Powered URL Shortener
11/4/2025

Overview
AI Shorter Link helps users create short, branded links with AI‑assisted slugs and built‑in analytics. It includes plan‑based features, per‑user quotas, and strong redirect logic with optional UTM query forwarding.

Goals & Outcomes
- Fast link creation with AI slug helpers for premium tiers
- Clean analytics with geo/UA breakdowns and duplicate filtering
- Strong guardrails: blacklist, per‑minute limits, and expiration
Architecture
- Apps:
client/(user app),admin/,server/(API) - Data: MongoDB (Mongoose models: Link, Visit, User, Blacklist)
- Payments: Stripe for credits/subscription
[client] → React + Vite + Tailwind (Dashboard, Links, Link Detail, Settings)
[admin] → React admin shell
[server] → Express API (auth, links, analytics, billing, redirect)
├─ routes/{links,redirect,analytics,auth,billing}
├─ services/ai (OpenAI-powered slug + summaries)
└─ models/{Link,Visit,User,Blacklist}
Key Features
- AI slug suggestions: single or multiple, uniqueness‑checked
- Redirect engine: 301 with optional query forwarding, duplicate‑click detection
- Analytics: visits by referrer, country/region/city, browser, OS, device
- Plan logic: free vs premium fields (tags, expiration, duplicate destination)

Advanced Implementation
Link creation with plan limits, blacklist, and rate control
// server/src/routes/links.js (excerpt)
// Free plan: cap total links, enforce clean slugs; per-minute create limit
const oneMinuteAgo = new Date(Date.now() - 60 * 1000);
const recentCreates = await Link.countDocuments({ userId: req.user._id, createdAt: { $gte: oneMinuteAgo } });
if (recentCreates > 60) return res.status(429).json({ error: 'Too many links created. Please slow down.' });
// Blacklist domain/IP
const original = new URL(originalUrl); const hostname = original.hostname.toLowerCase();
if (await Blacklist.findOne({ type: 'domain', value: hostname })) return res.status(400).json({ error: 'Target domain is not allowed.' });
Redirect with duplicate‑click detection and optional query forwarding
// server/src/routes/redirect.js (excerpt)
// duplicate = same linkId + same ip + same userAgent within 10 minutes
const tenMinutesAgo = new Date(Date.now() - 10 * 60 * 1000);
const recent = await Visit.findOne({ linkId: link._id, ip, userAgent: ua, createdAt: { $gte: tenMinutesAgo } });
const isDuplicate = !!recent;
// Forward UTM params
if (link.forwardQuery) for (const [k,v] of Object.entries(req.query||{})) url.searchParams.set(k, String(v));
res.redirect(301, url.toString());
AI‑assisted slug generation and analytics summary
// server/src/services/ai.js (excerpt)
export async function generateSlugSuggestion(inputText) {
const prompt = 'You are a helpful assistant generating short, memorable URL slugs...';
const res = await fetch('https://api.openai.com/v1/chat/completions', {...});
let text = data.choices[0].message.content.trim().toLowerCase().replace(/[^a-z0-9-]/g,'-');
return text.slice(0, 32);
}
Analytics aggregation and AI dashboard summary
// server/src/routes/analytics.js (excerpt)
const linkIds = await Link.find({ userId }).distinct('_id');
const visitsLast7Days = await Visit.aggregate([
{ $match: { linkId: { $in: linkIds } } },
{ $group: { _id: { $dateToString: { date: '$createdAt', format: '%Y-%m-%d' } }, count: { $sum: 1 } } },
{ $sort: { _id: 1 } },
]);
// Threshold-based regeneration for AI summary on premium plan

SEO & Branding
- App: shipped
robots.txtandsitemap.xml; descriptive titles/meta via hooks (useSEO) - Branding: energetic accent with modern sans, neon‑tech hero, animated starfield
- UX elements: badges, cards, and gradients tuned for clarity over flash
Client SEO hook:
// client/src/hooks/useSEO.js (excerpt)
setMeta('description', description);
setLink('canonical', canonical || url);
setProperty('og:title', fullTitle);
setProperty('og:description', description);
setMeta('twitter:card', image ? 'summary_large_image' : 'summary');
setJSONLD(jsonld);
Branding & Theming
- Typeface: Poppins (set as
--font-sansvia Tailwind theme) for clean, modern UI legibility - Brand palette: CSS custom properties
--color-brand-50 … 900define a blue scale used across backgrounds, accents, and states - Background: dark gradient base with two radial glow orbs (brand tones) for depth
- Motion accent:
Starfieldcomponent (parallax micro‑stars with framer‑motion) adds subtle tech feel without distraction - Components: primary buttons use brand‑600 with hover to brand‑500; secondary/ghost variants keep contrast on dark UI
/* client/src/index.css (excerpt) */
:root{
--color-brand-500:#4f6fff; /* primary */
--color-brand-600:#2b4eff; /* hover/active */
}
// client/src/components/ui/Button.jsx (excerpt)
const variants = {
primary: 'bg-brand-600 hover:bg-brand-500 text-white',
secondary: 'bg-white/10 hover:bg-white/20 text-white',
ghost: 'bg-transparent hover:bg-white/10 text-white'
}
Performance & Security
- Express Rate Limit on sensitive endpoints; Helmet/CORS, JWT auth
- Lightweight redirects; duplicate filtering to avoid analytics inflation
- MongoDB indexes on slug, userId, createdAt; aggregation for visit counts
Security & guardrails:
- JWT auth, Helmet, CORS
- Express‑validator on inputs (slug rules, URL scheme)
- Blacklist checks (domain/IP) and per‑minute creation limit
What made it work
- Clear separation of plans; sensible limits for free tier
- AI assistance where it matters (slugs, analytics summary)
- Guardrails that keep data clean and the product resilient
Deliverables
- User app + admin + API
- AI slug suggestions and analytics summary
- Abuse controls (blacklist, per‑user limits)
- Geo/UA analytics and duplicate‑click detection
- Stripe credits/billing