orchard
mirrorEvery site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.
blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics
1// The copy button on the recovery codes page. They are shown once, so the
2// difference between copying them and retyping twelve characters ten times is
3// the difference between saving them and not bothering.
4export function copyButtons() {
5 for (const button of document.querySelectorAll("[data-copy]")) {
6 button.addEventListener("click", async () => {
7 const target = document.querySelector(button.dataset.copy);
8 if (!target) return;
9
10 const text = target.innerText.trim();
11 try {
12 await navigator.clipboard.writeText(text);
13 } catch {
14 // Denied, or an insecure context. Selecting the text is still better
15 // than a button that silently does nothing.
16 const range = document.createRange();
17 range.selectNodeContents(target);
18 const sel = window.getSelection();
19 sel.removeAllRanges();
20 sel.addRange(range);
21 return;
22 }
23
24 const was = button.textContent;
25 button.textContent = "Copied";
26 button.classList.add("is-done");
27 setTimeout(() => {
28 button.textContent = was;
29 button.classList.remove("is-done");
30 }, 1600);
31 });
32 }
33}