From f59527c110c3ab259ec8afcff1259ab214a4ca9e Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Mar 2026 10:02:08 -0400 Subject: [PATCH 01/14] donate: follow system theme instead of forcing dark mode (#21) * Initial plan * fix: follow system theme on donate page instead of forcing dark mode Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * style: format code with Prettier and StandardJS This commit fixes the style issues introduced in 04d1db2 according to the output from Prettier and StandardJS. Details: https://github.com/SillyLittleTech/lander/pull/21 * fix: head script uses only system theme, no localStorage, on donate page Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> Co-authored-by: Kiya Rose Ren-Miyakari Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com> --- donate.html | 80 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/donate.html b/donate.html index 83b4c9b..d80ed0a 100644 --- a/donate.html +++ b/donate.html @@ -1,9 +1,26 @@ - + Make a Donation - SillyLittleTech + @@ -294,12 +311,65 @@

Make a Donation

- + - + diff --git a/base.css b/base.css index 12c4927..383c9cd 100644 --- a/base.css +++ b/base.css @@ -1,4 +1,13 @@ /* base.css - shared variables and minimal resets used by all pages */ +/* + * NOTE: The Lexend font used as the primary body font is NOT loaded here. + * Every page that includes base.css MUST load Lexend via tags in its + * (before base.css) to avoid falling back to system fonts: + * + * + * + * + */ :root { --bg-color: #ffffff; --text-color: #1a1a1a; @@ -28,9 +37,9 @@ } body { - /* Primary site font: Slfdreamer (fallbacks provided) */ + /* Primary site font: Lexend (fallbacks provided) */ font-family: - "Slfdreamer", + "Lexend", -apple-system, BlinkMacSystemFont, "Segoe UI", @@ -38,7 +47,7 @@ body { "Helvetica Neue", Arial, sans-serif; - /* Base font size: larger for Slfdreamer legibility */ + /* Base font size tuned for readability */ font-size: 18px; background: var(--bg-color); color: var(--text-color); @@ -59,7 +68,7 @@ body { } } -/* Slfdreamer primary display font */ +/* SLF Dreamer font used by footer copyright */ @font-face { font-family: "Slfdreamer"; src: url("assetlab/faces/Slfdreamer-Regular.ttf") format("truetype"); @@ -167,6 +176,19 @@ footer.site-footer { z-index: 1000; } +/* Keep footer copyright in SLF Dreamer */ +footer.site-footer .footer-copyright { + font-family: + "Slfdreamer", + -apple-system, + BlinkMacSystemFont, + "Segoe UI", + Roboto, + "Helvetica Neue", + Arial, + sans-serif; +} + /* link/button groups baseline */ .links { display: flex; diff --git a/brand.css b/brand.css index cb344c4..be941c7 100644 --- a/brand.css +++ b/brand.css @@ -1,25 +1,113 @@ /* brand.css - overrides and layout specific to brand guidelines page */ -.container.single-column { grid-template-columns: 1fr; max-width:900px; gap:28px; padding:24px; margin: 0 auto; text-align: center } -.brand-hero { display:flex; gap:20px; align-items:center; margin:40px 0; flex-direction:column } -.brand-logo { width:140px; height:140px; object-fit:contain; margin:0 auto } -.brand-section { margin:28px 0 } -.badge-sample { width:160px; margin:8px; display:inline-block } +.container.single-column { + grid-template-columns: 1fr; + max-width: 900px; + gap: 28px; + padding: 24px; + margin: 0 auto; + text-align: center; +} +.brand-hero { + display: flex; + gap: 20px; + align-items: center; + margin: 40px 0; + flex-direction: column; +} +.brand-logo { + width: 140px; + height: 140px; + object-fit: contain; + margin: 0 auto; +} +.brand-section { + margin: 28px 0; +} +.badge-sample { + width: 160px; + margin: 8px; + display: inline-block; +} -.back-link { display: inline-block; margin-bottom: 30px; color: var(--accent-color); text-decoration: none; font-weight: 500 } -.back-link:hover { text-decoration: underline } +.back-link { + display: inline-block; + margin-bottom: 30px; + color: var(--accent-color); + text-decoration: none; + font-weight: 500; +} +.back-link:hover { + text-decoration: underline; +} /* center headings and sections */ -.brand-section h3 { text-align:center } -.brand-section p, .brand-section ul { display:inline-block; text-align:left; max-width:720px } +.brand-section h3 { + text-align: center; +} +.brand-section p, +.brand-section ul { + display: inline-block; + text-align: left; + max-width: 720px; +} /* center codebox */ -pre.codebox { max-width: 820px; margin: 12px auto; text-align: left } +pre.codebox { + max-width: 820px; + margin: 12px auto; + text-align: left; +} /* tabs */ -.tab { padding:6px 10px; border-radius:8px; border:1px solid var(--border-color); background:transparent; color:var(--text-color); cursor:pointer; font-weight:600 } -.tab.active { background: linear-gradient(180deg, var(--accent-color), color-mix(in srgb, var(--accent-color) 82%, black 8%)); color:white; border-color:transparent } +.tab { + padding: 6px 10px; + border-radius: 8px; + border: 1px solid var(--border-color); + background: transparent; + color: var(--text-color); + cursor: pointer; + font-weight: 700; +} +.tab.active { + background: linear-gradient( + 180deg, + var(--accent-color), + color-mix(in srgb, var(--accent-color) 82%, black 8%) + ); + color: white; + border-color: transparent; +} /* codebox */ -pre.codebox { background: var(--card-bg); color: var(--text-color); padding:14px; border-radius:10px; border:1px solid var(--border-color); box-shadow:0 8px 24px rgba(0,0,0,0.06); position:relative; overflow:auto } -button.copy-btn { position:absolute; right:10px; top:10px; background:transparent; color:var(--text-color); border:1px solid var(--border-color); padding:6px 8px; border-radius:6px } -pre.codebox, pre.codebox code { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, 'Roboto Mono', 'Courier New', monospace; font-size:14px } +pre.codebox { + background: var(--card-bg); + color: var(--text-color); + padding: 14px; + border-radius: 10px; + border: 1px solid var(--border-color); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06); + position: relative; + overflow: auto; +} +button.copy-btn { + position: absolute; + right: 10px; + top: 10px; + background: transparent; + color: var(--text-color); + border: 1px solid var(--border-color); + padding: 6px 8px; + border-radius: 6px; + font-weight: 700; +} +/* keep Tech lighter in the brand wordmark */ +.brand-wordmark .tech-thin { + font-weight: 300; +} +pre.codebox, +pre.codebox code { + font-family: + ui-monospace, SFMono-Regular, Menlo, Monaco, "Roboto Mono", "Courier New", + monospace; + font-size: 14px; +} diff --git a/brand.html b/brand.html index 79ee2be..f60fcc6 100644 --- a/brand.html +++ b/brand.html @@ -12,6 +12,12 @@ } catch (e) {} })(); + + + - - +
← Back to Home diff --git a/brand.html b/brand.html index f60fcc6..01216a1 100644 --- a/brand.html +++ b/brand.html @@ -76,44 +76,7 @@ - +
← Back to Home @@ -319,6 +282,8 @@

Licensing & permissions

.replace(/>/g, ">"); } function highlightHtml(s) { + // Input is always the output of makeHtml() — a bounded, machine-generated + // string, never free user input — so ReDoS is not a concern here. let escaped = escapeHtml(s); escaped = escaped.replace( /("[^"]*")/g, @@ -328,8 +293,9 @@

Licensing & permissions

/([a-zA-Z-:]+)(=)/g, '$1$2', ); + // Use greedy [^&]* (not lazy) — no nested quantifiers, no backtracking risk. escaped = escaped.replace( - /(<\/?[a-zA-Z0-9-]+)([^&]*?)(>)/g, + /(<\/?[a-zA-Z0-9-]+)([^&]*)(>)/g, '$1$2$3', ); return escaped; diff --git a/donate.html b/donate.html index 002ec9c..e563639 100644 --- a/donate.html +++ b/donate.html @@ -191,45 +191,7 @@ - - +
← Back to Home diff --git a/index.html b/index.html index b7d2ed9..59954af 100644 --- a/index.html +++ b/index.html @@ -25,44 +25,7 @@ - +
diff --git a/theme.js b/theme.js index cedabf8..f563519 100644 --- a/theme.js +++ b/theme.js @@ -1,5 +1,5 @@ // Simple theme initialization and toggle handling. -// Sets html[data-theme] on load and wires #themeToggle click. +// Sets html[data-theme] on load, injects #themeToggle if absent, and wires click. (function(){ const html = document.documentElement; @@ -29,13 +29,43 @@ return next; } + // Inject the shared theme-toggle button into so pages don't each need + // to duplicate the markup. Any page that already contains #themeToggle keeps + // its own element unchanged. Called only from init(), which itself only runs + // once the DOM is ready, so document.body is always available at this point. + function injectThemeToggleButton(){ + if (!document.body) return null; + const btn = document.createElement('button'); + btn.className = 'theme-toggle'; + btn.id = 'themeToggle'; + btn.setAttribute('aria-label', 'Toggle theme'); + btn.innerHTML = + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''; + document.body.appendChild(btn); + return btn; + } + function init(){ const saved = getSavedTheme(); const theme = saved || detectSystem(); applyTheme(theme); if (!saved) saveTheme(theme); - const btn = document.getElementById('themeToggle'); + let btn = document.getElementById('themeToggle'); + if (!btn) btn = injectThemeToggleButton(); if (btn) btn.addEventListener('click', toggleTheme); } From 4a11e2774e5701480b6924f1e5fff31b24ded7cd Mon Sep 17 00:00:00 2001 From: Kiya Rose Ren-Miyakari Date: Fri, 20 Mar 2026 13:53:47 -0400 Subject: [PATCH 04/14] Create dependabot.yml for version updates Add initial configuration for Dependabot updates. --- .github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..5990d9c --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" From be31691ec2753f4cdd1036cf626c17222b2d7aa8 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 18:01:50 +0000 Subject: [PATCH 05/14] Fix copy button hidden behind codebox on brand page (#29) * Initial plan * Fix: Move copy button inside codebox to fix visibility on brand page Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> Agent-Logs-Url: https://github.com/SillyLittleTech/lander/sessions/95786c2e-8426-4962-9e32-0a5d8b95169d * Fix copy button: solid background, outside scroll container, clean up duplicate CSS rule Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> Agent-Logs-Url: https://github.com/SillyLittleTech/lander/sessions/a3f820f0-13cd-462d-99b7-6f488c044450 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> --- brand.css | 18 +++++++++--------- brand.html | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/brand.css b/brand.css index be941c7..05eb0ff 100644 --- a/brand.css +++ b/brand.css @@ -51,13 +51,6 @@ max-width: 720px; } -/* center codebox */ -pre.codebox { - max-width: 820px; - margin: 12px auto; - text-align: left; -} - /* tabs */ .tab { padding: 6px 10px; @@ -79,6 +72,11 @@ pre.codebox { } /* codebox */ +.codebox-wrapper { + position: relative; + max-width: 820px; + margin: 12px auto; +} pre.codebox { background: var(--card-bg); color: var(--text-color); @@ -86,19 +84,21 @@ pre.codebox { border-radius: 10px; border: 1px solid var(--border-color); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06); - position: relative; overflow: auto; + text-align: left; } button.copy-btn { position: absolute; right: 10px; top: 10px; - background: transparent; + background: var(--card-bg); color: var(--text-color); border: 1px solid var(--border-color); padding: 6px 8px; border-radius: 6px; font-weight: 700; + cursor: pointer; + z-index: 1; } /* keep Tech lighter in the brand wordmark */ .brand-wordmark .tech-thin { diff --git a/brand.html b/brand.html index 01216a1..acaccdb 100644 --- a/brand.html +++ b/brand.html @@ -228,7 +228,7 @@

Badges (raster)

-
+
From 07bd2e53d661601c3d9723a1880e28262ef30853 Mon Sep 17 00:00:00 2001 From: Kiya Rose Ren-Miyakari Date: Fri, 20 Mar 2026 14:02:11 -0400 Subject: [PATCH 06/14] Set package ecosystem to 'npm' in dependabot config --- .github/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5990d9c..5f0889c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,7 +5,7 @@ version: 2 updates: - - package-ecosystem: "" # See documentation for possible values + - package-ecosystem: "npm" # See documentation for possible values directory: "/" # Location of package manifests schedule: interval: "weekly" From db39556a8b55ac8bbaade2169eb85ed0d331489e Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 14:19:54 -0400 Subject: [PATCH 07/14] Fix FOUC on Contact Us page and resolve SonarCloud maintainability warnings (#31) * Initial plan * Fix: add anti-FOUC theme script to apply.html head Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> Agent-Logs-Url: https://github.com/SillyLittleTech/lander/sessions/a98d089c-ab11-4c4b-a4fa-7650d3896cd8 * Fix SonarCloud empty catch block warning in anti-FOUC scripts Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> Agent-Logs-Url: https://github.com/SillyLittleTech/lander/sessions/6f4b51b7-2269-4f71-ae73-973284fcaffc * Fix SonarCloud unused catch binding in anti-FOUC scripts (use optional catch binding) Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> Agent-Logs-Url: https://github.com/SillyLittleTech/lander/sessions/a28f3a6f-996a-4016-8937-3b1ac822baa6 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> --- apply.html | 8 ++++++++ brand.html | 2 +- index.html | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apply.html b/apply.html index 60958cc..9c4d8fa 100644 --- a/apply.html +++ b/apply.html @@ -4,6 +4,14 @@ Apply for a Website - SillyLittleTech + diff --git a/index.html b/index.html index 59954af..590e322 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,7 @@ try { const t = localStorage.getItem("theme"); if (t) document.documentElement.setAttribute("data-theme", t); - } catch (e) {} + } catch { /* localStorage may be unavailable */ } })(); From 26ba128f03fbbe6bce62f42cad8959f70efef790 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 18:30:05 +0000 Subject: [PATCH 08/14] fix: resolve 53 SonarCloud code smells across 6 files (#27) * Initial plan * fix: resolve 53 SonarCloud code smells across brand.css, brand.html, donate.html, index.html, script.js, theme.js Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> Agent-Logs-Url: https://github.com/SillyLittleTech/lander/sessions/c16e496a-1317-4d1b-8e22-e77d44847609 * Changes before error encountered Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> Agent-Logs-Url: https://github.com/SillyLittleTech/lander/sessions/6ab0c607-d2b4-4328-b631-5e9ab7d8bab2 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> --- brand.css | 2 ++ brand.html | 26 ++++++++++++-------------- donate.html | 53 +++++++++++++++++++++++++++-------------------------- index.html | 9 +++------ script.js | 11 ++++++++++- theme.js | 16 ++++++++-------- 6 files changed, 62 insertions(+), 55 deletions(-) diff --git a/brand.css b/brand.css index 05eb0ff..d488b66 100644 --- a/brand.css +++ b/brand.css @@ -78,6 +78,8 @@ margin: 12px auto; } pre.codebox { + max-width: 820px; + margin: 12px auto; background: var(--card-bg); color: var(--text-color); padding: 14px; diff --git a/brand.html b/brand.html index 31e2b8c..b8cb65e 100644 --- a/brand.html +++ b/brand.html @@ -8,8 +8,8 @@ /* ensure theme attribute is present early to avoid FOUC */ (function () { try { const t = localStorage.getItem("theme"); - if (t) document.documentElement.setAttribute("data-theme", t); - } catch { /* localStorage may be unavailable */ } + if (t) document.documentElement.dataset.theme = t; + } catch (e) { console.warn(e); } })(); @@ -88,10 +88,7 @@

Brand guidelines

src="assetlab/raster/newslticon.png" alt="SillyLittleTech logo" class="brand-logo" - onerror=" - this.onerror = null; - this.src = 'assetlab/smallicon.png'; - " + data-fallback="assetlab/smallicon.png" />

@@ -277,31 +274,31 @@

Licensing & permissions

function escapeHtml(s) { return s - .replace(/&/g, "&") - .replace(//g, ">"); + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">"); } function highlightHtml(s) { // Input is always the output of makeHtml() — a bounded, machine-generated // string, never free user input — so ReDoS is not a concern here. let escaped = escapeHtml(s); - escaped = escaped.replace( + escaped = escaped.replaceAll( /("[^"]*")/g, '$1', ); - escaped = escaped.replace( + escaped = escaped.replaceAll( /([a-zA-Z-:]+)(=)/g, '$1$2', ); // Use greedy [^&]* (not lazy) — no nested quantifiers, no backtracking risk. - escaped = escaped.replace( + escaped = escaped.replaceAll( /(<\/?[a-zA-Z0-9-]+)([^&]*)(>)/g, '$1$2$3', ); return escaped; } function highlightMd(s) { - return escapeHtml(s).replace( + return escapeHtml(s).replaceAll( /\[([^\]]+)\]\(([^)]+)\)/g, '[$1]($2)', ); @@ -340,7 +337,7 @@

Licensing & permissions

.querySelectorAll("button.tab") .forEach((b) => b.classList.remove("active")); btn.classList.add("active"); - currentFormat = btn.getAttribute("data-fmt"); + currentFormat = btn.dataset.fmt; render(); }); @@ -364,6 +361,7 @@

Licensing & permissions

copyBtn.textContent = "Copied"; setTimeout(() => (copyBtn.textContent = "Copy"), 1200); } catch (e) { + console.error(e); alert("Copy failed"); } }); diff --git a/donate.html b/donate.html index e563639..b94fa6d 100644 --- a/donate.html +++ b/donate.html @@ -17,13 +17,14 @@ // immediately, without waiting for later scripts to run. try { var theme = - window.matchMedia && - window.matchMedia("(prefers-color-scheme: dark)").matches + globalThis.matchMedia && + globalThis.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; - document.documentElement.setAttribute("data-theme", theme); + document.documentElement.dataset.theme = theme; } catch (e) { - document.documentElement.setAttribute("data-theme", "light"); + console.warn(e); + document.documentElement.dataset.theme = "light"; } })(); @@ -268,15 +269,14 @@

