summaryrefslogtreecommitdiff
path: root/internal
AgeCommit message (Collapse)Author
5 daysOptimize VPN mirror sync and release v0.19.2v0.19.2Paul Buetow
Amp-Thread-ID: https://ampcode.com/threads/T-019fc31d-668a-769a-8dc8-554ecbd6a274 Co-authored-by: Amp <amp@ampcode.com>
5 daysAdd WireGuard fallback for mirror syncPaul Buetow
Amp-Thread-ID: https://ampcode.com/threads/T-019fc31d-668a-769a-8dc8-554ecbd6a274 Co-authored-by: Amp <amp@ampcode.com>
5 daysMake arcade theme music more audiblePaul Buetow
Amp-Thread-ID: https://ampcode.com/threads/T-019fbeb1-4c14-7775-baa1-5cd8579b1dfd Co-authored-by: Amp <amp@ampcode.com>
5 daysAdd arcade themes and release v0.19.0Paul Buetow
Amp-Thread-ID: https://ampcode.com/threads/T-019fbeb1-4c14-7775-baa1-5cd8579b1dfd Co-authored-by: Amp <amp@ampcode.com>
5 daysAdd Tetris themePaul Buetow
Amp-Thread-ID: https://ampcode.com/threads/T-019fbeb1-4c14-7775-baa1-5cd8579b1dfd Co-authored-by: Amp <amp@ampcode.com>
2026-07-08joPaul Buetow
2026-07-06Bump version to 0.18.0v0.18.0Paul Buetow
2026-07-05Add splash screen choice to enter with or without background music (js0)Paul Buetow
Injects an explicit "With music" / "Without music" choice into the splash overlay at runtime (uniformly across all themes) instead of only letting visitors discover the 'p' ambient shortcut after they're already inside. Clicking a button saves the preference, starts/pauses the ambient engine, and dismisses the splash. Re-injected after the two spots that replace #splash-overlay's innerHTML wholesale (theme switch / theme-meta swap) so the buttons survive. Also fixes a keyboard-focus bug this introduced: the splash's document-level Enter/Space handler was swallowing native button activation for a Tab-focused choice button. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03Fix --sync remote path and permissions after pi0/pi1 NetBSD migrationPaul Buetow
The default sync target directory was still /var/www/html/snonux/, but that directory was renamed to snonux.foo/ on both pi0 and pi1 as part of a bozohttpd vhost fix. Also add --chmod=D755,F644 to the rsync invocation: locally-generated output is mode 600, which lighttpd apparently tolerated but bozohttpd's separate _httpd service user does not (403 Forbidden). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-06-03Bump version to 0.17.0v0.17.0Paul Buetow
Amp-Thread-ID: https://ampcode.com/threads/T-019e8f2a-b58e-72b3-b572-28d1fb1d9a1d Co-authored-by: Amp <amp@ampcode.com>
2026-06-03Show post share button on desktop too (clipboard copy fallback)Paul Buetow
Removed the mobile-only display:none gate so the share button is visible on all viewports. On desktop, navigator.share is typically unavailable, so the existing JS handler falls through to clipboard.writeText() and shows the 'Link copied' toast. The mobile @media rule still bumps the touch target to 40x40. Amp-Thread-ID: https://ampcode.com/threads/T-019e8f2a-b58e-72b3-b572-28d1fb1d9a1d Co-authored-by: Amp <amp@ampcode.com>
2026-06-03Add per-post share button with permalink (mobile view)Paul Buetow
Each post now exposes a share button in its header that surfaces only on mobile. Clicking it invokes navigator.share() with a permalink of the form "<page>#post-<ID>", which the existing deep-link handler in shared.js already opens directly in the modal. When navigator.share is unavailable the link is copied to the clipboard and a brief toast confirms the action; very old browsers fall back to window.prompt. Amp-Thread-ID: https://ampcode.com/threads/T-019e8f2a-b58e-72b3-b572-28d1fb1d9a1d Co-authored-by: Amp <amp@ampcode.com>
2026-05-16Add theme background musicv0.16.0Paul Buetow
2026-05-06Bump version to 0.15.0v0.15.0Paul Buetow
Amp-Thread-ID: https://ampcode.com/threads/T-019dfbe0-b5ea-77bb-be19-11decfbbea69 Co-authored-by: Amp <amp@ampcode.com>
2026-05-01add more fontsv0.14.2Paul Buetow
2026-05-01Handle scroll-driven post selection for task bPaul Buetow
2026-05-01Document brutalist system fonts for task aPaul Buetow
2026-05-01task 9: self-host nukem Web437 fontPaul Buetow
2026-05-01Task 8: self-host volcano theme fontsPaul Buetow
2026-05-01Task 7: self-host tropicale Quicksand fontsPaul Buetow
2026-05-01Task 5b: self-host aurora Manrope fontsPaul Buetow
2026-05-01za: self-host neon Orbitron webfontsPaul Buetow
2026-05-01xa: self-host surveillance webfontPaul Buetow
2026-05-01wa self-host Space Mono for spaceagePaul Buetow
2026-05-01va self-host retrofuture webfontsPaul Buetow
2026-05-01ua self-host noir webfontsPaul Buetow
2026-05-01ta self-host cathedral webfontsPaul Buetow
2026-05-01Add self-hosted Outfit font for ocean themePaul Buetow
Task: 7b
2026-05-01Self-host Exo 2 for cosmos theme (task 6b)Paul Buetow
2026-05-01task 2b: self-host terminal JetBrains MonoPaul Buetow
2026-05-01Self-host Rajdhani for plasma theme (task 8b)Paul Buetow
2026-05-01Add retro VT323 webfont for task 1bPaul Buetow
2026-05-01Add synthwave self-hosted webfonts for task yaPaul Buetow
2026-05-01Add self-hosted VT323 matrix font for task 0bPaul Buetow
2026-05-01biomech theme: self-host Oxanium 400/700 webfont (task sa)Paul Buetow
- Add Oxanium-Regular.woff2 and Oxanium-Bold.woff2 (latin + latin-ext subset, ~22 KB total) by Tyler Finck, fetched 2026-05-01 from https://gwfh.mranftl.com/fonts/oxanium (mirrors Google Fonts); released under SIL OFL 1.1. - biomech/theme.css: add @font-face blocks pointing at the local files. The CSS already declared 'Oxanium' as the body font but the family was never loaded, so it silently fell back to system sans-serif. Now the geometric techy face actually renders. - biomech/FONT_LICENSE.txt: full attribution + OFL link + source URL + fetch date so future maintainers can re-fetch deterministically. - templates/embed.go: append themes/*/*.woff2 to the //go:embed glob (deferred from task ra because go:embed requires every pattern to match at least one file, which biomech now satisfies). - README.md: append biomech entry to the bundled-fonts bullet list. Self-hosted, no third-party CDN requests at page load; verified via grep -RnE 'googleapis|gstatic|@import url\(http' against both source and generated dist. Amp-Thread-ID: https://ampcode.com/threads/T-019de000-c062-73c5-9afc-c9af422473cf Co-authored-by: Amp <amp@ampcode.com>
2026-05-01webfonts: bundle dos theme font + document per-theme webfont conventions ↵Paul Buetow
(task ra) - dos theme: bundle 'WebPlus IBM VGA 8x16' (.woff) by VileR from the Ultimate Oldschool PC Font Pack v2.2 (CC BY-SA 4.0); replace the never-loaded VT323 reference with @font-face + a self-hosted bitmap face matching the BBS/DOS aesthetic. - templates/embed.go: add ThemeExtraFiles + extend the //go:embed glob with themes/*/*.woff and themes/*/FONT_LICENSE.txt so any theme can ship its own font assets without further code changes; add a NOTE comment block documenting the per-theme directory convention and the //go:embed pattern-matching constraint. - generator/writeThemeAsset: copy any extra files (fonts, license notices) verbatim from the embedded FS into dist/themes/<name>/. - README.md: rewrite the 'Third-party assets' section into a bullet list with self-hosting policy, attribution for the bundled dos font, and a step-by-step recipe for adding new bundled fonts. - dos/FONT_LICENSE.txt: full attribution + CC BY-SA 4.0 notice. Self-hosted, no third-party CDN requests at page load. Amp-Thread-ID: https://ampcode.com/threads/T-019de000-c062-73c5-9afc-c9af422473cf Co-authored-by: Amp <amp@ampcode.com>
2026-04-29Bump version to 0.14.10.14.1Paul Buetow
Made-with: Cursor
2026-04-27Bump version to 0.14.0v0.14.0Paul Buetow
2026-04-27fix(processor): handle os.Remove errors for markdown inbox extrasPaul Buetow
When removing markdown inbox extras (embedded local images), os.Remove errors were silently ignored. If removal failed, the image remained in the inbox and was later published as a standalone image post. - Check os.Remove errors and return a wrapped error. - Rollback the already-saved post directory when extra removal fails. - Deduplicate extras to avoid failing on duplicate references (e.g. same image referenced twice in one markdown). - Add a negative test that verifies the error is returned and no post is persisted when removing an embedded image fails. Fixes duplicate image posts caused by leftover inbox extras.
2026-04-27+code-quality Add slice capacity pre-allocation in loadAllPosts and paginatePaul Buetow
- loadAllPosts: pre-allocate posts slice with capacity len(entries) since each directory entry may become a post. - paginate: pre-allocate pages slice with capacity (len(posts)+pageSize-1)/pageSize. The concat function no longer exists in the codebase (removed when theme sound data was moved to embedded JSON files in commit 06dd860).
2026-04-27+code-quality Remove dead/unimplemented midi.go (YAGNI violation)Paul Buetow
2026-04-27refactor(generator): move theme sound data from Go code to embedded JSON filesPaul Buetow
- Generate sounds.json for each theme inside templates/themes/<name>/ - Load sound data at runtime from embedded FS via templates.ThemeSounds() - Replace ~1100 lines of hardcoded builder functions and presets with a 145-line loader (soundCache, initSoundCache, loadThemeSounds) - Update embed.go to include themes/*/sounds.json in the embedded FS - Update tests to use loadThemeSounds() instead of themeSoundPresets - Eliminates duplication between themeSoundPresets and JSON output Improves cohesion and DRY by keeping theme assets (CSS, JS, meta, sounds) in a single location per theme directory.
2026-04-27generator: place Run entry point before private helpersPaul Buetow
2026-04-27Add context.Context to I/O-bound public APIs (generator.Run, processor.Run, ↵Paul Buetow
atom.Generate, syncOutput) - generator.Run(ctx, cfg) – ctx passed through to atom.Generate - processor.Run(ctx, cfg) – signature updated for cancellation propagation - atom.Generate(ctx, posts, cfg) – accepts ctx for future cancellation - syncOutput(ctx, cfg) – rsync subprocesses now use exec.CommandContext - Updated all call sites in tests, cmd/snonux/main.go, and integration tests - All call sites pass context.Background() / context.TODO() All tests pass: go test ./...
2026-04-27Externalize sync targets from hardcoded constants to env/configPaul Buetow
- Added SyncTargets and SyncRemoteDir to internal/config.Config. - Replaced the package-level syncTargets and syncRemoteDir constants in cmd/snonux/sync.go with default values, populated lazily via resolveSyncConfig(). - Accept --sync-targets and --sync-remote-dir CLI flags; fall back to SNONUX_SYNC_TARGETS and SNONUX_SYNC_REMOTE_DIR env vars; then fall back to the previous hardcoded defaults (pi0/pi1, /var/www/html/snonux/).
2026-04-27processor: introduce PostBuilder registry to replace hardcoded switchPaul Buetow
Replace the large, duplicate switch statements in planPost and commitPlan with a PostBuilder interface registered per file extension. - PostBuilder interface: Plan(srcPath, ext) (postPlan, error) and Commit(plan, postDir, id, now) (*post.Post, []string, error) - Per-type builders: txtBuilder, mdBuilder, imageBuilder, audioBuilder. - Each builder self-registers via init() into a map[string]PostBuilder. - Core processor loops are now extension-agnostic, satisfying OCP/DIP. - All existing tests pass.
2026-04-27processor: refactor to two-phase commit for inbox processingPaul Buetow
Introduce postPlan to capture everything validated in Phase 1 before any filesystem mutation occurs. Phase 1 scans the inbox, validates all source files (parses text, markdown, image, audio), checks markdown image claims for conflicts, and collects a plan per item. Phase 2 commits mutations only after every plan is validated: creates post directories, writes assets, persists post.json, and removes sources. If Phase 1 fails (e.g. unsupported file, missing markdown image, claim conflict), no mutations occur and the inbox is left untouched. Roll back the partial post directory if a mutation fails during commit. Also refactor image and audio sub-processors into validation-only and write-only parts (validateImage/writeImageAsset, validateAudio/copyFile) so that Phase 1 is strictly read-only. All existing tests pass.
2026-04-27generator: lazy-init themeSet and navDefs with sync.OncePaul Buetow
2026-04-27Move post.Load constructor before methods in post.goPaul Buetow
2026-04-27processor: reject two markdown files claiming the same inbox imagePaul Buetow
The pre-scan claimedByMarkdown used to mark an image as claimed by any markdown that referenced it, but it did not prevent two different markdown files from referencing the same image. When that happened, the first file processed would copy the image into its post directory and then delete it from the inbox. The second file then failed because the source image was already gone. Fix: make image claiming exclusive. claimedByMarkdown now tracks the owning markdown filename for each claimed image and returns an error immediately during the pre-scan if a conflict is detected. This way no sources are removed and no partial posts are created. Also add tests: - twoMarkdownsClaimingSameImageFails (negative) - duplicateImageClaimsInSameMarkdownAllowed (positive)