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
1package main
2
3import (
4 "encoding/json"
5 "html/template"
6)
7
8// personID matches the portfolio and the blog, so the sites describe one person
9// rather than several with the same name.
10const (
11 personID = "https://isaacbythewood.com/#person"
12 websiteID = baseURL + "/#website"
13 appID = baseURL + "/#app"
14)
15
16// jsonLD marshals a graph for the script tag. template.JS is safe because
17// encoding/json escapes <, > and &, so no value can close the element early.
18func jsonLD(nodes ...map[string]any) template.JS {
19 buf, err := json.MarshalIndent(map[string]any{
20 "@context": "https://schema.org",
21 "@graph": nodes,
22 }, "", " ")
23 if err != nil {
24 return ""
25 }
26 return template.JS(buf)
27}
28
29// pageGraph is the graph every page on this site carries.
30func pageGraph(title, description, canonical string) template.JS {
31 return jsonLD(
32 map[string]any{
33 "@type": "Person",
34 "@id": personID,
35 "name": authorName,
36 "url": "https://isaacbythewood.com/",
37 "jobTitle": "Senior Solutions Architect",
38 "sameAs": []string{
39 "https://github.com/" + githubUser,
40 "https://isaacbythewood.com/",
41 },
42 },
43 map[string]any{
44 "@type": "WebApplication",
45 "@id": appID,
46 "name": "Analytics",
47 "url": baseURL + "/",
48 "description": "Self-hosted website analytics. Page views, clicks, scrolls, sessions, and custom events.",
49 "applicationCategory": "BusinessApplication",
50 "operatingSystem": "Any",
51 "author": map[string]any{"@id": personID},
52 "publisher": map[string]any{"@id": personID},
53 "image": baseURL + "/static/og/card.png",
54 // A zero price is how schema.org says "free"; no offers means unknown.
55 "offers": map[string]any{
56 "@type": "Offer",
57 "price": "0",
58 "priceCurrency": "USD",
59 },
60 },
61 map[string]any{
62 "@type": "WebSite",
63 "@id": websiteID,
64 "url": baseURL + "/",
65 "name": siteName,
66 "description": "Self-hosted website analytics. Page views, clicks, scrolls, sessions, and custom events.",
67 "inLanguage": "en",
68 "publisher": map[string]any{"@id": personID},
69 },
70 map[string]any{
71 "@type": "WebPage",
72 "@id": canonical + "#webpage",
73 "url": canonical,
74 "name": title,
75 "description": description,
76 "isPartOf": map[string]any{"@id": websiteID},
77 "about": map[string]any{"@id": appID},
78 "inLanguage": "en",
79 },
80 )
81}