Update index.html

This commit is contained in:
2025-09-26 18:28:09 -07:00
parent 93084ca804
commit 9e85b79d88

View File

@@ -1,159 +1 @@
<!doctype html><html lang=en class="h-full">
<head>
<meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1">
<title>4ev.link — Short links that last</title>
<meta name=description content="Get your 4ev.link. Free random short links. Paid: custom URLs, analytics, CDN proxy, your own subdomain (coming soon).">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%23ff2d55' d='M16 29S2 22 2 11a7 7 0 0 1 13-3 7 7 0 0 1 13 3c0 11-14 18-14 18'/%3E%3C/svg%3E">
<script src="https://cdn.tailwindcss.com"></script>
<script>tailwind.config={theme:{extend:{colors:{bg:'#0b0b0d'}}}}</script>
<script src="https://unpkg.com/lucide@latest" defer></script>
<script src="//unpkg.com/alpinejs" defer></script>
</head>
<body class="min-h-screen bg-bg text-gray-100 antialiased selection:bg-white/10 selection:text-white"
x-data="{
u:'', r:'', e:'', busy:!1,
async shorten(){
this.e=''; this.r='';
let v=this.u?.trim();
if(!v) return this.e='Please paste a URL';
try{ new URL(v) }catch(_){ return this.e='Invalid URL' }
this.busy=!0;
try{
let res=await fetch('/',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({url:v})});
if(!res.ok){ this.e=(await res.text())||'Failed to shorten'; }
else { let d=await res.json(); this.r=d.shortUrl }
}catch(_){ this.e='Network error' }
this.busy=!1; this.$nextTick(()=>window.lucide&&lucide.createIcons())
},
copy(){ navigator.clipboard.writeText(this.r) }
}" x-init="$nextTick(()=>window.lucide&&lucide.createIcons())">
<header class="sticky top-0 z-10 border-b border-white/5 bg-bg/80 backdrop-blur">
<div class="mx-auto max-w-6xl px-4 py-3 flex items-center justify-between">
<a href="/" class="flex items-center gap-2 font-semibold text-white">
<i data-lucide="infinity" class="w-5 h-5 text-white/80"></i>
4ev.link
<span class="ml-2 rounded-full bg-white/5 px-2 py-0.5 text-xs text-white/60">beta</span>
</a>
<nav class="flex items-center gap-2">
<a href="/login" class="px-3 py-1.5 rounded-md text-sm text-white/80 hover:text-white hover:bg-white/5 transition">
<i data-lucide="log-in" class="w-4 h-4 inline -mt-0.5 mr-1"></i> Log in
</a>
<a href="/signup" class="px-3 py-1.5 rounded-md text-sm bg-white text-black hover:bg-gray-200 transition">
<i data-lucide="user-plus" class="w-4 h-4 inline -mt-0.5 mr-1"></i> Sign up
</a>
</nav>
</div>
</header>
<main class="mx-auto max-w-6xl px-4">
<section class="pt-16 sm:pt-24">
<div class="text-center">
<h1 class="text-3xl sm:text-4xl md:text-5xl font-extrabold tracking-tight text-white">
Get ur 4ev.link <span class="align-middle">❤️</span>
</h1>
<p class="mt-3 text-sm sm:text-base text-white/60">
Minimal, fast, and forever-ish. Free gives you a random short link. Paid adds power.
</p>
</div>
<form @submit.prevent="shorten" class="mx-auto mt-8 w-full max-w-2xl">
<div class="rounded-xl bg-white/5 ring-1 ring-white/10 p-2 sm:p-3">
<div class="flex flex-col sm:flex-row gap-2 sm:gap-3">
<div class="relative flex-1">
<i data-lucide="link" class="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-white/40"></i>
<input x-model="u" type="url" inputmode="url" required
placeholder="https://example.com/very/long/url"
class="w-full bg-transparent pl-9 pr-3 py-3 rounded-lg text-white placeholder-white/30 outline-none border border-transparent focus:border-white/20">
</div>
<button type="submit" :disabled="busy"
class="inline-flex items-center justify-center gap-2 rounded-lg bg-white text-black px-4 py-3 font-medium hover:bg-gray-200 disabled:opacity-60 disabled:hover:bg-white transition">
<template x-if="!busy"><i data-lucide="wand-2" class="w-4 h-4"></i></template>
<template x-if="busy"><i data-lucide="loader-2" class="w-4 h-4 animate-spin"></i></template>
Shorten
</button>
</div>
<div class="mt-2 grid grid-cols-1 sm:grid-cols-3 gap-2 text-xs text-white/50">
<div class="flex items-center gap-2">
<i data-lucide="hash" class="w-3.5 h-3.5"></i>
Free: random slug
</div>
<div class="flex items-center gap-2">
<i data-lucide="pencil" class="w-3.5 h-3.5"></i>
Custom URLs <span class="ml-1 rounded bg-white/10 px-1.5 py-0.5 text-[10px] text-white/70">paid</span>
</div>
<div class="flex items-center gap-2">
<i data-lucide="sparkles" class="w-3.5 h-3.5"></i>
Analytics • Proxy (CDN) • Subdomain <span class="ml-1 rounded bg-white/10 px-1.5 py-0.5 text-[10px] text-white/70">coming soon</span>
</div>
</div>
</div>
<p x-show="e" x-text="e" class="mt-3 text-sm text-rose-400" x-cloak></p>
<div x-show="r" x-cloak class="mt-4 rounded-xl border border-white/10 bg-white/5 p-3">
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
<div class="truncate">
<span class="text-xs text-white/50">Your short link</span>
<div class="mt-0.5 font-mono text-sm sm:text-base text-white truncate">
<a :href="r" x-text="r" class="hover:underline" target="_blank" rel="noopener"></a>
</div>
</div>
<div class="flex items-center gap-2">
<button type="button" @click="copy" class="inline-flex items-center gap-2 rounded-lg bg-white/10 hover:bg-white/15 px-3 py-2 text-sm">
<i data-lucide="copy" class="w-4 h-4"></i> Copy
</button>
<a :href="r" target="_blank" rel="noopener"
class="inline-flex items-center gap-2 rounded-lg bg-white text-black px-3 py-2 text-sm hover:bg-gray-200">
Open <i data-lucide="external-link" class="w-4 h-4"></i>
</a>
</div>
</div>
</div>
</form>
</section>
<section class="mx-auto mt-16 sm:mt-24 max-w-3xl">
<div class="grid sm:grid-cols-3 gap-4">
<div class="rounded-lg border border-white/10 p-4 bg-white/5">
<div class="flex items-center gap-2 text-white">
<i data-lucide="zap" class="w-4 h-4 text-white/70"></i><span class="text-sm font-semibold">Fast</span>
</div>
<p class="mt-1 text-sm text-white/60">Edge-hosted redirects with no fuss.</p>
</div>
<div class="rounded-lg border border-white/10 p-4 bg-white/5">
<div class="flex items-center gap-2 text-white">
<i data-lucide="shield" class="w-4 h-4 text-white/70"></i><span class="text-sm font-semibold">Safe</span>
</div>
<p class="mt-1 text-sm text-white/60">Validate URLs client + server side.</p>
</div>
<div class="rounded-lg border border-white/10 p-4 bg-white/5">
<div class="flex items-center gap-2 text-white">
<i data-lucide="settings" class="w-4 h-4 text-white/70"></i><span class="text-sm font-semibold">Scalable</span>
</div>
<p class="mt-1 text-sm text-white/60">Built on Cloudflare KV and Workers.</p>
</div>
</div>
<div class="mt-6 text-center text-xs text-white/40">
Paid: custom slugs, analytics, proxy (CDN), your own subdomain — coming soon.
</div>
</section>
</main>
<footer class="mt-20 border-t border-white/5">
<div class="mx-auto max-w-6xl px-4 py-8 text-xs text-white/50 flex items-center justify-between">
<span>© <span x-text="new Date().getFullYear()"></span> 4ev.link</span>
<div class="flex items-center gap-3">
<a href="/terms" class="hover:text-white/80">Terms</a>
<a href="/privacy" class="hover:text-white/80">Privacy</a>
<a href="https://github.com/4ev-link/4ev.link" class="hover:text-white/80 flex items-center gap-1">
<i data-lucide="github" class="w-4 h-4"></i> GitHub
</a>
</div>
</div>
</footer>
<script>addEventListener('DOMContentLoaded',()=>window.lucide&&lucide.createIcons())</script>
</body>
</html>