repos
/ orchard main

orchard

mirror

Every 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

3.8 KB · 110 lines · HTML Raw History
  1{{define "hero"}}
  2{{$d := .Data}}
  3{{if not $.LoggedIn}}
  4{{/*
  5  The signed out view of this page is an advert for running the thing yourself,
  6  so it opens the way the other sites here open. Signed in it is a working repo
  7  list and the hero would be in the way every single visit.
  8*/}}
  9<section class="hero">
 10  <div class="wrap">
 11  <span class="hero-eyebrow">
 12    <span class="eyebrow-dot" aria-hidden="true"></span>
 13    {{len $d.Repos}} repositories &middot; self-hosted
 14  </span>
 15  <h1 class="hero-title">
 16    A git remote for operators who host their <span class="accent">own code</span>.
 17  </h1>
 18  <p class="hero-sub">
 19    Push over HTTPS with a token and a repository is created on arrival. Browse
 20    branches, tags, files, diffs, and an Atom feed. Your data never leaves your
 21    infrastructure.
 22  </p>
 23  <div class="hero-ctas">
 24    <a href="#repositories" class="btn btn-primary">Browse repositories</a>
 25    <a href="{{$.SourceURL}}" target="_blank" rel="noopener" class="btn btn-ghost">View source</a>
 26  </div>
 27  </div>
 28</section>
 29
 30<section class="stat-strip">
 31  <div class="wrap stat-row">
 32  <div class="stat">
 33    <div class="stat-label">repositories</div>
 34    <div class="stat-value">{{len $d.Repos}}</div>
 35  </div>
 36  <div class="stat">
 37    <div class="stat-label">mirrored</div>
 38    <div class="stat-value">{{$d.Mirrors}}</div>
 39  </div>
 40  <div class="stat">
 41    <div class="stat-label">total size</div>
 42    <div class="stat-value">{{humanBytes $d.TotalSize}}</div>
 43  </div>
 44  <div class="stat">
 45    <div class="stat-label">last push</div>
 46    <div class="stat-value stat-value-sm">{{humanTime $d.LastPush}}</div>
 47  </div>
 48  </div>
 49</section>
 50{{end}}
 51{{end}}
 52
 53{{define "content"}}
 54{{$d := .Data}}
 55
 56{{if and $.LoggedIn (not $d.HasTokens)}}
 57<div class="notice">
 58  <strong>No push token yet.</strong>
 59  Mint one in <a href="/settings">Settings</a> before your first push.
 60</div>
 61{{end}}
 62
 63<div class="pagehead" id="repositories">
 64  <h1 class="pagetitle">Repositories <span class="count">{{len $d.Repos}}</span></h1>
 65  {{if $.LoggedIn}}{{template "firstpush" (dict "CloneURL" $d.CloneURL "Bridge" $d.Bridge "Name" "<name>")}}{{end}}
 66</div>
 67
 68{{if not $d.Repos}}
 69<div class="emptystate">
 70  <h2>Nothing here yet</h2>
 71  <p>Push a repository and it will be created:</p>
 72  <pre class="cmd">git remote add origin {{$d.CloneURL}}/&lt;name&gt;.git
 73git push -u origin main</pre>
 74  {{if $.LoggedIn}}{{template "pushlimit" (dict "Bridge" $d.Bridge "Name" "<name>")}}{{end}}
 75</div>
 76{{end}}
 77
 78<ul class="repolist">
 79{{range $d.Repos}}
 80  <li class="repocard">
 81    <div class="row">
 82      <a class="name" href="/{{.Name}}">{{.Name}}</a>
 83      {{if .Mirror}}<span class="badge mirror">mirror</span>{{end}}
 84      {{if .Archived}}<span class="badge archived">archived</span>{{end}}
 85      {{if .UpstreamGone}}<span class="badge gone" title="No longer on GitHub. This is the only copy.">only copy</span>{{end}}
 86      {{if .Empty}}<span class="badge empty">empty</span>{{end}}
 87    </div>
 88
 89    {{if .Description}}<p class="desc">{{.Description}}</p>{{end}}
 90    {{if .Topics}}<p class="topics">{{range .Topics}}<span class="topic">{{.}}</span>{{end}}</p>{{end}}
 91
 92    {{/*
 93      One span per fact, so the flex gap falls between facts rather than
 94      inside one. Zero counts are dropped: "0 tags" on every row is noise that
 95      makes the real numbers harder to spot.
 96    */}}
 97    <p class="meta">
 98      <span>{{humanBytes .Size}}</span>
 99      <span>{{.Branches}} {{pluralize .Branches "branch" "branches"}}</span>
100      {{if .Tags}}<span>{{.Tags}} {{pluralize .Tags "tag" "tags"}}</span>{{end}}
101      <span>updated <time title="{{.LastPush.Format "2006-01-02 15:04:05 MST"}}">{{humanTime .LastPush}}</time></span>
102      {{if .Mirror}}<span>synced {{humanTime .LastSync}}</span>{{end}}
103    </p>
104
105    {{if .LastSyncErr}}<p class="syncerr">Last sync failed: {{.LastSyncErr}}</p>{{end}}
106  </li>
107{{end}}
108</ul>
109{{end}}