Compact home page entries; set up Compose for Arcane git sync
Podium, Spotlight and Grid render smaller on the home page on desktop so one entry no longer fills the screen; list pages keep full size. Compose now builds on every deploy (pull_policy: build), stores data in the canon-data named volume outside the synced folder (CANON_DATA_PATH overrides), and takes optional bind/port/version settings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
33053d1c5f
commit
218bb296ee
4 files changed
+71
-3
No files matched your search
@@ -20,3 +20,13 @@ CANON_IGDB_CLIENT_SECRET=
|
|||||||
# CANON_HOST=0.0.0.0 # all network interfaces; 127.0.0.1 = this machine only
|
# CANON_HOST=0.0.0.0 # all network interfaces; 127.0.0.1 = this machine only
|
||||||
# CANON_PORT=4242
|
# CANON_PORT=4242
|
||||||
# CANON_LOG_LEVEL=debug
|
# CANON_LOG_LEVEL=debug
|
||||||
|
|
||||||
|
# ---- Docker Compose only (not read by Canon itself) ----
|
||||||
|
# Where the database and images live. Default: the canon_canon-data volume.
|
||||||
|
# Use an absolute host path to keep them in a folder (writable by UID 1000).
|
||||||
|
# CANON_DATA_PATH=/srv/canon
|
||||||
|
# Host address and port to publish on.
|
||||||
|
# CANON_BIND=0.0.0.0
|
||||||
|
# CANON_PUBLISH_PORT=4242
|
||||||
|
# Version label baked into the image at build time.
|
||||||
|
# CANON_VERSION=dev
|
||||||
@@ -37,6 +37,23 @@ To skip the setup page, set `CANON_ADMIN_USERNAME` and `CANON_ADMIN_PASSWORD` in
|
|||||||
|
|
||||||
Canon listens on all network interfaces (`0.0.0.0`) by default, so phones and other computers on your network can open `http://<this computer's IP>:4242`. When run outside Docker, the startup log prints the exact addresses. If another device can't connect, the host's firewall is probably blocking the port (for example `sudo ufw allow 4242/tcp`). To keep Canon private to one machine, set `CANON_HOST=127.0.0.1`, or publish `127.0.0.1:4242:4242` in `docker-compose.yml`.
|
Canon listens on all network interfaces (`0.0.0.0`) by default, so phones and other computers on your network can open `http://<this computer's IP>:4242`. When run outside Docker, the startup log prints the exact addresses. If another device can't connect, the host's firewall is probably blocking the port (for example `sudo ufw allow 4242/tcp`). To keep Canon private to one machine, set `CANON_HOST=127.0.0.1`, or publish `127.0.0.1:4242:4242` in `docker-compose.yml`.
|
||||||
|
|
||||||
|
### With Arcane (Git sync)
|
||||||
|
|
||||||
|
The compose file works as an [Arcane](https://getarcane.app) project synced from this repository:
|
||||||
|
|
||||||
|
1. **Projects → New → Git sync**, direction **Pull**, compose file path `docker-compose.yml`.
|
||||||
|
2. Turn on **Redeploy after sync** to rebuild whenever you push. `pull_policy: build` makes every deploy build the image from the synced source; it never looks for `canon:latest` on a registry.
|
||||||
|
3. Put your settings (admin account, API keys) in the project's environment in Arcane. Arcane writes them to `.env`, which Canon reads.
|
||||||
|
|
||||||
|
The database lives in the `canon_canon-data` named volume, outside the synced folder, so a sync can't overwrite or delete it. To use a host folder instead, set `CANON_DATA_PATH` to an absolute path (it must be writable by UID 1000). To move data from an existing `./data` folder into the volume:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker compose stop canon
|
||||||
|
docker run --rm -v "$PWD/data:/from" -v canon_canon-data:/to alpine sh -c 'cp -a /from/. /to/ && chown -R 1000:1000 /to'
|
||||||
|
```
|
||||||
|
|
||||||
|
The compose file joins the external `chromanet` network; create it first (`docker network create chromanet`) or remove the `networks` entries.
|
||||||
|
|
||||||
### Without Compose
|
### Without Compose
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
+19
-3
@@ -1,21 +1,37 @@
|
|||||||
name: canon
|
name: canon
|
||||||
|
|
||||||
|
# Works with a plain `docker compose up -d --build` and with Arcane's Git sync
|
||||||
|
# (Pull). Arcane pulls this file's whole directory, so the build context is
|
||||||
|
# the repository itself.
|
||||||
|
|
||||||
services:
|
services:
|
||||||
canon:
|
canon:
|
||||||
build: .
|
build:
|
||||||
|
context: .
|
||||||
|
args:
|
||||||
|
VERSION: ${CANON_VERSION:-dev}
|
||||||
image: canon:latest
|
image: canon:latest
|
||||||
|
# Never look for canon:latest on a registry: every deploy (including
|
||||||
|
# Arcane's "Pull image" / "Redeploy after sync") builds from the source
|
||||||
|
# that was just synced.
|
||||||
|
pull_policy: build
|
||||||
container_name: canon
|
container_name: canon
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "0.0.0.0:4242:4242"
|
- "${CANON_BIND:-0.0.0.0}:${CANON_PUBLISH_PORT:-4242}:4242"
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/data
|
# A named volume by default, so a Git sync never touches the database.
|
||||||
|
# Set CANON_DATA_PATH to a host folder (e.g. ./data) to keep it there.
|
||||||
|
- ${CANON_DATA_PATH:-canon-data}:/data
|
||||||
env_file:
|
env_file:
|
||||||
- path: .env
|
- path: .env
|
||||||
required: false
|
required: false
|
||||||
networks:
|
networks:
|
||||||
- chromanet
|
- chromanet
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
canon-data:
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
chromanet:
|
chromanet:
|
||||||
external: true
|
external: true
|
||||||
@@ -166,6 +166,10 @@ code { font: 0.9em ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; bac
|
|||||||
.items { list-style: none; margin: 0; padding: 0; }
|
.items { list-style: none; margin: 0; padding: 0; }
|
||||||
.items--grid { display: grid; gap: 22px 18px; grid-template-columns: repeat(auto-fill, minmax(156px, 1fr)); }
|
.items--grid { display: grid; gap: 22px 18px; grid-template-columns: repeat(auto-fill, minmax(156px, 1fr)); }
|
||||||
.aspect-square .items--grid { grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); }
|
.aspect-square .items--grid { grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); }
|
||||||
|
@media (min-width: 641px) {
|
||||||
|
.page-home .items--grid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
|
||||||
|
.page-home .aspect-square .items--grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
|
||||||
|
}
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.items--grid { grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 16px 12px; }
|
.items--grid { grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 16px 12px; }
|
||||||
.aspect-square .items--grid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
|
.aspect-square .items--grid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
|
||||||
@@ -325,6 +329,21 @@ code { font: 0.9em ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; bac
|
|||||||
.podium-card { padding-bottom: 10px; }
|
.podium-card { padding-bottom: 10px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The home page is a preview of every list, so its podium is compact; the
|
||||||
|
list page keeps the full-size one. */
|
||||||
|
@media (min-width: 641px) {
|
||||||
|
.page-home .podium { max-width: 580px; gap: 0 16px; }
|
||||||
|
.page-home .podium--2 { max-width: 390px; }
|
||||||
|
.page-home .podium--1 { grid-template-columns: minmax(0, 190px); }
|
||||||
|
.page-home .podium-card { gap: 10px; padding-bottom: 10px; }
|
||||||
|
.page-home .podium-card .item-title { font-size: 14.5px; }
|
||||||
|
.page-home .podium-spot--1 .item-title { font-size: 16px; }
|
||||||
|
.page-home .podium-step { font-size: 22px; }
|
||||||
|
.page-home .podium-spot--1 .podium-step { height: 56px; font-size: 28px; }
|
||||||
|
.page-home .podium-spot--2 .podium-step { height: 40px; }
|
||||||
|
.page-home .podium-spot--3 .podium-step { height: 28px; font-size: 18px; }
|
||||||
|
}
|
||||||
|
|
||||||
/* "Show N more" under a podium: the browser's own <details>, so it works
|
/* "Show N more" under a podium: the browser's own <details>, so it works
|
||||||
without JavaScript. */
|
without JavaScript. */
|
||||||
.more { padding-top: 18px; }
|
.more { padding-top: 18px; }
|
||||||
@@ -372,6 +391,12 @@ code { font: 0.9em ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; bac
|
|||||||
display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
|
display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
|
||||||
}
|
}
|
||||||
.spotlight-more { margin-top: 10px; }
|
.spotlight-more { margin-top: 10px; }
|
||||||
|
@media (min-width: 641px) {
|
||||||
|
.page-home .spotlight, .page-home .aspect-square .spotlight { grid-template-columns: 150px 1fr; gap: 24px; padding: 18px; }
|
||||||
|
.page-home .spotlight-rank { font-size: 32px; }
|
||||||
|
.page-home .spotlight-title { font-size: clamp(20px, 2.2vw, 26px); }
|
||||||
|
.page-home .spotlight-desc, .page-home .spotlight-note { -webkit-line-clamp: 3; font-size: 14.5px; }
|
||||||
|
}
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.spotlight, .aspect-square .spotlight { grid-template-columns: 1fr; gap: 18px; padding: 18px; }
|
.spotlight, .aspect-square .spotlight { grid-template-columns: 1fr; gap: 18px; padding: 18px; }
|
||||||
.spotlight-art { width: min(100%, 220px); justify-self: center; }
|
.spotlight-art { width: min(100%, 220px); justify-self: center; }
|
||||||
|
|||||||
Reference in new issue
Block a user