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>
This commit is contained in:
commit
e9a75a968a
53 files changed
+7078
No files matched your search
@@ -0,0 +1,45 @@
|
||||
{{define "bodyclass"}}page-home{{end}}
|
||||
{{define "content"}}
|
||||
{{$name := or .Site.OwnerName .Site.Title}}
|
||||
<section class="profile container">
|
||||
<div class="avatar avatar--lg">
|
||||
{{- if .Site.AvatarURL}}<img src="{{.Site.AvatarURL}}" alt="">{{else}}<span>{{initial $name}}</span>{{end -}}
|
||||
</div>
|
||||
<div class="profile-text">
|
||||
<h1 class="profile-name">{{$name}}</h1>
|
||||
{{with .Site.Tagline}}<p class="profile-tagline">{{.}}</p>{{end}}
|
||||
{{with .Data}}{{if .Sections}}
|
||||
<p class="profile-stats"><strong>{{num .TotalItems}}</strong> {{plural .TotalItems "favorite" "favorites"}} across <strong>{{.TotalLists}}</strong> {{plural .TotalLists "list" "lists"}}</p>
|
||||
{{end}}{{end}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{if .Data.Sections}}
|
||||
{{if gt (len .Data.Sections) 1}}
|
||||
<nav class="jump container" aria-label="Lists">
|
||||
{{range .Data.Sections}}<a class="chip" href="#{{.List.Slug}}">{{icon .Category.Icon}}<span>{{.List.Title}}</span></a>{{end}}
|
||||
</nav>
|
||||
{{end}}
|
||||
{{range .Data.Sections}}
|
||||
<section class="shelf container" id="{{.List.Slug}}" aria-labelledby="h-{{.List.Slug}}">
|
||||
<header class="shelf-head">
|
||||
<span class="shelf-icon">{{icon .Category.Icon}}</span>
|
||||
<div class="shelf-titles">
|
||||
<h2 id="h-{{.List.Slug}}"><a href="/l/{{.List.Slug}}">{{.List.Title}}</a></h2>
|
||||
{{with .List.Description}}<p class="shelf-desc">{{.}}</p>{{end}}
|
||||
</div>
|
||||
<a class="see-all" href="/l/{{.List.Slug}}">{{if .More}}All {{num .List.ItemCount}}{{else}}Open{{end}}{{icon "arrow-right"}}</a>
|
||||
</header>
|
||||
{{if .Items}}{{template "items" (dict "Items" .Items "Category" .Category "Layout" .List.Layout "Title" .List.Title)}}{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<section class="empty container">
|
||||
<div class="empty-art">{{icon "deck"}}</div>
|
||||
<h2>Nothing ranked yet</h2>
|
||||
<p>This collection is still being curated. Check back soon.</p>
|
||||
{{if .LoggedIn}}<a class="btn btn--primary" href="/admin">{{icon "plus"}}Start a list</a>{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "scripts"}}<script type="module" src="/static/js/public.js?v={{.AssetVer}}"></script>{{end}}
|
||||
Reference in new issue
Block a user