Fonts served via server
Build LinkLog Development Image / development-image (push) Successful in 22s
Build LinkLog Development Image / development-image (push) Successful in 22s
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
* Added a high-contrast Red color theme
|
||||
* Brightened the Red theme surfaces and deepened its crimson accents
|
||||
* Allow every user to filter the feed using every available tag or label
|
||||
* Bundle required web fonts during Docker image builds and serve them from LinkLog
|
||||
### Fixed
|
||||
* Fixed element ID conflict on the Admin page so Available Themes load correctly
|
||||
* Positioned new-entry tag checkboxes after their label text
|
||||
|
||||
@@ -13,6 +13,8 @@ RUN pip install --no-cache-dir -r backend/requirements.txt
|
||||
|
||||
COPY backend ./backend
|
||||
COPY frontend ./frontend
|
||||
COPY scripts/download_fonts.py ./scripts/download_fonts.py
|
||||
RUN python scripts/download_fonts.py
|
||||
RUN useradd --create-home --uid 10001 linklog \
|
||||
&& mkdir -p /app/backend/data \
|
||||
&& chown -R linklog:linklog /app
|
||||
|
||||
@@ -76,7 +76,7 @@ Open these URLs:
|
||||
The browser extension requires a backend URL to be entered during setup; it does not assume a default server.
|
||||
|
||||
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.
|
||||
The visible LinkLog brand text uses the Google Foundry `Asset` font when available, with local fallbacks in the Firefox extension.
|
||||
The visible LinkLog brand text uses the Google Foundry `Asset` font. Docker image builds download and bundle Asset, DM Sans, and Space Grotesk under `/static/fonts`, so the web frontend loads fonts from the LinkLog server rather than Google. The Firefox extension uses its bundled assets and local fallback fonts without requesting Google Fonts.
|
||||
|
||||
## Regenerate Logo Assets
|
||||
|
||||
|
||||
@@ -1418,3 +1418,9 @@ I believe tag selection was still working for v0.1.0 - it is still broken
|
||||
|
||||
### Assistant outcome
|
||||
Found the actual regression in the direct-refresh update: `Promise.all([loadUsers(), loadTags()]).then(loadFeed)` passed its results array into the new `selectedTag` parameter. The feed then attempted to call `toLowerCase()` on that array during initialization. Restored the v0.1.0 callback shape with `.then(() => loadFeed())`, retained direct selected-tag refreshes, added a regression assertion, and cache-busted the feed asset to `feed.js?v=12`.
|
||||
|
||||
### User
|
||||
Don't let the frontend and plugin pull from the google foundry but make sure any necessary fonts are served from the linklog server. I would prefer the fonts to be updated at docker image building time.
|
||||
|
||||
### Assistant outcome
|
||||
Removed the web frontend's Google Fonts import and added a Docker build-time font bundling script. Image builds now download pinned Asset, DM Sans, and Space Grotesk files into `frontend/static/fonts`, generate a local `fonts.css`, and serve them through LinkLog at `/static/fonts`. The Firefox extension did not make Google Font requests and continues to use bundled assets with local fallback fonts. A clean image build confirmed all nine local font assets are present.
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
233. tag filter doesn't seem to respond when pressed
|
||||
234. The tag filter still does not allow me to select tags, even though the raw html contains the correct content. Also the user filter and the sort functionality work too
|
||||
235. I believe tag selection was still working for v0.1.0 - it is still broken
|
||||
236. Don't let the frontend and plugin pull from the google foundry but make sure any necessary fonts are served from the linklog server. I would prefer the fonts to be updated at docker image building time.
|
||||
|
||||
## Future entries
|
||||
|
||||
|
||||
@@ -841,6 +841,9 @@ def test_public_and_admin_pages_render_html():
|
||||
assert 'edit-tag-options' in feed_script
|
||||
assert 'new_tags' in feed_script
|
||||
assert 'A link can have at most 10 tags.' in feed_script
|
||||
style_sheet = client.get('/static/style.css').text
|
||||
assert "@import url('/static/fonts/fonts.css');" in style_sheet
|
||||
assert 'fonts.googleapis.com' not in style_sheet
|
||||
|
||||
|
||||
def test_link_submission_posts_to_enabled_mastodon_plugin():
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Copyright © 2026 Olaf Kolkman */
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
@import url('https://fonts.googleapis.com/css2?family=Asset&family=DM+Sans:wght@400;500;600;700&family=Space+Grotesk:wght@500;600;700&display=swap');
|
||||
@import url('/static/fonts/fonts.css');
|
||||
|
||||
:root {
|
||||
--base: #1e1e2e;
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
## Copyright © 2026 Olaf Kolkman
|
||||
## SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from pathlib import Path
|
||||
from urllib.request import urlopen
|
||||
|
||||
|
||||
FONT_SOURCES = {
|
||||
'Asset-Regular.ttf': 'https://fonts.gstatic.com/s/asset/v30/SLXGc1na-mM4cWIm.ttf',
|
||||
'DMSans-Regular.ttf': 'https://fonts.gstatic.com/s/dmsans/v17/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAopxhTg.ttf',
|
||||
'DMSans-Medium.ttf': 'https://fonts.gstatic.com/s/dmsans/v17/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAkJxhTg.ttf',
|
||||
'DMSans-SemiBold.ttf': 'https://fonts.gstatic.com/s/dmsans/v17/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAfJthTg.ttf',
|
||||
'DMSans-Bold.ttf': 'https://fonts.gstatic.com/s/dmsans/v17/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwARZthTg.ttf',
|
||||
'SpaceGrotesk-Medium.ttf': 'https://fonts.gstatic.com/s/spacegrotesk/v22/V8mQoQDjQSkFtoMM3T6r8E7mF71Q-gOoraIAEj7aUUsj.ttf',
|
||||
'SpaceGrotesk-SemiBold.ttf': 'https://fonts.gstatic.com/s/spacegrotesk/v22/V8mQoQDjQSkFtoMM3T6r8E7mF71Q-gOoraIAEj42Vksj.ttf',
|
||||
'SpaceGrotesk-Bold.ttf': 'https://fonts.gstatic.com/s/spacegrotesk/v22/V8mQoQDjQSkFtoMM3T6r8E7mF71Q-gOoraIAEj4PVksj.ttf',
|
||||
}
|
||||
|
||||
FONT_CSS = """@font-face {
|
||||
font-family: 'Asset';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('Asset-Regular.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('DMSans-Regular.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url('DMSans-Medium.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url('DMSans-SemiBold.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('DMSans-Bold.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Space Grotesk';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url('SpaceGrotesk-Medium.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Space Grotesk';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url('SpaceGrotesk-SemiBold.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Space Grotesk';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('SpaceGrotesk-Bold.ttf') format('truetype');
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def main() -> None:
|
||||
target_dir = Path('frontend/static/fonts')
|
||||
target_dir.mkdir(parents=True, exist_ok=True)
|
||||
for filename, url in FONT_SOURCES.items():
|
||||
with urlopen(url, timeout=30) as response:
|
||||
(target_dir / filename).write_bytes(response.read())
|
||||
(target_dir / 'fonts.css').write_text(FONT_CSS, encoding='utf-8')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user