Files
canon/web/templates/layout.html
T
cdnutterandClaude Opus 5.5 e9a75a968a Initial TopDeck: self-hosted ranked favorites
A single Go binary with SQLite that serves a public page of the owner's
ranked lists (movies, TV, albums, songs, video games, theater) and a
login-gated editor.

- Lists of 1–65,535 entries (100 recommended), several per category
- Search-to-add via TMDB, TheTVDB, IGDB, Deezer/MusicBrainz, Wikipedia;
  manual entry as a fallback
- Theater entries carry a production (Broadway, tour, …), venue and cast
- Artwork cached locally; URL override and uploads
- Drag, arrow and type-a-rank reordering; paginated for long lists
- 12 theme presets plus custom CSS
- First-run setup code or env-provided admin; bcrypt, rate-limited login,
  CSRF-guarded JSON API
- Dockerfile and docker-compose.yml

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 16:54:19 -07:00

48 lines
2.2 KiB
HTML

<!doctype html>
<html lang="en" data-theme="{{.Site.Theme}}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{if .PageTitle}}{{.PageTitle}} · {{end}}{{.Site.Title}}</title>
<meta name="description" content="{{if .Site.Tagline}}{{.Site.Tagline}}{{else}}{{.Site.Title}}: a ranked collection of favorites{{end}}">
<meta property="og:title" content="{{if .PageTitle}}{{.PageTitle}} · {{end}}{{.Site.Title}}">
<link rel="icon" href="/static/img/favicon.svg" type="image/svg+xml">
<link rel="stylesheet" href="/static/css/themes.css?v={{.AssetVer}}">
<link rel="stylesheet" href="/static/css/app.css?v={{.AssetVer}}">
{{- if .Site.CustomCSS}}
<link rel="stylesheet" href="/custom.css?v={{.Site.CSSVersion}}">
{{- end}}
</head>
<body class="{{block "bodyclass" .}}{{end}}">
<a class="skip-link" href="#main">Skip to content</a>
<header class="topbar">
<div class="topbar-inner container">
<a class="brand" href="/">
{{- if .Site.AvatarURL}}<img class="brand-avatar" src="{{.Site.AvatarURL}}" alt="">{{else}}<span class="brand-mark">{{icon "deck"}}</span>{{end -}}
<span class="brand-name">{{.Site.Title}}</span>
</a>
{{- if .LoggedIn}}
<nav class="topnav" aria-label="Admin">
<a href="/admin"{{if or (eq .Path "/admin") (hasPrefix .Path "/admin/lists")}} aria-current="page"{{end}}>{{icon "list"}}<span>Lists</span></a>
<a href="/admin/settings"{{if eq .Path "/admin/settings"}} aria-current="page"{{end}}>{{icon "settings"}}<span>Settings</span></a>
<form method="post" action="/logout" class="topnav-form">
<button type="submit" class="topnav-btn" title="Sign out ({{.Username}})">{{icon "logout"}}<span class="sr-only">Sign out</span></button>
</form>
</nav>
{{- end}}
</div>
</header>
<main id="main">
{{block "content" .}}{{end}}
</main>
<footer class="footer">
<div class="container footer-inner">
<span>{{if .Site.OwnerName}}Curated by {{.Site.OwnerName}}{{else}}{{.Site.Title}}{{end}}</span>
<span class="footer-sep" aria-hidden="true">·</span>
<span>Powered by <a href="https://git.iamchrisama.com/cdnutter/topdeck" rel="noopener">TopDeck</a></span>
</div>
</footer>
{{block "scripts" .}}{{end}}
</body>
</html>