Files
4ev.link/index.html

146 lines
8.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html><html lang=en>
<head>
<meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1">
<title>4ev.link — simple forever-short links</title>
<meta name=description content="4ev.link is a minimal, fast URL shortener. Free, no account needed. Paid custom URLs coming soon.">
<link rel=preconnect href=https://fonts.googleapis.com><link rel=preconnect href=https://fonts.gstatic.com crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=Space+Grotesk:wght@500;700&family=Roboto+Mono:wght@400;700&display=swap" rel=stylesheet>
<script src=//unpkg.com/alpinejs defer></script>
<script src=https://unpkg.com/lucide@latest defer></script>
<style>
:root{--bg:#fff;--fg:#111;--sub:#666;--mut:#888;--br:#e5e7eb;--card:#f8fafc;--ok:#111;--err:#b91c1c;--ring:0 0 0 3px rgba(0,0,0,.08)}
*{box-sizing:border-box}html,body{height:100%}body{margin:0;background:var(--bg);color:var(--fg);font:16px/1.45 Inter,system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,'Helvetica Neue',Arial,'Apple Color Emoji','Segoe UI Emoji';-webkit-font-smoothing:antialiased}
a{color:inherit;text-decoration:none}a:hover{text-decoration:underline}
.container{max-width:980px;margin:0 auto;padding:16px}
.nav{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 0}
.brand{display:inline-flex;align-items:center;gap:8px;font-weight:700}
.badge{font:700 12px/1 Inter;background:#111;color:#fff;border-radius:999px;padding:6px 10px}
.actions{display:flex;gap:8px}
.btn{appearance:none;border:1px solid var(--br);background:#fff;color:#111;border-radius:10px;padding:10px 14px;font-weight:600;cursor:pointer}
.btn:hover{box-shadow:var(--ring)}.btn:disabled{opacity:.6;cursor:not-allowed}
.btn.black{background:#111;color:#fff;border-color:#111}
.btn.ghost{background:transparent}
.hero{display:grid;gap:14px;place-items:center;text-align:center;padding:28px 0}
h1{font:700 clamp(24px,5.5vw,42px)/1.1 'Space Grotesk',Inter,system-ui;margin:0}
h2{font:600 18px/1.2 Inter;margin:0}
.sub{color:var(--sub);font-size:14px}
.card{background:var(--card);border:1px solid var(--br);border-radius:14px;padding:14px}
.grid{display:grid;gap:12px}
@media(min-width:720px){.grid-2{grid-template-columns:1fr 1fr}}
.input{display:flex;gap:8px;align-items:center;background:#fff;border:1px solid var(--br);border-radius:12px;padding:8px 8px}
.input:focus-within{box-shadow:var(--ring)}
input[type=url],input[type=text]{border:0;outline:0;background:transparent;width:100%;padding:10px 8px;font-size:16px}
small.mono{font:14px/1.3 'Roboto Mono',monospace;color:#333;background:#fff;border:1px dashed var(--br);border-radius:8px;padding:8px 10px;display:inline-flex;gap:6px;align-items:center}
.kbd{font:600 12px/1 'Roboto Mono',monospace;border:1px solid var(--br);border-radius:6px;padding:4px 6px;background:#fff;color:#333}
.row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
hr{border:0;border-top:1px solid var(--br);margin:16px 0}
.notice{font-size:13px;color:var(--mut)}
.result{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.copy{display:inline-flex;align-items:center;gap:6px}
.tag{border:1px solid var(--br);border-radius:999px;padding:6px 10px;background:#fff;color:#111;font-weight:600}
.pricing .plan{display:grid;gap:10px}
.plan h3{margin:0;font:700 16px/1 Inter}
.dim{color:var(--mut)}
footer{color:#777;font-size:13px;padding:24px 0}
noscript{display:block;background:#fff3f3;border:1px solid #ffdede;color:#8a1616;padding:10px;border-radius:10px}
</style>
</head>
<body x-data="{url:'',out:'',slug:'',busy:!1,err:'',copied:!1,paid:!1,shorten:async function(){this.err='';this.out='';this.copied=!1;let t=this.url?.trim();if(!t)return this.err='Enter a valid URL';try{new URL(t)}catch(_){return this.err='Enter a valid URL'}this.busy=1;try{let r=await fetch('/',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({url:t})});if(!r.ok)throw new Error(await r.text()||'Failed');let d=await r.json();this.out=d.shortUrl}catch(e){this.err=String(e.message||e)}this.busy=0},copy:async function(v){try{await navigator.clipboard.writeText(v||this.out);this.copied=1;setTimeout(()=>this.copied=0,1600)}catch(_){this.copied=0}}}" x-init="lucide&&lucide.createIcons()">
<noscript>4ev.link works best with JavaScript enabled.</noscript>
<div class=container>
<nav class=nav>
<div class=brand><i data-lucide=infinity></i><a href=/ aria-label="Home">4ev.link</a><span class=badge>Free</span></div>
<div class=actions>
<a class="btn ghost" href=#login>Log in</a>
<a class="btn black" href=#signup>Sign up</a>
</div>
</nav>
<header class=hero>
<h1>Get ur 4ev.link <span aria-hidden=true style=color:#e11d48>❤️</span></h1>
<p class=sub>Free. No account needed. Paste a link, get a short one. Custom aliases for paid users (coming soon).</p>
</header>
<main class=grid>
<section class="card grid" aria-label="Shorten form">
<h2>Shorten a link</h2>
<form class=grid @submit.prevent="shorten">
<div class=input>
<i data-lucide=link-2></i>
<input type=url x-model=url inputmode=url spellcheck=false placeholder="https://example.com/some/very/long/url" aria-label="Paste a long URL">
<button class="btn black" type=submit :disabled=busy x-text="busy?'Shortening…':'Shorten'"></button>
</div>
</form>
<template x-if="err"><div class="row" role=alert style="color:var(--err)"><i data-lucide=alert-triangle></i><span x-text=err></span></div></template>
<template x-if="out">
<div class="result">
<i data-lucide=check-circle style=color:#16a34a></i>
<a class="tag" :href=out target=_blank rel=noopener x-text=out></a>
<button class="btn copy" @click.prevent="copy()"><i data-lucide=copy></i><span x-text="copied?'Copied!':'Copy'"></span></button>
</div>
</template>
<hr>
<div class="row">
<small class=mono><i data-lucide=sparkles></i>Free → random slug (ex: 4ev.link/aB9Z)</small>
<small class=mono><i data-lucide=lock></i>Custom alias → <b>Paid</b> <span class=dim>(coming soon)</span></small>
</div>
<div class="grid-2 grid" aria-hidden=true>
<div class=input title="Custom alias (Pro soon)">
<i data-lucide=tag></i>
<span class=dim style="padding:10px 8px">Alias (ex: /my-handle)</span>
<button class="btn" disabled>Pro soon</button>
</div>
<div class=input>
<i data-lucide=eye></i>
<span class=dim style="padding:10px 8px">Preview page <span class=kbd>soon</span></span>
</div>
</div>
</section>
<section class="grid card" aria-label=Why>
<h2>Why 4ev.link?</h2>
<div class=grid-2 style="gap:10px">
<div class=row><i data-lucide=zap></i><div><b>Fast</b><div class=dim>Edge redirects in ~20ms</div></div></div>
<div class=row><i data-lucide=shield-check></i><div><b>Safe</b><div class=dim>Simple, open endpoints</div></div></div>
<div class=row><i data-lucide=clock></i><div><b>Forever</b><div class=dim>No expiry on free links</div></div></div>
<div class=row><i data-lucide=wrench></i><div><b>Low-friction</b><div class=dim>No account required</div></div></div>
</div>
<p class=notice>Tip: paste a URL and hit Enter. Well give you a short link you can share instantly.</p>
</section>
<section class="card grid pricing" aria-label=Pricing>
<h2>Pricing</h2>
<div class="grid-2 grid">
<div class=plan>
<h3>Free</h3>
<ul class=dim style="margin:0 0 6px 18px">
<li>Random 4-char slugs</li><li>No account needed</li><li>Unlimited redirects</li>
</ul>
<a class="btn black" href=#start>Start free</a>
</div>
<div class=plan>
<h3>Pro <span class=dim>(coming soon)</span></h3>
<ul class=dim style="margin:0 0 6px 18px">
<li>Custom aliases</li><li>Analytics</li><li>Team access</li>
</ul>
<button class="btn" disabled>Notify me soon</button>
</div>
</div>
</section>
</main>
<footer class=row style="justify-content:space-between">
<div class=row><i data-lucide=copyright></i><span>4ev.link</span><span>·</span><span class=dim>Built on Cloudflare</span></div>
<div class=row><a href=#tos>Terms</a><span>·</span><a href=#privacy>Privacy</a><span>·</span><a href=https://github.com/4ev-link/4ev.link target=_blank rel=noopener class=dim>GitHub</a></div>
</footer>
</div>
<script>document.addEventListener('alpine:init',()=>{lucide&&lucide.createIcons()});</script>
</body>
</html>