You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -19,8 +19,8 @@ Inserting styles into a webpage is easy: I just need to include a link to the CS
19
19
20
20
```scss
21
21
/* components.scss */
22
-
@import'components/header';
23
-
@import'components/footer';
22
+
@import"components/header";
23
+
@import"components/footer";
24
24
```
25
25
26
26
Normally I'd need to publish `components.scss` in order to use it, but I created a Hugo template a while ago that automatically transpiles and publishes all SCSS files. Here's what it looks like, if you're curious.
@@ -38,7 +38,10 @@ Normally I'd need to publish `components.scss` in order to use it, but I created
38
38
So all I need to do to import the component styles into another project is include this line of HTML:
@@ -84,7 +89,7 @@ The only question is how to get the data from the HTML partials into a JavaScrip
84
89
85
90
I was curious to see how the [Zed Agent](https://zed.dev/agentic) would approach this problem without any supervision. I had no intention of using the code that it came up with, but I thought that this would be a good opportunity to experiment with vibe coding. I set Zed to use Claude Sonnet 4 and gave it the following prompt.
86
91
87
-
> **User**\
92
+
> **User**\
88
93
> I want a script, accessible at `/js/ethmarks-components.js`, that defines two Web Components whose content is the same as @header.html and @footer.html. It is absolutely cardinally important that the code be DRY, so you can't just copy the HTMl. Instead, you'll have to do something clever with Hugo that dynamically creates a JS file and publishes it.
89
94
>
90
95
> The end result should be as such:
@@ -97,44 +102,45 @@ I was curious to see how the [Zed Agent](https://zed.dev/agentic) would approach
97
102
98
103
It spent a few minutes reading my existing files, writing new ones, testing if the site built without errors (it often did not), and continued iterating until it had something that worked.
99
104
100
-
Its solution was *really* dumb.
105
+
Its solution was _really_ dumb.
101
106
102
107
It ignored my instruction to create the JS file dynamically and opted instead to make a static JS file that fetches the HTML content from a pseudo-dynamic API that it also created.
103
108
104
109
Here's the JS script it created to fetch that API data.
Here's its Hugo template to create a JSON file containing the header and footer HTML.
@@ -176,11 +182,11 @@ And here are the changes it made to my Hugo config to create the "API" output fo
176
182
177
183
This solution is bad for two reasons.
178
184
179
-
First, it's hideously overcomplicated; as you'll see later, I managed to accomplish the same thing in a single file, with *far* less code, and without messing with the Hugo config.
185
+
First, it's hideously overcomplicated; as you'll see later, I managed to accomplish the same thing in a single file, with _far_ less code, and without messing with the Hugo config.
180
186
181
187
Second, the JS script fetches the data from an API. This introduces an extra network request, slows down the page load, and possibly causes CORS issues.
182
188
183
-
To the Zed Agent's credit, it *did* adhere to my requirements. Its solution does define the Web Components, doesn't interfere with my existing partials, and references the partials in a DRY manner. And the only thing that it cost me (other than eating into my prompt quota) was a few minutes of my time (which I spent reading [Ringworld](https://www.goodreads.com/book/show/61179.Ringworld)).
189
+
To the Zed Agent's credit, it _did_ adhere to my requirements. Its solution does define the Web Components, doesn't interfere with my existing partials, and references the partials in a DRY manner. And the only thing that it cost me (other than eating into my prompt quota) was a few minutes of my time (which I spent reading [Ringworld](https://www.goodreads.com/book/show/61179.Ringworld)).
184
190
185
191
I've come to similar conclusions from my other experiments with vibe coding. If your goal is 'code that works', vibe coding is probably the easiest and most labor-efficient way to achieve that goal. But if you care even slightly about the quality of the code, AI agents tend to take shortcuts and make dumb architectural decisions.
186
192
@@ -230,18 +236,20 @@ As of the time of writing, my template produces the following JS:
The final JS isn't exactly pretty, but the source template (the code whose prettiness is actually important) is simple, concise, and follows best practices.
@@ -294,31 +302,73 @@ Here's a demo page that does exactly that.
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
312
-
<p>Olim erat homo quidam qui in silva habitabat. Hic vir singulis diebus ad fontem ambulabat ut aquam hauriret. Sed quadam die, cum ad fontem pervenit, vidit ibi puellam pulcherrimam capillis aureis. Puella ei dixit se esse nympham fontis et si vellet secum manere, magnam felicitatem ei daturam </p>
313
-
<p>Vir autem, qui uxorem domi habebat et liberos tres, respondit se non posse relinquere familiam suam. Tunc nympha irascens malum carmen cantavit et statim vir in cervum conversus est. Cornua magna ei creverunt et pedes eius ungulae factae sunt.</p>
314
-
<p>Diu per silvam errabat, suam formam humanam desiderans. Aliquando prope domum suam ibat et uxorem liberosque videbat, sed illi eum non cognoscebant. Uxor eius saepe dicebat viris vicinis maritum suum mysterioso modo evanisse.</p>
315
-
<p>Post multos menses, cervus ad fontem rediit et nympham rogavit ut maledicto liberaret eum. Nympha, quae iam paenitentiam egerat crudelitatis suae, respondit se posse eum liberare si aliquis pro eo mortem oppeteret. Cervus tristis factus est, nam neminem noverat qui hoc faceret.</p>
316
-
<p>Sed ecce! Canis fidelis qui eum per totam silvam secutus erat, subito in aquam saluit. Aquae magicae canem statim necaverunt, sed simul cervum in hominem retransformaverunt. Vir domum cucurrit et familiam suam amplexatus est, numquam obliturus sacrificium canis fidelis.</p>
317
-
<p>Postea semper ad fontem revertebatur ut flores ibi poneret in memoriam canis sui, et nympha, quae nunc benigna facta erat, fonti virtutem dedit ut aegros sanaret qui cum fide ad eum venirent.</p>
318
-
</article>
324
+
<article>
325
+
<p>
326
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
327
+
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
328
+
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
329
+
aliquip ex ea commodo consequat.
330
+
</p>
331
+
<p>
332
+
Olim erat homo quidam qui in silva habitabat. Hic vir singulis diebus
333
+
ad fontem ambulabat ut aquam hauriret. Sed quadam die, cum ad fontem
334
+
pervenit, vidit ibi puellam pulcherrimam capillis aureis. Puella ei
335
+
dixit se esse nympham fontis et si vellet secum manere, magnam
336
+
felicitatem ei daturam
337
+
</p>
338
+
<p>
339
+
Vir autem, qui uxorem domi habebat et liberos tres, respondit se non
340
+
posse relinquere familiam suam. Tunc nympha irascens malum carmen
341
+
cantavit et statim vir in cervum conversus est. Cornua magna ei
342
+
creverunt et pedes eius ungulae factae sunt.
343
+
</p>
344
+
<p>
345
+
Diu per silvam errabat, suam formam humanam desiderans. Aliquando
346
+
prope domum suam ibat et uxorem liberosque videbat, sed illi eum non
347
+
cognoscebant. Uxor eius saepe dicebat viris vicinis maritum suum
348
+
mysterioso modo evanisse.
349
+
</p>
350
+
<p>
351
+
Post multos menses, cervus ad fontem rediit et nympham rogavit ut
352
+
maledicto liberaret eum. Nympha, quae iam paenitentiam egerat
353
+
crudelitatis suae, respondit se posse eum liberare si aliquis pro eo
354
+
mortem oppeteret. Cervus tristis factus est, nam neminem noverat qui
355
+
hoc faceret.
356
+
</p>
357
+
<p>
358
+
Sed ecce! Canis fidelis qui eum per totam silvam secutus erat, subito
359
+
in aquam saluit. Aquae magicae canem statim necaverunt, sed simul
360
+
cervum in hominem retransformaverunt. Vir domum cucurrit et familiam
361
+
suam amplexatus est, numquam obliturus sacrificium canis fidelis.
362
+
</p>
363
+
<p>
364
+
Postea semper ad fontem revertebatur ut flores ibi poneret in memoriam
365
+
canis sui, et nympha, quae nunc benigna facta erat, fonti virtutem
366
+
dedit ut aegros sanaret qui cum fide ad eum venirent.
367
+
</p>
368
+
</article>
319
369
</main>
320
370
<ethmarks-footer></ethmarks-footer>
321
-
</body>
371
+
</body>
322
372
</html>
323
373
```
324
374
@@ -328,7 +378,7 @@ And here's what it looks when rendered.
328
378
329
379
It looks almost exactly like a page on my site. All that from just a few lines of HTML!
330
380
331
-
I'm already using this approach for [Thessa](https://ethmarks.github.io/thessa/). The [source code for Thessa](https://github.com/ethmarks/thessa) lives in a separate repo from my personal website, so I couldn't just use my normal Hugo partials. Instead, I used `ethmarks-components.js` to import the header and footer using Web Components. The components on Thessa look exactly the same as the components on my personal website. This is because they *are* exactly the same, right down to the HTML.
381
+
I'm already using this approach for [Thessa](/posts/thessa/). The [source code for Thessa](https://github.com/ethmarks/thessa) lives in a separate repo from my personal website, so I couldn't just use my normal Hugo partials. Instead, I used `ethmarks-components.js` to import the header and footer using Web Components. The components on Thessa look exactly the same as the components on my personal website. This is because they _are_ exactly the same, right down to the HTML.
0 commit comments