links-free.openapps.xyz

Source

This app’s code and revision history are public. Download a copy or explore the files below.

Public
The app’s code and revision history are public.
Owned app · rev 9e2af813edac
Run it yourself
Take the whole tree and run it on your own machine. The download needs no account. Cloning needs a sign-in.
Download .zip
bounded clone 3151231032497ed786b88a0a
A copy you download is not bounded. The guarantees this app runs under - declared egress, proven invariants, writes that fail closed - live in the runtime serving this page, not in the files. What you get is auditable source you can read and run, with no runtime guarantees attached.
← All files
functions/lib/links.ts
// What a short link may be, shared by the web app and the public API.
import { SITE_URL } from "./config";

export const MAX_URL = 2000;
const CODE_RE = /^[A-Za-z0-9_-]{3,32}$/;
// Random endings skip look-alikes (0 O o, 1 l I) so they survive being read aloud or retyped.
const CODE_ALPHABET = "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
const KEY_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
// Paths the site uses itself. Endings cannot hold a dot, so files like llms.txt are already safe.
const RESERVED = ["api", "e", "new", "admin", "about", "help", "assets", "art", "fonts", "__bounded"];
// Hosts that serve Links: a link pointing back at them would open another short link, or loop.
const OWN_HOSTS = ["links-free.openapps.xyz", "oafree-links.bounded.page", new URL(SITE_URL).hostname];

function random(alphabet: string, length: number): string {
  const out: string[] = [];
  const limit = 256 - (256 % alphabet.length);
  while (out.length < length) {
    for (const b of crypto.getRandomValues(new Uint8Array(length * 2))) {
      if (b < limit && out.length < length) out.push(alphabet[b % alphabet.length]);
    }
  }
  return out.join("");
}

export const randomCode = () => random(CODE_ALPHABET, 7);
export const randomKey = () => random(KEY_ALPHABET, 24);
export const shortUrl = (code: string) => `${SITE_URL}/${code}`;
export const editUrl = (code: string, key: string) => `${SITE_URL}/e/${code}#k=${key}`;

/** A UTC day as the number yyyymmdd (20261019), the id of a link's daily click count. */
export const dayNumber = (date: Date) => date.getUTCFullYear() * 10000 + (date.getUTCMonth() + 1) * 100 + date.getUTCDate();
/** 20261019 -> "2026-10-19". */
export const dayIso = (d: number) => `${Math.floor(d / 10000)}-${String(Math.floor(d / 100) % 100).padStart(2, "0")}-${String(d % 100).padStart(2, "0")}`;

/** Normalizes a destination, or says what is wrong with it. "example.com/x" becomes "https://example.com/x". */
export function checkUrl(raw: unknown): { url: string } | { error: string } {
  let text = String(raw ?? "").trim();
  if (!text) return { error: "Paste the link you want to shorten." };
  const scheme = text.match(/^([a-z][a-z0-9+.-]*):/i);
  if (!scheme || (!/^[a-z][a-z0-9+.-]*:\/\//i.test(text) && scheme[1].includes("."))) text = `https://${text}`;
  let u: URL;
  try {
    u = new URL(text);
  } catch {
    return { error: "That does not look like a web address." };
  }
  if (u.protocol !== "http:" && u.protocol !== "https:") return { error: "Only web addresses (http or https) can be shortened." };
  if (!u.hostname.includes(".")) return { error: "That does not look like a web address." };
  if (OWN_HOSTS.includes(u.hostname.replace(/\.$/, ""))) return { error: "That is already a Links address. Paste the page it should open instead." };
  if (u.href.length > MAX_URL) return { error: `Links can be up to ${MAX_URL.toLocaleString("en-US")} characters long.` };
  return { url: u.href };
}

/** True when a stored destination is safe to open: only http and https, never back at Links. */
export function isSafeDestination(url: unknown): url is string {
  const checked = checkUrl(url);
  return "url" in checked && checked.url === url;
}

/** Checks a custom ending. */
export function checkCode(raw: unknown): { code: string } | { error: string } {
  const code = String(raw ?? "").trim().replace(/^\/+|\/+$/g, "");
  if (!CODE_RE.test(code)) return { error: "Endings are 3 to 32 letters, numbers, dashes or underscores." };
  if (RESERVED.includes(code.toLowerCase())) return { error: `"${code}" is reserved. Try another ending.` };
  return { code };
}

Change history

Quality pass: clicks per day, CSV export, links on other devices
9e2af813ed · 6 hours ago
Bounded source sync
29eee7dafa · 1 day ago
Bounded source sync
c5e634046a · 1 day ago
Bounded source sync
12abf93e7e · 1 day ago
Bounded source sync
d0d6a654b1 · 1 day ago
Bounded source sync
e03049f905 · 1 day ago
Bounded source sync
eb5c793bfa · 1 day ago
Bounded source sync
5dd8ec26e1 · 1 day ago