Heavy security and file splitting
CI / Go Tests (push) Successful in 15s
CI / Build (push) Successful in 9s
Format / gofmt (push) Successful in 7s
Release Artifacts / Validate release tag (push) Successful in 2s
Release Artifacts / Build and release executables (push) Successful in 15s
Release Artifacts / Build and release Docker image (push) Successful in 28s

This commit is contained in:
2026-06-01 20:15:28 -05:00
parent bdbe1a9416
commit ad4355df17
27 changed files with 1540 additions and 1166 deletions
+8
View File
@@ -4,6 +4,14 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Scratchbox</title>
<meta name="description" content="Minimal temporary file sharing. Upload once, share the link, auto-expires." />
<meta property="og:title" content="Scratchbox" />
<meta property="og:description" content="Minimal temporary file sharing. Upload once, share the link, auto-expires." />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Scratchbox" />
<meta name="twitter:description" content="Minimal temporary file sharing. Upload once, share the link, auto-expires." />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
</head>
<body>
<div id="app"></div>
+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
<rect x="3" y="3" width="26" height="26" rx="5" fill="#213f75" stroke="#2f67c8" stroke-width="2"/>
<text x="16" y="22" font-family="system-ui, sans-serif" font-size="16" font-weight="700" fill="#f5f7fc" text-anchor="middle" dominant-baseline="middle">S</text>
</svg>

After

Width:  |  Height:  |  Size: 367 B

+37 -2
View File
@@ -30,6 +30,14 @@
const maxUploadSizeDisplay = $derived(formatBytes(maxUploadSizeBytes, true));
const defaultTTLDisplay = $derived(formatTTLDisplay(defaultTTL));
const viewPageTitle = $derived(
viewMeta?.filename
? `${viewMeta.filename} • Scratchbox`
: scratchID
? `${scratchID} • Scratchbox`
: "Scratchbox"
);
onMount(async () => {
nowTicker = window.setInterval(() => {
nowMs = Date.now();
@@ -127,14 +135,16 @@
return;
}
const msg = await metaResponse.text();
throw new Error(msg || `Failed to load scratch metadata (${metaResponse.status}).`);
viewError = msg || `Failed to load scratch metadata (${metaResponse.status}).`;
return;
}
viewMeta = await metaResponse.json();
const rawResponse = await fetch(`/api/raw/${encodeURIComponent(scratchID)}`);
if (!rawResponse.ok) {
const msg = await rawResponse.text();
throw new Error(msg || `Failed to load scratch content (${rawResponse.status}).`);
viewError = msg || `Failed to load scratch content (${rawResponse.status}).`;
return;
}
const contentType = rawResponse.headers.get("content-type") ?? "";
@@ -412,6 +422,31 @@
}
</script>
<svelte:head>
{#if routeMode === "view"}
<title>{viewPageTitle}</title>
<meta property="og:title" content={viewPageTitle} />
<meta property="og:description" content="Temporary scratch file shared on Scratchbox." />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content={viewPageTitle} />
{:else if routeMode === "expired"}
<title>Scratch expired • Scratchbox</title>
<meta property="og:title" content="Scratch expired • Scratchbox" />
<meta property="og:description" content="This scratch is no longer available." />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Scratch expired • Scratchbox" />
{:else if routeMode === "notfound"}
<title>Not found • Scratchbox</title>
<meta property="og:title" content="Not found • Scratchbox" />
<meta property="og:description" content="The requested path does not exist." />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Not found • Scratchbox" />
{/if}
</svelte:head>
<main class="container">
<header class="site-header">
<div class="brand-row">