Rename project from TopDeck to Canon

- Module github.com/cdnutter/canon, binary/command cmd/canon, Docker
  image and compose project "canon"
- Environment variables now use the CANON_ prefix
- Default site title is "<Your name>'s Canon" (or "Canon" with no name);
  a Site title set in Settings still overrides it
- Existing topdeck.db (and WAL files) is renamed to canon.db on start
- README: upgrade notes, including moving the old compose volume

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cdnutterandClaude Opus 5.5 committed 2026-09-24 17:22:17 -07:00
1 parent 58a29b7339
commit 3923444b3b
26 files changed
+215 -120

No files matched your search

+7 -4
View File
@@ -70,7 +70,10 @@ function profileSection() {
});
const ownerName = h("input", { maxlength: 100, value: settings.ownerName, placeholder: "Your name" });
const siteTitle = h("input", { maxlength: 100, value: settings.siteTitle, placeholder: "TopDeck" });
// Mirrors DefaultTitle in render.go.
const defaultTitle = (name) => (name.trim() ? `${name.trim()}'s Canon` : "Canon");
const siteTitle = h("input", { maxlength: 100, value: settings.siteTitle, placeholder: defaultTitle(settings.ownerName) });
ownerName.addEventListener("input", () => { siteTitle.placeholder = defaultTitle(ownerName.value); });
const tagline = h("input", { maxlength: 300, value: settings.tagline, placeholder: "A line about you or your taste" });
const preview = h("input", { type: "number", min: 0, max: 50, value: settings.previewCount, style: { maxWidth: "120px" } });
const notes = h("input", { type: "checkbox", checked: settings.showNotes });
@@ -78,7 +81,7 @@ function profileSection() {
const form = h("form", { class: "stack" },
h("div", { class: "avatar-edit" }, avatarBox, h("div", { class: "row-btns", style: { display: "flex", gap: "6px", flexWrap: "wrap" } }, uploadBtn, removeBtn, file)),
h("div", { class: "row" }, field("Your name", ownerName, "Shown as the page heading."), field("Site title", siteTitle, "Shown in the header and browser tab.")),
h("div", { class: "row" }, field("Your name", ownerName, "Shown as the page heading."), field("Site title", siteTitle, "Shown in the header and browser tab. Leave blank to use “Your name's Canon”.")),
field("Tagline", tagline),
field("Entries per list on the home page", preview, "Visitors see the full list on each list's page. 0 shows only the heading."),
h("label", { class: "check" }, notes, "Show my notes to visitors"),
@@ -93,7 +96,7 @@ function profileSection() {
if (ok) {
renderAvatar();
const brand = document.querySelector(".brand-name");
if (brand) brand.textContent = settings.siteTitle || "TopDeck";
if (brand) brand.textContent = settings.siteTitleShown;
}
});
renderAvatar();
@@ -181,7 +184,7 @@ function secretInput(key, label, hintHTML) {
disabled: st.locked,
});
const hint = h("span", { class: "field-hint" });
if (st.locked) hint.textContent = `Set by the ${"TOPDECK_" + key.toUpperCase()} environment variable.`;
if (st.locked) hint.textContent = `Set by the ${"CANON_" + key.toUpperCase()} environment variable.`;
else if (hintHTML) hint.append(...hintHTML);
const wrap = field(label, input);
wrap.append(hint);