Improve bookmark logo variation and documentation screenshot #55

Merged
eleith merged 1 commits from improve-bookmark-logos-and-screenshot into main 2026-10-27 12:59:31 +00:00
10 changed files with 21 additions and 273 deletions

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
---
'@directory/web': patch
---
Vary generated bookmark logo backgrounds by link rather than group, keeping colors stable when titles or groups change.
@@ -116,7 +116,7 @@ describe('prepared bookmark logos with the current Initials renderer', () => {
).toBe('BF');
});
it('keys separate slugs independently while sharing a named group color', () => {
it('uses per-link colors even within the same named group', () => {
const logos = renderBookmarkLogos(
configuration({
photos: { title: 'Photos', group: 'Family' },
@@ -126,7 +126,7 @@ describe('prepared bookmark logos with the current Initials renderer', () => {
expect(Object.keys(logos)).toEqual(['photos', 'backup']);
expect(letters(logos.photos!)).toBe('PH');
expect(letters(logos.backup!)).toBe('BF');
expect(background(logos.photos!)).toBe(background(logos.backup!));
expect(background(logos.photos!)).not.toBe(background(logos.backup!));
});
it('keeps colors stable through group insertion, declaration reordering and accent changes', () => {
@@ -148,6 +148,19 @@ describe('prepared bookmark logos with the current Initials renderer', () => {
for (const id of Object.keys(original)) expect(updated[id]).toBe(original[id]);
});
it('keeps a link color stable through title edits, regrouping and ungrouping', () => {
const original = renderBookmarkLogos(
configuration({ photos: { title: 'Photos', group: 'Family' } })
).photos!;
for (const group of ['Another group', undefined]) {
const updated = renderBookmarkLogos(
configuration({ photos: { title: 'Picture library', ...(group ? { group } : {}) } })
).photos!;
expect(background(updated)).toBe(background(original));
expect(letters(updated)).toBe('PL');
}
});
it('uses a varied flat palette with opaque high-contrast colors and intrinsic 64px dimensions', () => {
const config = configuration(
Object.fromEntries(
@@ -9,8 +9,7 @@ const backgrounds = ['#dbeafe', '#dcfce7', '#fef3c7', '#fce7f3', '#ede9fe', '#cf
export function renderBookmarkLogos(config: DirectoryConfiguration): Record<string, string> {
return Object.fromEntries(
Object.entries(config.links).map(([id, link]) => {
const identity = link.group === undefined ? `link:${id}` : `named:${link.group}`;
const colorIndex = createHash('sha256').update(identity).digest().readUInt32BE(0);
const colorIndex = createHash('sha256').update(`link:${id}`).digest().readUInt32BE(0);
const background = backgrounds[colorIndex % backgrounds.length]!;
const svg = new Avatar(style, {
seed: initialsSeed(link.title, id),
@@ -27,7 +26,6 @@ export function renderBookmarkLogos(config: DirectoryConfiguration): Record<stri
}
function initialsSeed(title: string, id: string): string {
// DiceBear limits seeds to 1,024 Unicode characters and ignores text after @.
const titleSeed = Array.from(title.split('@', 1)[0]!).slice(0, 1024).join('');
if (/\p{L}/u.test(titleSeed)) return titleSeed;
const slugSeed = Array.from(id).slice(0, 1024).join('');
-237
View File
@@ -1,237 +0,0 @@
# yaml-language-server: $schema=../../packages/config/src/config.schema.json
# Local demo only: replace these known credentials before exposing the directory.
# Runtime auth still needs a unique generated AUTH_SECRET and matching ORIGIN/AUTH_URL.
# See demo/README.md for a preview that leaves operator configuration untouched.
version: 1
site:
title: Home Server
description: Useful things running at home.
footer: Something not working? Ask your household maintainer.
appearance:
primary_light_color: '#0f766e'
primary_dark_color: '#5eead4'
auth:
credentials:
username: admin
password: directory
# Reserved example.com destinations are placeholders, not live integrations.
# All bookmarks use generated logos; site branding uses the bundled default.
links:
photos:
title: Photos
url: https://photos.example.com
description: |
Family photos and videos, all in one place.
Install your photo service's mobile app for automatic uploads.
tags: [photos, videos, memories]
group: Photos & files
requires_auth: true
files:
title: Files
url: https://files.example.com
description: Shared documents, school projects and household paperwork.
tags: [documents, sharing, storage]
group: Photos & files
backups:
title: Backups
url: https://backups.example.com
description: |
Check the latest backup status before you need a restore.
Ask your household maintainer for help recovering a file.
tags: [backup, recovery, storage]
group: Photos & files
scans:
title: Paperwork inbox
url: https://scans.example.com
description: Sort recent scans into searchable bills, receipts and warranties.
tags: [scans, documents, receipts]
group: Photos & files
archive:
title: Family history archive
url: https://archive.example.com
description: Old letters, digitized albums and notes about the family tree.
tags: [history, memories, documents]
group: Photos & files
albums:
title: Shared albums
url: https://albums.example.com
description: Choose a photo collection to share with visiting relatives.
tags: [photos, albums, sharing]
group: Photos & files
transfers:
title: File drop
url: https://transfers.example.com
description: Temporary space for large files moving between household devices.
tags: [transfer, sharing, storage]
group: Photos & files
internal_only: true
notebooks:
title: Household notebooks
url: https://notebooks.example.com
description: Shared notes for school, travel plans and everyday reference.
tags: [notes, writing, planning]
group: Photos & files
sync:
title: Device sync status
url: https://sync.example.com
description: Check whether laptop folders have reached the home server.
tags: [sync, devices, storage]
group: Photos & files
internal_only: true
keepsakes:
title: DigitalKeepsakesAndSchoolProjectCollections
url: https://keepsakes.example.com
description: Finished school projects and small creations worth keeping.
tags: [school, archive, memories]
group: Photos & files
music:
title: Music
url: https://music.example.com
description: Albums, playlists and a soundtrack for dinner.
tags: [music, audio, playlists]
group: Entertainment
movies:
title: Movies
url: https://movies.example.com
description: Browse the family movie and television library.
tags: [movies, television, streaming]
group: Entertainment
books:
title: Books
url: https://books.example.com
description: Find your next ebook or audiobook for the commute.
tags: [books, reading, audiobooks]
group: Entertainment
radio:
title: Radio
url: https://radio.example.com
description: Saved station links and recordings from the community radio club.
tags: [radio, audio, recordings]
group: Entertainment
podcasts:
title: Podcast queue
url: https://podcasts.example.com
description: Episodes downloaded for the next long drive.
tags: [podcasts, audio, travel]
group: Entertainment
reading:
title: Weekend reading list
url: https://reading.example.com
description: Saved articles and reading suggestions from around the household.
tags: [reading, articles, bookmarks]
group: Entertainment
requests:
title: Library requests
url: https://requests.example.com
description: Suggest something for the household media collection.
tags: [library, requests, media]
group: Entertainment
requires_auth: true
home-automation:
title: Home automation
url: https://home.example.com
description: |
Lights, room temperatures and everyday routines.
Connect to the home network or VPN before opening this service.
tags: [home, lights, routines]
group: Everyday tools
internal_only: true
recipes:
title: Recipes
url: https://recipes.example.com
description: Favorite meals, shopping lists and this week's dinner plan.
tags: [cooking, meals, shopping]
group: Everyday tools
calendar:
title: Family calendar
url: https://calendar.example.com
description: Appointments, school events and reminders for bin collection.
tags: [calendar, reminders, planning]
group: Everyday tools
groceries:
title: Shopping list
url: https://groceries.example.com
description: Add groceries before the next trip to the shops.
tags: [shopping, groceries, pantry]
group: Everyday tools
weather:
title: Garden weather station
url: https://weather.example.com
description: Local rainfall and temperature readings from the garden sensors.
tags: [weather, garden, sensors]
group: Everyday tools
energy:
title: Energy
url: https://energy.example.com
description: Household electricity trends and daily solar production.
tags: [energy, solar, sensors]
group: Everyday tools
internal_only: true
guides:
title: Workshop guides
url: https://guides.example.com
description: Repair notes and instructions for frequently used tools.
tags: [workshop, repair, guides]
group: Workshop
printer:
title: 3D printer
url: https://printer.example.com
description: Check the current print before starting another job.
tags: [printing, workshop, projects]
group: Workshop
internal_only: true
inventory:
title: Parts inventory
url: https://inventory.example.com
description: Find spare cables, screws and electronic components.
tags: [parts, storage, workshop]
group: Workshop
projects:
title: Works in progress
url: https://projects.example.com
description: Sketches, task lists and progress photos for household projects.
tags: [projects, planning, workshop]
group: Workshop
manuals:
title: Appliance manuals and warranty notes
url: https://manuals.example.com
description: Setup instructions and service records for household appliances.
tags: [manuals, warranties, repair]
group: Workshop
router:
title: Router
url: https://router.example.com
description: Manage the home network; leave changes to your household maintainer.
tags: [network, router, maintenance]
group: Behind the scenes
requires_auth: true
internal_only: true
admin_only: true
monitoring:
title: Server health
url: https://monitoring.example.com
description: Storage capacity, temperatures and service availability.
tags: [monitoring, maintenance, server]
group: Behind the scenes
internal_only: true
admin_only: true
containers:
title: Container console
url: https://containers.example.com
description: Maintenance console for the services running on the home server.
tags: [containers, maintenance, server]
group: Behind the scenes
requires_auth: true
internal_only: true
admin_only: true
dns:
title: Local name service
url: https://dns.example.com
description: Household DNS records and local network filtering settings.
tags: [network, dns, maintenance]
group: Behind the scenes
internal_only: true
admin_only: true
-5
View File
@@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<rect width="64" height="64" rx="16" fill="#0f766e"/>
<path d="M16 30 32 16l16 14v19H36V36h-8v13H16Z" fill="#f0fdfa"/>
<circle cx="32" cy="27" r="3" fill="#0f766e"/>
</svg>

Before

Width:  |  Height:  |  Size: 240 B

-6
View File
@@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64" role="img" aria-labelledby="title">
<title id="title">Files</title>
<rect width="64" height="64" rx="12" fill="#1e3a8a"/>
<path d="M13 24v-6h15l6 6h17v25H13Z" fill="none" stroke="#fff" stroke-width="3" stroke-linejoin="round"/>
<path d="M13 28h38M23 36h18M23 42h12" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 432 B

-6
View File
@@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64" role="img" aria-labelledby="title">
<title id="title">Home automation</title>
<rect width="64" height="64" rx="12" fill="#7c2d12"/>
<path d="m11 29 21-17 21 17M18 25v26h28V25" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
<path d="m34 28-8 11h7l-3 9 10-13h-8Z" fill="#fff"/>
</svg>

Before

Width:  |  Height:  |  Size: 419 B

-7
View File
@@ -1,7 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64" role="img" aria-labelledby="title">
<title id="title">Music</title>
<rect width="64" height="64" rx="12" fill="#581c87"/>
<path d="M27 43V20l22-5v23M27 27l22-5" fill="none" stroke="#fff" stroke-width="3" stroke-linejoin="round"/>
<ellipse cx="21" cy="44" rx="7" ry="5" fill="#fff"/>
<ellipse cx="43" cy="39" rx="7" ry="5" fill="#fff"/>
</svg>

Before

Width:  |  Height:  |  Size: 436 B

-7
View File
@@ -1,7 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64" role="img" aria-labelledby="title">
<title id="title">Photos</title>
<rect width="64" height="64" rx="12" fill="#14532d"/>
<rect x="12" y="15" width="40" height="34" rx="3" fill="none" stroke="#fff" stroke-width="3"/>
<circle cx="40" cy="25" r="4" fill="#fff"/>
<path d="m15 44 12-16 10 12 6-6 6 10Z" fill="#fff"/>
</svg>

Before

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 54 KiB