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,64 @@
|
||||
// Package config loads runtime configuration from environment variables.
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Config holds process-level settings. Anything the owner can change from the
|
||||
// web UI lives in the database instead (see store.Settings); the API-key
|
||||
// fields here only act as overrides when set.
|
||||
type Config struct {
|
||||
ListenAddr string
|
||||
DataDir string
|
||||
AdminUsername string
|
||||
AdminPassword string
|
||||
SecureCookies bool
|
||||
TrustProxy bool
|
||||
|
||||
// Optional overrides for provider credentials. When set, the matching
|
||||
// setting is locked in the web UI.
|
||||
TMDBKey string
|
||||
TVDBKey string
|
||||
TVDBPin string
|
||||
IGDBClientID string
|
||||
IGDBClientSecret string
|
||||
}
|
||||
|
||||
func Load() Config {
|
||||
port := env("TOPDECK_PORT", "4242")
|
||||
return Config{
|
||||
ListenAddr: env("TOPDECK_LISTEN", ":"+port),
|
||||
DataDir: env("TOPDECK_DATA_DIR", "./data"),
|
||||
AdminUsername: env("TOPDECK_ADMIN_USERNAME", ""),
|
||||
AdminPassword: env("TOPDECK_ADMIN_PASSWORD", ""),
|
||||
SecureCookies: envBool("TOPDECK_SECURE_COOKIES", false),
|
||||
TrustProxy: envBool("TOPDECK_TRUST_PROXY", false),
|
||||
TMDBKey: env("TOPDECK_TMDB_API_KEY", ""),
|
||||
TVDBKey: env("TOPDECK_TVDB_API_KEY", ""),
|
||||
TVDBPin: env("TOPDECK_TVDB_PIN", ""),
|
||||
IGDBClientID: env("TOPDECK_IGDB_CLIENT_ID", ""),
|
||||
IGDBClientSecret: env("TOPDECK_IGDB_CLIENT_SECRET", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func env(key, def string) string {
|
||||
if v, ok := os.LookupEnv(key); ok && strings.TrimSpace(v) != "" {
|
||||
return strings.TrimSpace(v)
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
func envBool(key string, def bool) bool {
|
||||
v, ok := os.LookupEnv(key)
|
||||
if !ok {
|
||||
return def
|
||||
}
|
||||
b, err := strconv.ParseBool(strings.TrimSpace(v))
|
||||
if err != nil {
|
||||
return def
|
||||
}
|
||||
return b
|
||||
}
|
||||
Reference in new issue
Block a user