Make a Donation

/>
- + @@ -34,10 +34,7 @@ src="assetlab/raster/newslticon.png" alt="SillyLittleTech logo" class="avatar-img" - onerror=" - this.onerror = null; - this.src = 'assetlab/smallicon.png'; - " + data-fallback="assetlab/smallicon.png" />

Silly Little Tech

diff --git a/script.js b/script.js index 55d8a67..2a8bf44 100644 --- a/script.js +++ b/script.js @@ -2,6 +2,15 @@ document.addEventListener('DOMContentLoaded', () => { debugLog('DOMContentLoaded fired') + // Set up fallback src for images that declare a data-fallback attribute. + document.querySelectorAll('img[data-fallback]').forEach((img) => { + img.addEventListener('error', function () { + if (this.dataset.fallback && this.src !== this.dataset.fallback) { + this.src = this.dataset.fallback + } + }, { once: true }) + }) + // Render links from links.json debugLog('Calling renderLinks') renderLinks('#linksContainer', 'links.json') @@ -165,7 +174,7 @@ function setupAvatarDebugUnlock () { _debugEnabled = true // flush buffer into the visible box const box = getOrCreateDebugBox() - box.textContent = `${_debugBuffer.reverse().join('\n')}\n${box.textContent}` + box.textContent = `${_debugBuffer.toReversed().join('\n')}\n${box.textContent}` _debugBuffer = [] debugLog('Debug mode unlocked (avatar clicked 5x)') } diff --git a/theme.js b/theme.js index f563519..fd2c52d 100644 --- a/theme.js +++ b/theme.js @@ -4,25 +4,25 @@ const html = document.documentElement; function getSavedTheme(){ - try { return localStorage.getItem('theme'); } catch(e) { return null; } + try { return localStorage.getItem('theme'); } catch(e) { console.warn(e); return null; } } function saveTheme(t){ - try{ localStorage.setItem('theme', t); }catch(e){} + try{ localStorage.setItem('theme', t); }catch(e){ console.warn(e); } } function applyTheme(t){ if(!t) return; - html.setAttribute('data-theme', t); + html.dataset.theme = t; } function detectSystem(){ - try{ return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; } - catch(e){ return 'light'; } + try{ return globalThis.matchMedia && globalThis.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; } + catch(e){ console.warn(e); return 'light'; } } function toggleTheme(){ - const current = html.getAttribute('data-theme') || 'light'; + const current = html.dataset.theme || 'light'; const next = current === 'light' ? 'dark' : 'light'; applyTheme(next); saveTheme(next); @@ -72,6 +72,6 @@ if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); else init(); - window.SLT = window.SLT || {}; - window.SLT.theme = { applyTheme, getSavedTheme, detectSystem, toggleTheme }; + globalThis.SLT = globalThis.SLT || {}; + globalThis.SLT.theme = { applyTheme, getSavedTheme, detectSystem, toggleTheme }; })(); From 280936919c2b143aeb94c25b097e0beffc5ec041 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 01:08:22 +0000 Subject: [PATCH 09/14] Add package.json listing all project dependencies (#32) Agent-Logs-Url: https://github.com/SillyLittleTech/lander/sessions/4be40485-ef5d-4df0-a8f7-ba0e3df5456a Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> --- package.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 0000000..e171702 --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "lander", + "version": "1.0.0", + "description": "Lander website for SillyLittleTech — a link-tree style static page with theme toggling and Cloudflare Pages redirects.", + "private": true, + "scripts": { + "start": "serve . --listen 8000", + "lint": "prettier --check .", + "format": "prettier --write ." + }, + "devDependencies": { + "prettier": "^3.5.3", + "serve": "^14.2.4" + } +} From 387b097fbe2b2a3852b984083f889a0e73c5bfa3 Mon Sep 17 00:00:00 2001 From: Kiya Rose Ren-Miyakari Date: Wed, 25 Mar 2026 03:44:43 -0400 Subject: [PATCH 10/14] Create CNAME --- CNAME | 1 + 1 file changed, 1 insertion(+) create mode 100644 CNAME diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..b8f38e5 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +projects.sillylittle.tech \ No newline at end of file From 0cec436f9958646645aa80c06d0c67cdd1e71237 Mon Sep 17 00:00:00 2001 From: Kiya Rose Ren-Miyakari Date: Wed, 25 Mar 2026 16:09:07 -0400 Subject: [PATCH 11/14] Delete CNAME --- CNAME | 1 - 1 file changed, 1 deletion(-) delete mode 100644 CNAME diff --git a/CNAME b/CNAME deleted file mode 100644 index b8f38e5..0000000 --- a/CNAME +++ /dev/null @@ -1 +0,0 @@ -projects.sillylittle.tech \ No newline at end of file From 2e6e76d293b27069d7ce80ca731700281446879f Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Mar 2026 15:16:10 -0400 Subject: [PATCH 12/14] Replace contributor links with Projects page; add floating contributor profile icons (#36) * Initial plan * Modernize links: add projects link, contributor profile icons Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> Agent-Logs-Url: https://github.com/SillyLittleTech/lander/sessions/a574598b-7edf-4eb0-aa1e-5a759150361d * Move contributor icons to contributors.json, load dynamically Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> Agent-Logs-Url: https://github.com/SillyLittleTech/lander/sessions/dfe39997-dff4-4df4-a515-5832beec1d91 * Move contributor icons above links in right section Agent-Logs-Url: https://github.com/SillyLittleTech/lander/sessions/c06585fb-4ad8-402f-bfbe-eb9b2a46e50c Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com> --- contributors.json | 14 ++++++++++++++ index.html | 2 ++ links.json | 9 +++------ script.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ site.css | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 contributors.json diff --git a/contributors.json b/contributors.json new file mode 100644 index 0000000..d8c9df6 --- /dev/null +++ b/contributors.json @@ -0,0 +1,14 @@ +[ + { + "name": "Kiya Rose", + "url": "https://kiya.cat", + "avatar": "https://avatars.githubusercontent.com/u/75678535?v=4", + "label": "Kiya Rose — Portfolio" + }, + { + "name": "Krystal Rose", + "url": "https://enby.fun", + "avatar": "https://avatars.githubusercontent.com/u/32627918?v=4", + "label": "Krystal Rose — Website" + } +] diff --git a/index.html b/index.html index 3ffd3d4..0c45d3f 100644 --- a/index.html +++ b/index.html @@ -76,6 +76,8 @@

Silly Little Tech

+ +
diff --git a/links.json b/links.json index 31cde1a..8c95d2d 100644 --- a/links.json +++ b/links.json @@ -1,10 +1,7 @@ [ { - "title": "Kiya Rose — Portfolio", - "url": "/kiya" - }, - { - "title": "Krystal Rose — Website", - "url": "/krystal" + "title": "Projects", + "url": "https://projects.sillylittle.tech", + "subtitle": "Explore our open-source projects" } ] diff --git a/script.js b/script.js index 2a8bf44..9fcbe44 100644 --- a/script.js +++ b/script.js @@ -15,6 +15,10 @@ document.addEventListener('DOMContentLoaded', () => { debugLog('Calling renderLinks') renderLinks('#linksContainer', 'links.json') + // Render contributor icons from contributors.json + debugLog('Calling renderContributors') + renderContributors('#contributorsContainer', 'contributors.json') + // Render footer from includes/footer.html debugLog('Calling renderFooter') renderFooter('#siteFooter', 'includes/footer.html') @@ -75,6 +79,47 @@ function renderLinks (containerSelector, jsonPath) { }) } +/** + * Fetches a JSON file containing contributor data and renders round profile icon links. + * Each contributor object may have: { name, url, avatar, label } + */ +function renderContributors (containerSelector, jsonPath) { + const container = document.querySelector(containerSelector) + if (!container) return + debugLog(`renderContributors: fetching ${jsonPath}`) + + fetch(jsonPath) + .then((res) => { + if (!res.ok) throw new Error(`Failed to load ${jsonPath}`) + return res.json() + }) + .then((contributors) => { + container.innerHTML = '' + debugLog(`renderContributors: got ${contributors.length} contributors`) + + contributors.forEach((contributor) => { + const anchor = document.createElement('a') + anchor.className = 'contributor-icon' + anchor.href = contributor.url || '#' + anchor.target = '_blank' + anchor.rel = 'noopener noreferrer' + anchor.setAttribute('aria-label', contributor.label || contributor.name || contributor.url || 'Contributor') + + const img = document.createElement('img') + img.src = contributor.avatar || '' + img.alt = contributor.name || '' + + anchor.appendChild(img) + container.appendChild(anchor) + }) + }) + .catch((err) => { + const msg = err?.message ?? 'unknown error' + console.error('Error rendering contributors:', err) + debugLog(`renderContributors error: ${msg}`) + }) +} + /** * Fetches an HTML file and injects its content into the target element. * Falls back to the original static footer markup already in the page if the fetch fails. diff --git a/site.css b/site.css index 510ec3d..03eba6c 100644 --- a/site.css +++ b/site.css @@ -158,6 +158,38 @@ footer.site-footer a { font-size: 14px; } +/* Contributor profile icons — displayed above the links list in the right section */ +.contributor-icons { + display: flex; + flex-direction: row; + gap: 10px; + margin-bottom: 16px; +} +.contributor-icon { + width: 44px; + height: 44px; + border-radius: 50%; + overflow: hidden; + border: 2px solid var(--border-color); + background: var(--card-bg); + display: block; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); + transition: + transform 0.18s ease, + box-shadow 0.18s ease; + text-decoration: none; +} +.contributor-icon:hover { + transform: scale(1.12); + box-shadow: 0 6px 18px rgba(0, 0, 0, 0.2); +} +.contributor-icon img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + @media (max-width: 768px) { .container { grid-template-columns: 1fr; From 9a12752c070e747eab3fc61f658109b85c615d58 Mon Sep 17 00:00:00 2001 From: Kiya Rose Ren-Miyakari Date: Sat, 28 Mar 2026 22:21:32 -0400 Subject: [PATCH 13/14] enhance: better terminology on apply page (#37) Apply page now better serves as a versatile contact us page. The terminology on this page now better serves any possible reason for contact, and is welcoming to projects of all types. --- apply.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apply.html b/apply.html index 9c4d8fa..71a7a44 100644 --- a/apply.html +++ b/apply.html @@ -3,7 +3,7 @@ - Apply for a Website - SillyLittleTech + Have an idea? - SillyLittleTech