From 4ae184f24c681b3d3376d1f7a8819a60b4d76771 Mon Sep 17 00:00:00 2001 From: Olaf Date: Mon, 24 Aug 2026 22:01:35 +0200 Subject: [PATCH] Add a (simple) logo --- README.md | 7 +++++-- VIBE/CHAT_LOG.md | 18 ++++++++++++++++++ VIBE/PROMPTS.md | 3 +++ backend/app/services/plugin_manager.py | 2 +- backend/tests/test_api.py | 10 ++++++---- backend/tests/test_user_config.py | 2 +- frontend/static/logo.svg | 18 ++++++++++++++++++ frontend/static/profile.js | 4 ++-- frontend/static/style.css | 14 ++++++++++++++ frontend/templates/admin.html | 3 ++- frontend/templates/feed.html | 2 +- frontend/templates/labels.html | 1 + frontend/templates/login.html | 2 +- frontend/templates/user_profile.html | 9 ++++++--- logo.svg | 18 ++++++++++++++++++ webextension/logo.svg | 18 ++++++++++++++++++ webextension/options.css | 9 +++++++++ webextension/options.html | 3 ++- webextension/popup.css | 9 +++++++++ webextension/popup.html | 2 +- 20 files changed, 136 insertions(+), 18 deletions(-) create mode 100644 frontend/static/logo.svg create mode 100644 logo.svg create mode 100644 webextension/logo.svg diff --git a/README.md b/README.md index 23d2b3a..bbc8ac3 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ LinkLog is a Firefox extension and Python web service for saving links with a ti backend/ FastAPI application, services, database, and tests frontend/ Jinja templates and browser-side assets webextension/ Firefox Manifest V3 extension +Logo.svg Source logo artwork used by the web and extension interfaces Dockerfile Backend container image docker-compose.yml App plus Traefik for local proxying REQUIREMENTS.md Product requirements @@ -77,13 +78,15 @@ Open these URLs: The browser extension defaults to `http://localhost:8000`. +The supplied `Logo.svg` is bundled as `frontend/static/logo.svg` for web pages and `webextension/logo.svg` for the Firefox popup and settings page. + Appending a username to the root URL, such as `/alice`, opens that user's public feed and profile information. Configuration APIs require a bearer token returned by the login endpoint. User configuration uses the identity in that token. Plugin administration additionally requires an administrator account; the development `alice` account is seeded as an administrator, while `bob` is a standard user. Users can change their password from the profile page. The current password is required, new passwords must contain at least 8 characters, and the endpoint is `PUT /api/user/password`. -On the profile page, the authenticated username is displayed as read-only. Users can upload a PNG, JPEG, GIF, or WebP avatar up to 2 MB; uploaded files are stored in the persistent data volume and served by the application. Bio and email fields remain empty until the user provides values. Mastodon settings default to the `mastodon.social` instance and the `From my #LinkLog: "` post prefix. +On the profile page, the authenticated username is displayed as read-only. Users can upload a PNG, JPEG, GIF, or WebP avatar up to 2 MB; uploaded files are stored in the persistent data volume and served by the application. Bio and email fields remain empty until the user provides values. Mastodon settings default to the `mastodon.social` instance and the `From my #LinkLog: ` post prefix. ## Run Tests @@ -177,7 +180,7 @@ After logging in, open and save the Mastodon set - **Instance**: hostname or URL such as `mastodon.social` or `https://mastodon.social` - **Access token**: a Mastodon API token with permission to create statuses -- **Post prefix**: text placed immediately before the link; defaults to `From my #LinkLog: "` +- **Post prefix**: text placed immediately before the link; defaults to `From my #LinkLog: ` Enable the plugin from the admin API or the admin page. New links are saved first and then posted to the configured instance at `/api/v1/statuses`. A Mastodon network failure does not undo the saved link. diff --git a/VIBE/CHAT_LOG.md b/VIBE/CHAT_LOG.md index 50b8a7c..ccbd84b 100644 --- a/VIBE/CHAT_LOG.md +++ b/VIBE/CHAT_LOG.md @@ -373,3 +373,21 @@ Create a page where users can add, delete, or edit labels - Labels can be edited ### Assistant outcome Added schema migration 4 with label ownership, authenticated user label CRUD endpoints and a `/labels` management page. Label creators can edit/delete their own labels, non-owners are denied, and administrators can delete any label including another user's labels. Added administrator label listing/deletion controls and regression coverage. The strict backend suite passed with 15 tests. + +### User +The profile page shows in red: "can't access property \"classList\", document.querySelector(...) is null" + +### Assistant outcome +Found that `profile.js` still queried the removed standalone `#admin-link`, while the current hamburger menu uses `#auth-admin-link`. Updated the selector with an optional null guard, bumped the live asset to `profile.js?v=3`, rebuilt/verified the Docker service, and confirmed the profile route and full strict backend suite with 15 passing tests. + +### User +The post prefix is now 'From my #LinkLog: "' make that 'From my #LinkLog: ' + +### Assistant outcome +Removed the trailing double quote from the default Mastodon post prefix in the publisher, profile UI, fallback, tests, and documentation. Removed the stale minified profile artifact and verified Mastodon/profile tests plus the full strict backend suite with 15 passing tests. + +### User +Use the logo.svg in both the plugin as well as on the web page + +### Assistant outcome +Bundled the supplied logo into the web static assets and Firefox extension, replaced text-only headers with accessible logo images, added responsive sizing, and verified all web pages, extension references, scripts, and the strict backend suite. diff --git a/VIBE/PROMPTS.md b/VIBE/PROMPTS.md index fb511c4..9de7ac1 100644 --- a/VIBE/PROMPTS.md +++ b/VIBE/PROMPTS.md @@ -65,6 +65,9 @@ 61. Make the tags filtering case incensitive (but maintain case of tags) 62. Display the date as "2026 June 18 - 20:22" 63. Create a page where users can add, delete, or edit labels - Labels can be edited and deleted by the same user that created them. The administrator can delete any label. +64. The profile page shows in red: "can't access property \"classList\", document.querySelector(...) is null" +65. The post prefix is now 'From my #LinkLog: "' make that 'From my #LinkLog: ' +66. Use the logo.svg in both the plugin as well as on the web page ## Future entries diff --git a/backend/app/services/plugin_manager.py b/backend/app/services/plugin_manager.py index 0f86be7..a711ce8 100644 --- a/backend/app/services/plugin_manager.py +++ b/backend/app/services/plugin_manager.py @@ -4,7 +4,7 @@ from urllib.request import Request, urlopen from backend.app.plugins.base import BasePlugin -DEFAULT_POST_PREFIX = 'From my #LinkLog: "' +DEFAULT_POST_PREFIX = 'From my #LinkLog: ' class DefaultFrontendPlugin(BasePlugin): diff --git a/backend/tests/test_api.py b/backend/tests/test_api.py index 5a14b22..78b92c0 100644 --- a/backend/tests/test_api.py +++ b/backend/tests/test_api.py @@ -234,6 +234,7 @@ def test_logout_revokes_token_and_admin_can_list_plugins(): def test_public_and_admin_pages_render_html(): root_page = client.get('/') assert 'LinkLog' in root_page.text + assert 'src="/static/logo.svg"' in root_page.text assert 'class="menu-toggle"' in root_page.text assert 'id="auth-menu" class="auth-menu hidden"' in root_page.text assert 'id="auth-home-link" href="/">Home' in root_page.text @@ -255,6 +256,7 @@ def test_public_and_admin_pages_render_html(): assert client.get('/login').status_code == 200 login_page = client.get('/login').text assert 'Sign in' in login_page + assert 'src="/static/logo.svg"' in login_page assert 'id="auth-session" class="auth-session hidden"' in login_page assert 'logout.js?v=3' in login_page assert client.get('/admin').status_code == 200 @@ -300,7 +302,7 @@ def test_link_submission_posts_to_enabled_mastodon_plugin(): assert client.put('/api/user/plugins/mastodon', headers=headers, json={ 'instance': base_url, 'access_token': 'test-token', - 'post_prefix': 'From my #LinkLog: "', + 'post_prefix': 'From my #LinkLog: ', }).status_code == 200 assert client.put('/api/admin/plugins/mastodon', headers=headers, json={'enabled': True}).status_code == 200 @@ -315,7 +317,7 @@ def test_link_submission_posts_to_enabled_mastodon_plugin(): assert received['path'] == '/api/v1/statuses' assert received['authorization'] == 'Bearer test-token' assert received['body'] == { - 'status': 'A useful page\nWorth sharing\nFrom my #LinkLog: "https://example.com/useful #python #web', + 'status': 'A useful page\nWorth sharing\nFrom my #LinkLog: https://example.com/useful #python #web', } finally: server.shutdown() @@ -328,12 +330,12 @@ def test_plugin_config_can_be_saved_for_mastodon(): assert client.put('/api/user/plugins/mastodon', headers=headers, json={ 'instance': 'mastodon.social', 'access_token': 'demo-token', - 'post_prefix': 'From my #LinkLog: "', + 'post_prefix': 'From my #LinkLog: ', }).status_code == 200 payload = client.get('/api/user/plugins/mastodon', headers=headers).json() assert payload['instance'] == 'mastodon.social' - assert payload['post_prefix'] == 'From my #LinkLog: "' + assert payload['post_prefix'] == 'From my #LinkLog: ' admin_update = client.put('/api/admin/plugins/mastodon', headers=headers, json={ 'enabled': True, diff --git a/backend/tests/test_user_config.py b/backend/tests/test_user_config.py index 69fbe5d..301a615 100644 --- a/backend/tests/test_user_config.py +++ b/backend/tests/test_user_config.py @@ -34,7 +34,7 @@ def test_user_config_api_and_profile_page(): assert 'name="avatar" type="file"' in page_response.text assert 'name="avatar_url"' not in page_response.text assert 'value="mastodon.social"' in page_response.text - assert 'From my #LinkLog: "' in page_response.text + assert 'value="From my #LinkLog: "' in page_response.text assert 'id="auth-menu" class="auth-menu hidden"' in page_response.text assert 'id="auth-home-link" href="/">Home' in page_response.text assert 'id="auth-profile-link" class="hidden"' in page_response.text diff --git a/frontend/static/logo.svg b/frontend/static/logo.svg new file mode 100644 index 0000000..79df06e --- /dev/null +++ b/frontend/static/logo.svg @@ -0,0 +1,18 @@ + + + + + + + + L + + + + + + LinkLog + + + + diff --git a/frontend/static/profile.js b/frontend/static/profile.js index a14761d..e09e579 100644 --- a/frontend/static/profile.js +++ b/frontend/static/profile.js @@ -5,7 +5,7 @@ const mastodonForm = document.querySelector('#mastodon-form'); const profileLogoutButton = document.querySelector('#logout-button'); const accessToken = localStorage.getItem('linklogAccessToken'); const defaultMastodonInstance = 'mastodon.social'; -const defaultPostPrefix = 'From my #LinkLog: "'; +const defaultPostPrefix = 'From my #LinkLog: '; function authHeaders(includeJson = false) { return { @@ -33,7 +33,7 @@ async function loadProfile() { avatarPreview.classList.remove('hidden'); } if (profile.is_admin) { - document.querySelector('#admin-link').classList.remove('hidden'); + document.querySelector('#auth-admin-link')?.classList.remove('hidden'); } profileLogoutButton.classList.remove('hidden'); } diff --git a/frontend/static/style.css b/frontend/static/style.css index 5ba9dd1..0758131 100644 --- a/frontend/static/style.css +++ b/frontend/static/style.css @@ -84,6 +84,15 @@ body::selection { line-height: 1; } +.site-logo { + display: block; + width: min(260px, 70vw); + height: 58px; + margin-bottom: 12px; + object-fit: contain; + object-position: left center; +} + .site-header p { max-width: 34rem; margin: 14px 0 0; @@ -529,6 +538,11 @@ button:disabled { font-size: 2.35rem; } + .site-logo { + width: min(220px, 68vw); + height: 48px; + } + .header-row { align-items: center; gap: 12px; diff --git a/frontend/templates/admin.html b/frontend/templates/admin.html index b763f87..f65a7b9 100644 --- a/frontend/templates/admin.html +++ b/frontend/templates/admin.html @@ -11,7 +11,8 @@
-

LinkLog Admin

+ +

Admin

Manage users and plugin configuration

diff --git a/frontend/templates/feed.html b/frontend/templates/feed.html index fddf4ae..0738b41 100644 --- a/frontend/templates/feed.html +++ b/frontend/templates/feed.html @@ -11,7 +11,7 @@
-

LinkLog

+

Public link feed

diff --git a/frontend/templates/labels.html b/frontend/templates/labels.html index e5389f8..b99a41c 100644 --- a/frontend/templates/labels.html +++ b/frontend/templates/labels.html @@ -11,6 +11,7 @@
+

Labels

Manage your link labels

diff --git a/frontend/templates/login.html b/frontend/templates/login.html index 87d3c63..0cd9934 100644 --- a/frontend/templates/login.html +++ b/frontend/templates/login.html @@ -11,7 +11,7 @@
-

Sign in

+

Access your LinkLog settings

diff --git a/frontend/templates/user_profile.html b/frontend/templates/user_profile.html index 2014558..0fb5469 100644 --- a/frontend/templates/user_profile.html +++ b/frontend/templates/user_profile.html @@ -10,7 +10,10 @@