-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
244 lines (235 loc) · 23.5 KB
/
Copy pathindex.html
File metadata and controls
244 lines (235 loc) · 23.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>Joshua Trommel</title>
<meta name="description" content="Software engineer in Langley, BC. Building cross-platform apps for web, iOS, macOS, and watchOS.">
<link rel="icon" type="image/svg+xml" href="pwa/favicon.svg">
<link rel="apple-touch-icon" href="pwa/apple-touch-icon.png">
<link rel="canonical" href="https://heyitsmejosh.com">
<meta name="author" content="Joshua Trommel">
<meta name="robots" content="index, follow">
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#000000" media="(prefers-color-scheme: dark)">
<meta property="og:type" content="website">
<meta property="og:url" content="https://heyitsmejosh.com">
<meta property="og:title" content="Joshua Trommel">
<meta property="og:description" content="Software engineer building cross-platform apps for web, iOS, macOS, and watchOS.">
<meta property="og:image" content="https://heyitsmejosh.com/pwa/og-image.jpg">
<meta property="og:locale" content="en_CA">
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"Person","name":"Joshua Trommel","url":"https://heyitsmejosh.com","email":"jatrommel@gmail.com","jobTitle":"Software Engineer","sameAs":["https://github.com/nulljosh","https://letterboxd.com/literallyjordan/"]}
</script>
<link rel="sitemap" type="application/xml" href="/sitemap.xml">
<link rel="stylesheet" href="tokens.css?v=20260911">
<link rel="stylesheet" href="tokens-lovefrom.css?v=20260913">
<script>
const t=localStorage.getItem('theme');if(t)document.documentElement.dataset.theme=t;
</script>
<style>
:root{--bulb:#0074D9;--bulb-deep:#0058a3;--shadow-sm:none;--shadow-md:none;--shadow-lg:none;}
[data-theme="dark"]{--bulb-deep:var(--bulb);--shadow-sm:none;--shadow-md:none;--shadow-lg:none;}
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box;}
body{font-family:var(--font-body);letter-spacing:var(--tracking);font-size:.875rem;line-height:1.7;background:var(--color-bg);color:var(--color-text);-webkit-font-smoothing:antialiased;}
::selection{background:var(--bulb);color:#fff;}
main{max-width:var(--column-width);margin:0 auto;padding:7rem 1.25rem 6rem;}
header{text-align:center;}
.avatar{width:96px;height:96px;margin:0 auto 1.5rem;position:relative;}
.avatar img{width:100%;height:100%;image-rendering:pixelated;animation:bob 6.4s ease-in-out infinite;transform-origin:50% 85%;}
@keyframes bob{
0%,100%{transform:translateY(0) rotate(0deg) scale(1);}
12%{transform:translateY(-3px) rotate(3deg) scale(1.015);}
25%{transform:translateY(1px) rotate(-5deg) scale(1);}
38%{transform:translateY(3px) rotate(-2deg) scale(.99);}
50%{transform:translateY(2px) rotate(4deg) scale(1.01);}
62%{transform:translateY(-2px) rotate(6deg) scale(1);}
75%{transform:translateY(-4px) rotate(1deg) scale(1.015);}
88%{transform:translateY(-1px) rotate(-3deg) scale(.995);}
}
@media (prefers-reduced-motion:reduce){.avatar img{animation:none;}}
header h1{font-size:2.25rem;font-weight:600;letter-spacing:-0.035em;line-height:1.1;}
.updated{color:var(--color-secondary);margin-top:.15rem;}
.bio{margin-top:3.5rem;display:flex;flex-direction:column;gap:.5rem;}
.bio .links{color:var(--color-secondary);}
.bio .quote{font-style:italic;}
.bio .quote cite{display:block;font-style:normal;color:var(--color-secondary);margin-top:.15rem;}
a{color:var(--color-text);text-decoration:underline;text-decoration-color:var(--color-underline);text-underline-offset:3px;transition:text-decoration-color .5s ease-out;}
a:hover{text-decoration-color:var(--color-underline-hover);}
.list{padding-top:3rem;}
.list h2{color:var(--color-secondary);font-size:.875rem;font-weight:500;border-bottom:1px solid var(--color-hairline);padding-bottom:.5rem;}
.list ul{list-style:none;}
.list li{position:relative;}
.list .store{position:absolute;right:0;top:.735rem;color:var(--color-secondary);font-size:.85rem;text-decoration:none;}
.list .store:hover{color:var(--bulb);text-decoration:underline;}
.list li>a:first-child{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;padding:.735rem 5.5rem .735rem 6.75rem;text-decoration:none;border-bottom:1px solid var(--color-hairline);}
.list li:last-child a{border-bottom:none;}
.more summary{list-style:none;cursor:pointer;color:var(--color-secondary);padding:.735rem 0;font-size:.875rem;}
.more summary::-webkit-details-marker{display:none;}
.more[open] summary{border-bottom:1px solid var(--color-hairline);}
.list .year{position:absolute;left:0;top:.735rem;color:var(--color-secondary);}
.list li a:hover .name{text-decoration:underline;}
.list .meta{color:var(--color-secondary);white-space:nowrap;flex-shrink:0;}
@media screen and (max-width:520px){
.list li>a:first-child{padding-left:3rem;}
.list .meta{display:none;}
}
footer{padding-top:4rem;color:var(--color-secondary);display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;}
footer a{color:inherit;}
#theme{background:none;border:none;font:inherit;color:inherit;cursor:pointer;text-decoration:underline;text-decoration-color:var(--color-underline);text-underline-offset:3px;padding:0;}
#theme:hover{text-decoration-color:var(--color-underline-hover);}
#theme{transition:text-decoration-color .5s ease-out;}
</style>
<link rel="manifest" href="/pwa/manifest.webmanifest">
<meta name="apple-mobile-web-app-capable" content="yes">
</head>
<body>
<main>
<header>
<div class="avatar" id="avatar" aria-hidden="true">
<img src="images/memoji-face-2.png" width="96" height="96" alt="">
</div>
<h1>Joshua Trommel</h1>
<div class="updated">Langley, BC</div>
</header>
<div class="bio">
<p>Software engineer. I build apps for web, iOS, macOS, and watchOS. All free. No ads, no data sold.</p>
<p class="links"><a href="https://apps.apple.com/ca/developer/joshua-trommel/id6779522177" target="_blank" rel="noopener">App Store</a> · <a href="https://github.com/nulljosh" target="_blank" rel="noopener">GitHub</a> · <a href="https://letterboxd.com/literallyjordan/" target="_blank" rel="noopener">Letterboxd</a> · <a href="https://trakt.tv/users/nljs" target="_blank" rel="noopener">Trakt</a> · <a href="mailto:jatrommel@gmail.com">jatrommel@gmail.com</a></p>
<p class="quote">"I wish I was you, bro."<cite>my brother, catching me building apps over a beer</cite></p>
</div>
<section class="list" id="work">
<h2>Work</h2>
<ul id="workList">
<li><a href="https://talli.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos,watchos"><span class="year">2026</span><span class="name">Talli, BC disability benefits tracker</span><time class="meta">Web · iOS · macOS · watchOS</time></a><a class="store" href="https://apps.apple.com/app/id6782366555" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://epiphany.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos,watchos"><span class="name">Epiphany, finance dashboard</span><time class="meta">Web · iOS · macOS · watchOS</time></a><a class="store" href="https://apps.apple.com/app/id6779522175" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://sparkjar.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos"><span class="name">Sparkjar, idea forum</span><time class="meta">Web · iOS · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6785162492" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://voxprint.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos"><span class="name">Voxprint, on-device transcription</span><time class="meta">Web · iOS · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6782604262" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://lexly.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos"><span class="name">Lexly, language learning</span><time class="meta">Web · iOS · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6783501611" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://wiretext.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios"><span class="name">Blockframe, wireframe text editor</span><time class="meta">Web · iOS</time></a><a class="store" href="https://apps.apple.com/app/id6794988951" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://curvely.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos"><span class="name">Curvely, graph visualization</span><time class="meta">Web · iOS · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6794988370" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://quotable.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos"><span class="name">Quotestreak, movie-quote trivia</span><time class="meta">Web · iOS · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6804394619" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://wordroot.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos"><span class="name">Wordroot, etymology dictionary</span><time class="meta">Web · iOS · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6794988021" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://inkpress.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="ios,macos"><span class="name">Inkpress, RSS reader</span><time class="meta">iOS · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6787759999" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://bookrank.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos"><span class="name">Bookrank, reading list & summaries</span><time class="meta">Web · iOS · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6792376485" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://litigate.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios"><span class="name">Litigate, litigation planner</span><time class="meta">Web · iOS</time></a><a class="store" href="https://apps.apple.com/app/id6787857503" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://nyc.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos"><span class="name">NYC, Times Square city sim</span><time class="meta">Web · iOS · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6782618198" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://sidewise.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,macos"><span class="name">Sidewise, news aggregator with bias bars</span><time class="meta">Web · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6806028670" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://nimble.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,macos"><span class="name">Nimble, instant-answer search</span><time class="meta">Web · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6807858746" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://toroid.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,macos"><span class="name">Toroid, Game of Life on a torus</span><time class="meta">Web · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6806324937" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://doorstock.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,macos"><span class="name">Doorstock, garage door inventory & jobs</span><time class="meta">Web · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6791106082" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://curbfind.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos,android"><span class="name">Curbfind, classifieds browser</span><time class="meta">Web · iOS · macOS · Android</time></a><a class="store" href="https://apps.apple.com/app/id6809031662" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://healstack.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos"><span class="name">Healstack, health dashboard</span><time class="meta">Web · iOS · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6785764864" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
<li><a href="https://plain.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos"><span class="name">Plain, text editor</span><time class="meta">Web · iOS · macOS</time></a><a class="store" href="https://apps.apple.com/app/id6809841903" target="_blank" rel="noopener" aria-label="View on the App Store">App Store</a></li>
</ul>
<details class="more">
<summary>21 more</summary>
<ul id="workListMore">
<li><a href="https://cadence.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Cadence, commit-history tracker</span><time class="meta">Web</time></a></li>
<li><a href="https://keyrate.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Keyrate, typing test</span><time class="meta">Web</time></a></li>
<li><a href="https://bcgd.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,macos"><span class="name">BC Garage Doors, conversion site & inventory</span><time class="meta">Web · macOS</time></a></li>
<li><a href="https://lucarne.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos"><span class="name">Lucarne, WebKit browser</span><time class="meta">Web · iOS · macOS</time></a></li>
<li><a href="https://numen.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Numen, free-form calculator</span><time class="meta">Web</time></a></li>
<li><a href="https://journal.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Journal, weekly writing</span><time class="meta">Web</time></a></li>
<li><a href="https://homeqi.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Homeqi, home assessment</span><time class="meta">Web</time></a></li>
<li><a href="https://roost.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,ios,macos,android"><span class="name">Roost, worldwide real estate browsing</span><time class="meta">Web · iOS · macOS · Android</time></a></li>
<li><a href="https://seamark.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="npm,web,ios,macos,android,windows,linux"><span class="name">Seamark, chart-to-numbers reader</span><time class="meta">npm · Web · iOS · macOS · Android · Windows · Linux</time></a></li>
<li><a href="https://homeward.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web,android,macos,windows"><span class="name">Homeward, lost pet network</span><time class="meta">Web · Android · macOS · Windows</time></a></li>
<li><a href="https://swing.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Swing, random 1:1 video chat</span><time class="meta">Web</time></a></li>
<li><a href="https://dream.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Dream, dream journal</span><time class="meta">Web</time></a></li>
<li><a href="https://co-stanza.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Co-Stanza, poetry network</span><time class="meta">Web</time></a></li>
<li><a href="https://windgate.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Windgate, guided breathing</span><time class="meta">Web</time></a></li>
<li><a href="https://weather.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Weather, forecast page</span><time class="meta">Web</time></a></li>
<li><a href="https://fieldbook.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Fieldbook, 89 fields with check questions</span><time class="meta">Web</time></a></li>
<li><a href="https://tripwire.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Tripwire, API drift watcher</span><time class="meta">Web</time></a></li>
<li><a href="https://pwnlingo.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Pwnlingo, Duolingo autopilot</span><time class="meta">Web</time></a></li>
<li><a href="https://sieve.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="web"><span class="name">Sieve, inbox triage skill</span><time class="meta">Web</time></a></li>
<li><a href="https://joshuatree.heyitsmejosh.com" target="_blank" rel="noopener" data-tags="os"><span class="name">Joshua Tree, i386 kernel booting on QEMU</span><time class="meta">OS</time></a></li>
<li><a href="https://github.com/nulljosh/labs" target="_blank" rel="noopener" data-tags="source"><span class="name">Labs, small experiments & build-your-owns</span><time class="meta">Source</time></a></li>
</ul>
</details>
</section>
<section class="list" id="writing">
<h2>Writing</h2>
<ul>
<!-- journal-sync:start -->
<li><a href="https://journal.heyitsmejosh.com/2026/09/16/polish/"><span class="year">2026</span><span class="name">Polish</span><time class="meta" datetime="2026-09-16">Sep 16</time></a></li>
<li><a href="https://journal.heyitsmejosh.com/2026/09/15/hunt/"><span class="name">Hunt</span><time class="meta" datetime="2026-09-15">Sep 15</time></a></li>
<li><a href="https://journal.heyitsmejosh.com/2026/09/14/kernel/"><span class="name">Kernel</span><time class="meta" datetime="2026-09-14">Sep 14</time></a></li>
<li><a href="https://journal.heyitsmejosh.com/2026/09/13/foundation/"><span class="name">Foundation</span><time class="meta" datetime="2026-09-13">Sep 13</time></a></li>
<li><a href="https://journal.heyitsmejosh.com/2026/09/12/workflow/"><span class="name">Workflow</span><time class="meta" datetime="2026-09-12">Sep 12</time></a></li>
<li><a href="https://journal.heyitsmejosh.com/2026/09/11/scale/"><span class="name">Scale</span><time class="meta" datetime="2026-09-11">Sep 11</time></a></li>
<li><a href="https://journal.heyitsmejosh.com/2026/09/06/week/"><span class="name">Week</span><time class="meta" datetime="2026-09-06">Sep 06</time></a></li>
<li><a href="https://journal.heyitsmejosh.com/2026/08/24/the-picture-gets-accurate/"><span class="name">Accurate</span><time class="meta" datetime="2026-08-24">Aug 24</time></a></li>
<li><a href="https://journal.heyitsmejosh.com/2026/07/31/a-summer-of-renames/"><span class="name">Renames</span><time class="meta" datetime="2026-07-31">Jul 31</time></a></li>
<li><a href="https://journal.heyitsmejosh.com/2026/05/29/winter-into-spring/"><span class="name">Spring</span><time class="meta" datetime="2026-05-29">May 29</time></a></li>
<!-- journal-sync:end -->
</ul>
</section>
<section class="list" id="experience">
<h2>Experience</h2>
<ul>
<li><a href="#"><span class="year">2024</span><span class="name">Independent software developer, heyitsmejosh.com</span><time class="meta">2024-present</time></a></li>
<li><a href="https://bcgaragedoors.ca" target="_blank" rel="noopener"><span class="year">2020</span><span class="name">Customer service & inventory, Best Choice Garage Doors</span><time class="meta">2020-2026</time></a></li>
<li><a href="https://www.simply.ca" target="_blank" rel="noopener"><span class="year">2018</span><span class="name">Mac specialist, Simply Computing</span><time class="meta">2018-2019</time></a></li>
<li><a href="https://www.macinhome.com" target="_blank" rel="noopener"><span class="year">2017</span><span class="name">Mobile consultant, Macinhome</span><time class="meta">2017-2018</time></a></li>
</ul>
</section>
<section class="list" id="education">
<h2>Education</h2>
<ul>
<li><a href="https://www.sfu.ca" target="_blank" rel="noopener"><span class="year">2027</span><span class="name">Simon Fraser University, BSc Computer Science</span><time class="meta">3 years · possible finance minor</time></a></li>
<li><a href="https://www.kpu.ca" target="_blank" rel="noopener"><span class="year">2026</span><span class="name">Kwantlen Polytechnic University, prerequisite year</span><time class="meta">incl. Pre-Calculus 12</time></a></li>
<li><a href="https://www.bcit.ca" target="_blank" rel="noopener"><span class="name">BCIT, A+ hardware certification coursework</span></a></li>
</ul>
</section>
<footer>
<span><a href="mailto:jatrommel@gmail.com">jatrommel@gmail.com</a> · <a href="tel:+17782014533">778-201-4533</a> · © 2026</span>
<button id="theme" type="button">Toggle theme</button>
</footer>
</main>
<script>
document.getElementById('theme').onclick=()=>{
const root=document.documentElement;
const dark=root.dataset.theme?root.dataset.theme==='dark':matchMedia('(prefers-color-scheme: dark)').matches;
root.dataset.theme=dark?'light':'dark';
localStorage.setItem('theme',root.dataset.theme);
};
const avatar=document.getElementById('avatar');
if(avatar&&!matchMedia('(prefers-reduced-motion: reduce)').matches){
avatar.querySelector('img').style.animationDelay=(-Math.random()*6.4)+'s';
}
// New repos with a homepage set show up here automatically, no manual <li> needed.
// Curated entries above stay for SEO/no-JS; this only appends what's missing.
async function syncGithubRepos(){
const list=document.getElementById('workListMore');
if(!list) return;
const known=new Set([...document.querySelectorAll('#workList a[href],#workListMore a[href]')].map(a=>a.href.replace(/\/$/,'')));
try{
const res=await fetch('https://api.github.com/users/nulljosh/repos?per_page=100&sort=updated');
if(!res.ok) return;
const repos=await res.json();
for(const r of repos){
if(r.fork||!r.homepage) continue;
const href=r.homepage.replace(/\/$/,'');
if(known.has(href)) continue;
known.add(href);
const li=document.createElement('li');
const a=document.createElement('a');
a.href=r.homepage; a.target='_blank'; a.rel='noopener';
a.dataset.tags='web';
const name=document.createElement('span');
name.className='name';
name.textContent=r.description?`${r.name}, ${r.description.replace(/\.$/,'').toLowerCase()}`:r.name;
const meta=document.createElement('time');
meta.className='meta'; meta.textContent='Web';
a.append(name,meta);
li.append(a);
list.append(li);
}
}catch(e){/* offline or rate-limited, curated list still stands */}
}
syncGithubRepos();
</script>
<script>if('serviceWorker' in navigator)addEventListener('load',()=>navigator.serviceWorker.register('/sw.js'));</script>
</body>
</html>