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<!doctype html>
2<html lang="en">
3<head>
4 <meta charset="utf-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <title>{{ .Title }} ยท {{ .SiteName }}</title>
7 <meta name="description" content="{{ .Description }}">
8 <link rel="canonical" href="{{ .Canonical }}">
9 {{/* The staging hostname is a complete duplicate of the real site, which is
10 the one way it can damage it. robots.txt refuses the crawl and this
11 refuses the index, because either alone has a hole: a crawler that
12 ignores robots.txt still sees the meta tag, and one that obeys it never
13 fetches the page to read the tag. */}}
14 {{ if .Staging }}<meta name="robots" content="noindex, nofollow">{{ end }}
15 <link rel="icon" type="image/svg+xml" href="/favicon.ico">
16
17 {{/* This site shipped with no social meta at all, so every link to it
18 anywhere rendered as a bare URL. The card is a PNG compiled from
19 typst/card.typ at build time and dropped into dist: SVG is refused for
20 og:image by Facebook, X, LinkedIn, Slack, iMessage and Discord alike. */}}
21 <meta property="og:type" content="website">
22 <meta property="og:site_name" content="{{ .SiteName }}">
23 <meta property="og:title" content="{{ .Title }}">
24 <meta property="og:description" content="{{ .Description }}">
25 <meta property="og:url" content="{{ .Canonical }}">
26 <meta property="og:image" content="{{ .OGImage }}">
27 <meta property="og:image:width" content="1200">
28 <meta property="og:image:height" content="630">
29
30 <meta name="twitter:card" content="summary_large_image">
31 <meta name="twitter:title" content="{{ .Title }}">
32 <meta name="twitter:description" content="{{ .Description }}">
33 <meta name="twitter:image" content="{{ .OGImage }}">
34
35 {{ if .JSONLD }}<script type="application/ld+json">{{ .JSONLD }}</script>{{ end }}
36
37 {{ template "extra_head" . }}
38
39 {{ range .Styles }}<link href="{{ . }}" rel="stylesheet">{{ end }}
40 {{ range .PageStyles }}<link href="{{ . }}" rel="stylesheet">{{ end }}
41 {{ template "extra_css" . }}
42
43 {{/* The same collector snippet the other sites carry, behind the same gate:
44 off on a staging hostname. */}}
45 {{- if .Analytics }}
46 <script>
47 (function (m, e, t, r, i, c, s) {
48 m.collectorQueue = m.collectorQueue || r;
49 m.collectorServer = c;
50 m.collectorId = s;
51 m.collectorScript = e.createElement(t);
52 m.collectorScript.src = c + i;
53 e.head.appendChild(m.collectorScript);
54 })(window, document, "script", [], "/static/collector.js",
55 "https://analytics.bythewood.me", "{{ .AnalyticsID }}");
56 </script>
57 {{- end }}
58</head>
59
60<body>
61 {{ template "nav" . }}
62
63 {{ template "breadcrumb_bar" . }}
64
65 <main>
66 {{ template "main" . }}
67 </main>
68
69 {{ template "footer" . }}
70
71 <script type="module" src="{{ .Script }}"></script>
72 {{ if .PageScript }}<script type="module" src="{{ .PageScript }}"></script>{{ end }}
73 {{ template "extra_js" . }}
74</body>
75</html>