Browse Source

Links

master
David Larlet 2 months ago
parent
commit
1b12b20a77
Signed by: David Larlet <david@larlet.fr> GPG Key ID: 3E2953A359E7E7BD

+ 254
- 0
cache/2024/140458968f9f7da7d14e181d0a80e799/index.html View File

@@ -0,0 +1,254 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="en">
<!-- Has to be within the first 1024 bytes, hence before the `title` element
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>The Expanding Dark Forest and Generative AI (archive) — David Larlet</title>
<meta name="description" content="Publication mise en cache pour en conserver une trace.">
<!-- That good ol' feed, subscribe :). -->
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
<!-- Generated from https://realfavicongenerator.net/ such a mess. -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
<link rel="manifest" href="/static/david/icons2/site.webmanifest">
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
<meta name="msapplication-TileColor" content="#f7f7f7">
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
<meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
<!-- Is that even respected? Retrospectively? What a shAItshow…
https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/ -->
<meta name="robots" content="noai, noimageai">
<!-- Documented, feel free to shoot an email. -->
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<script>
function toggleTheme(themeName) {
document.documentElement.classList.toggle(
'forced-dark',
themeName === 'dark'
)
document.documentElement.classList.toggle(
'forced-light',
themeName === 'light'
)
}
const selectedTheme = localStorage.getItem('theme')
if (selectedTheme !== 'undefined') {
toggleTheme(selectedTheme)
}
</script>

<meta name="robots" content="noindex, nofollow">
<meta content="origin-when-cross-origin" name="referrer">
<!-- Canonical URL for SEO purposes -->
<link rel="canonical" href="https://maggieappleton.com/ai-dark-forest">

<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">


<article>
<header>
<h1>The Expanding Dark Forest and Generative AI</h1>
</header>
<nav>
<p class="center">
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="https://maggieappleton.com/ai-dark-forest" title="Lien vers le contenu original">Source originale</a>
<br>
Mis en cache le 2024-02-19
</p>
</nav>
<hr>
<div class="AssumedAudience__AssumedAudienceContainer-gnzma-0 LlqKU"><span class="label">Assumed Audience</span><div><p>People who have heard of GPT-3 / ChatGPT, and are vaguely following the
advances in machine learning, large language models, and image generators.
Also people who care about making the web a flourishing social and
intellectual space.</p></div></div>
<div class="Spacer-zsy3ll-0 jLPklF"></div>
<!-- -->
<p class="IntroParagraph-l306ci-0 hlDXQj"><p>The <span aria-expanded="false"><div class="InternalTooltipLink__StyledContainer-sc-11bupup-1 eqmyTL"><a href="/cozy-web" class="InternalTooltipLink__StyledLink-sc-11bupup-2 hvOxza"><span>dark forest theory</span></a></div></span> of the web points to the increasingly life-like but life-less state of being online.<aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="1" class="margin-toggle footnote-number"></label><input type="checkbox" id="1" class="margin-toggle"><span class="footnote"><span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://onezero.medium.com/the-dark-forest-theory-of-the-internet-7dc3e68a7cb1" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Dark Forest</span></a></div></span> <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://onezero.medium.com/the-dark-forest-theory-of-the-internet-7dc3e68a7cb1" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Theory of</span></a></div></span> <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://onezero.medium.com/the-dark-forest-theory-of-the-internet-7dc3e68a7cb1" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>the Internet</span></a></div></span> by Yancey Strickler</span></aside> Most open and publicly available spaces on the web are overrun with bots, advertisers, trolls, data scrapers, clickbait, keyword-stuffing “content creators,” and algorithmically manipulated junk.</p></p>
<p>It's like a dark forest that seems eerily devoid of human life – all the living creatures are hidden beneath the ground or up in trees. If they reveal themselves, they risk being attacked by automated predators.</p>
<p>Humans who want to engage in informal, unoptimised, personal interactions have to hide in closed spaces like invite-only Slack channels, Discord groups, email newsletters, small-scale blogs, and <span aria-expanded="false"><div class="InternalTooltipLink__StyledContainer-sc-11bupup-1 eqmyTL"><a href="/garden-history" class="InternalTooltipLink__StyledLink-sc-11bupup-2 hvOxza"><span>digital gardens</span></a></div></span>. Or make themselves <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.ribbonfarm.com/2010/07/26/a-big-little-idea-called-legibility/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>illegible</span></a></div></span> and algorithmically incoherent in public venues.</p>
<!-- -->
<figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/cozyweb.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/cozyweb-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/cozyweb-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/cozyweb-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/cozyweb-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/cozyweb-1800.jpg 1800w" alt="An illustration of layers of the web: the dark forest on top, followed by layers of cozyweb holes where people hide away from bots and ad scavengers" width="1000px" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 daiAzl"></figure>
<p>That dark forest is about to <div style="transform: scaleX(1.85); display: inline-flex; margin: 0px 2.2rem;">expand</div>. Large Language Models (LLMs) that can instantly generate coherent swaths of human-like text have just joined the party.</p>
<!-- -->
<p>Over the last six months, we've seen a flood of LLM copywriting and content-generation products come out: <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.jasper.ai/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Jasper</span></a></div></span>, <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.gomoonbeam.com/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Moonbeam</span></a></div></span>, <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.copy.ai/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Copy.ai</span></a></div></span>, and <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://anyword.com/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Anyword</span></a></div></span> are just a few. They're designed to pump out advertising copy, blog posts, emails, social media updates, and marketing pages. And they're <em>really</em> good at it.<aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="2" class="margin-toggle footnote-number"></label><input type="checkbox" id="2" class="margin-toggle"><span class="footnote">Primarily because <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://en.wikipedia.org/wiki/GPT-3" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>GPT-3</span></a></div></span> which powers many of these products was specifically trained on text from the web. It's intimately familiar with the style of language we use online.</span></aside></p>
<p>These models became competent copywriters much faster than people expected – too fast for us to fully process the implications. Many people had their come-to-Jesus moment a few weeks ago when OpenAI released <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://openai.com/blog/chatgpt/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>ChatGPT</span></a></div></span>, a slightly more capable version of GPT-3 with an accessible chat-bot style interface. <aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="3" class="margin-toggle footnote-number"></label><input type="checkbox" id="3" class="margin-toggle"><span class="footnote">They're calling it GPT-3.5. It's the same model with human <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://huggingface.co/blog/rlhf" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>reinforcement learning</span></a></div></span> layered on top.</span></aside> The <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://twitter.com/elonmusk/status/1599128577068650498?s=20&amp;t=MgaSdgsaF0uU1lITCVPghw" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>collective</span></a></div></span> <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://twitter.com/volodarik/status/1600854935515844610?s=20&amp;t=MgaSdgsaF0uU1lITCVPghw" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>shock</span></a></div></span> and <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://twitter.com/yu_angela/status/1599808692085743616?s=20&amp;t=MgaSdgsaF0uU1lITCVPghw" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>awe</span></a></div></span> <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://twitter.com/levie/status/1599156293050433536?s=20&amp;t=MgaSdgsaF0uU1lITCVPghw" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>reaction</span></a></div></span> made clear how few people had been tracking the progress of these models.</p>
<p>To complicate matters, language models are not the only mimicry machines gathering speed right now. Image generators like <!-- --><span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.midjourney.com/home/?callbackUrl=/app/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Midjourney</span></a></div></span>, <!-- --><span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://openai.com/dall-e-2/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>DALL-E</span></a></div></span>, and <!-- --><span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://en.wikipedia.org/wiki/Stable_Diffusion" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Stable Diffusion</span></a></div></span> have been on a year-long sprint. In January they could barely render a low-resolution, disfigured human face. By the autumn they reliably produced images indistinguishable from the work of human photographers and illustrators.<!-- --></p>
<div class="TwoColumn__TwoColumnContainer-sc-2qlq9z-0 ePKlxc"><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/mj8.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/mj8-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/mj8-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/mj8-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/mj8-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/mj8-1800.jpg 1800w" alt="..." width="100%" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 iGepOK"></figure><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/mj1.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/mj1-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/mj1-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/mj1-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/mj1-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/mj1-1800.jpg 1800w" alt="..." width="100%" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 iGepOK"></figure><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/mj7.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/mj7-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/mj7-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/mj7-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/mj7-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/mj7-1800.jpg 1800w" alt="..." width="100%" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 iGepOK"></figure><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/mj3.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/mj3-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/mj3-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/mj3-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/mj3-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/mj3-1800.jpg 1800w" alt="..." width="100%" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 iGepOK"></figure><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/mj9.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/mj9-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/mj9-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/mj9-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/mj9-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/mj9-1800.jpg 1800w" alt="..." width="100%" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 iGepOK"></figure><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/mj4.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/mj4-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/mj4-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/mj4-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/mj4-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/mj4-1800.jpg 1800w" alt="..." width="100%" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 iGepOK"></figure></div>
<aside class="Typography__Subtext-sc-1dhc7go-6 cHqTEw">Images I generated with Midjourney's V4 model</aside>
<!-- -->
<p><a href="#a-generated-web">
<h2 id="a-generated-web" class="Typography__Title2-sc-1dhc7go-1 eFwLIG">A Generated Web</h2></p>
<p></a></p>
<p>There's a swirl of optimism around how these models will save us from a suite of boring busywork: writing formal emails, internal memos, technical documentation, marketing copy, product announcement, advertisements, cover letters, and even negotiating with medical <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://twitter.com/StuartBlitz/status/1602834224284897282" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>insurance companies</span></a></div></span>.</p>
<p>But we'll also need to reckon with the trade-offs of making insta-paragraphs and 1-click cover images. These new models are poised to flood the web with generic, generated content.</p>
<p>You thought the first page of Google was bunk before? You haven't seen Google where SEO optimizer bros pump out billions of perfectly coherent but predictably dull informational articles for every longtail keyword combination under the sun.</p>
<p>Marketers, influencers, and growth hackers will set up <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://zapier.com/apps/openai/integrations" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>OpenAI → Zapier</span></a></div></span> pipelines that auto-publish a relentless and impossibly banal stream of LinkedIn #MotivationMonday posts, “engaging” tweet <span role="img">🧵</span> threads, Facebook outrage monologues, and corporate blog posts.</p>
<p>It goes beyond text too: <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://twitter.com/SamRo/status/1605919856808714240?s=20&amp;t=QB-eYoISuymlqbHFFDnrWw" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>video essays on YouTube</span></a></div></span>, TikTok clips, podcasts, slide decks, and Instagram stories can all be generated by <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://runwayml.com/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>patchworking</span></a></div></span> together ML systems. And then <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://byautomata.io/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>regurgitated</span></a></div></span> for each medium.</p>
<p>We're about to drown in a sea of pedestrian takes. An explosion of noise that will drown out any signal. Goodbye to finding original human insights or authentic connections under that pile of cruft.</p>
<p>Many people will say we already live in this reality. We've already become skilled at sifting through unhelpful piles of “optimised content” designed to gather clicks and advertising impressions.</p>
<p>4chan proposed <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.theatlantic.com/technology/archive/2021/08/dead-internet-theory-wrong-but-feels-true/619937/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>dead internet theory</span></a></div></span> years ago: that most of the internet is “empty and devoid of people” and has been taken over by artificial intelligence. A milder version of this theory is simply that we're overrun <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://nymag.com/intelligencer/2018/12/how-much-of-the-internet-is-fake.html" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>with bots</span></a></div></span>. Most of us take that for granted at this point.</p>
<p>But I think the sheer volume and scale of what's coming will be meaningfully different. And I think we're unprepared. Or at least, I am.</p>
<hr>
<p><a href="#passing-the-reverse-turing-test"><h2 id="passing-the-reverse-turing-test" class="Typography__Title2-sc-1dhc7go-1 eFwLIG">Passing the Reverse Turing Test</h2></a></p>
<p>Our new challenge as little snowflake humans will be to prove we aren't language models. It's the reverse <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://en.wikipedia.org/wiki/Turing_test" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>turing test</span></a></div></span>.</p>
<div class="TweetEmbed__TweetContainer-sc-1j7oyq8-0 dYplAO tweet"><div></div></div>
<div class="TweetEmbed__TweetContainer-sc-1j7oyq8-0 dYplAO tweet"><div></div></div>
<p>After the forest expands, we will become deeply sceptical of one another's <em>realness</em>. Every time you find a new favourite blog or Twitter account or Tiktok personality online, you'll have to ask: Is this really a whole human with a rich and complex life like mine? Is there a <em>being</em> on the other end of this web interface I can form a relationship with?<aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="4" class="margin-toggle footnote-number"></label><input type="checkbox" id="4" class="margin-toggle"><span class="footnote">“Relationship” in the holistic sense – friend, acquaintance, pen pal, intellectual interlocutor, frenemy, drinking buddy, and sure, maybe a lover.</span></aside></p>
<p>Before you continue, pause and consider: How would <em>you</em> prove you're not a language model generating predictive text? What special human tricks can you do that a language model can't?</p>
<h3 id="1-triangulate-objective-reality" class="Typography__Title3-sc-1dhc7go-3 jIUqxb">1. Triangulate objective reality</h3>
<p>As language models become increasingly capable and impressive, we should remember they are, at their core, linguistic <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.datacamp.com/blog/a-beginners-guide-to-gpt-3#:~:text=Language%20modeling%20is,predicting%20word%20sequences." class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>prediction systems</span></a></div></span>. They cannot (yet) reason like a human.</p>
<p>They do not have beliefs based on evidence, claims, and principles. They cannot consult external sources and run experiments against objective reality. They cannot go outside and touch grass.</p>
<p>In short, they do not have access to the same shared reality we do. They do not have embodied experiences, and cannot sense the world as we can sense it; they don't have vision, sound, taste, or touch. They cannot feel emotion or tightly hold a coherent set of values. They are not part of cultures, communities, or histories.</p>
<p>They are a language model in a box. If a historical event, fact, person, or concept wasn't part of their training data, they can't tell you about it. They don't know about events that happened after a certain cutoff date. <aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="5" class="margin-toggle footnote-number"></label><input type="checkbox" id="5" class="margin-toggle"><span class="footnote">Currently 2021 for GPT-3 / ChatGPT, but we can expect that to regularly update as new models are trained</span></aside></p>
<p>I found Murray Shanahan's paper on <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="http://arxiv.org/abs/2212.03551" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Talking About Large Language Models</span></a></div></span> (2022) full of helpful reflections on this point:</p>
<figure><blockquote class="BlockquoteCitation__Blockquote-sc-15uv93b-1 jMOCbH"><p><p>Humans are members of a community of language-users inhabiting a shared world, and this primal fact makes them essentially different to large language models. We can consult the world to settle our disagreements and update our beliefs. We can, so to speak, “triangulate” on objective reality.</p></p><figcaption><cite class="BlockquoteCitation__Cite-sc-15uv93b-0 bcodDR"><span>Murray Shanahan – </span><a href="http://arxiv.org/abs/2212.03551">Talking About Large Language Models</a></cite></figcaption></blockquote></figure>
<p>This leaves us with some low-hanging fruit for humanness. We can tell richly detailed stories grounded in our specific contexts and cultures: place names, sensual descriptions, local knowledge, and, well the <!-- --><em>je ne sais quoi</em> of being alive. Language models can decently mimic this style of writing but most don't without extensive prompt engineering. They stick to generics. They hedge. They leave out details. They have trouble maintaining a coherent sense of self over thousands of words.</p>
<p>Hipsterism and recency bias will help us here. Referencing obscure concepts, friends who are real but not famous, niche interests, and recent events all make you plausibly more human.<aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="6" class="margin-toggle footnote-number"></label><input type="checkbox" id="6" class="margin-toggle"><span class="footnote">This feels eerily like a hostage holding up yesterday's newspaper to prove they are actively in danger. Perhaps a premonition.</span></aside></p>
<h3 id="2-be-original-critical-and-sophisticated" class="Typography__Title3-sc-1dhc7go-3 jIUqxb">2. Be original, critical, and sophisticated</h3>
<p>Easier said than done, but one of the best ways to prove you're not a predictive language model is to demonstrate critical and sophisticated thinking.</p>
<p>Language models spit out text that sounds like a B+ college essay. Coherent, seemingly comprehensive, but never truly insightful or original (at least for now).</p>
<p>In a repulsively evocative metaphor, they engage in “<span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://en.wikipedia.org/wiki/The_Human_Centipede_(First_Sequence)" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>human centipede</span></a></div></span> epistemology.”<aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="7" class="margin-toggle footnote-number"></label><input type="checkbox" id="7" class="margin-toggle"><span class="footnote">I found this phrase via Twitter, but posted from a private account so I won't cite the original author.</span></aside> Language models regurgitate text from across the web, which some humans read and recycle into "original creations," which then become fodder to train other language models, and around and around we go recycling generic ideas and arguments and tropes and ways of thinking.</p>
<p>Hard exiting out of this cycle requires coming up with unquestionably original thoughts and theories. It means seeing and synthesising patterns across a broad range of sources: books, blogs, cultural narratives served up by media outlets, conversations, podcasts, lived experiences, and market trends. We can observe and analyse a much fuller range of inputs than bots and generative models can.</p>
<p>It will raise the stakes for everyone. As both consumers of content and creators of it, we'll have to foster a greater sense of critical thinking and scepticism.</p>
<p>This all sounds a bit rough, but there's a lot of hope in this vision. In a world of automated intelligence, our goalposts for intelligence will shift. We'll raise our quality bar for what we expect from humans. When a machine can pump out a great literature review or summary of existing work, there's no value in a person doing it.</p>
<h3 id="3-develop-creative-language-quirks-dialects-memes-and-jargon" class="Typography__Title3-sc-1dhc7go-3 jIUqxb">3. Develop creative language quirks, dialects, memes, and jargon</h3>
<p>The linguist <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://en.wikipedia.org/wiki/Ferdinand_de_Saussure" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Ferdinand de Saussure</span></a></div></span> argued there are two kinds of language:</p>
<ul>
<li><strong>La langue</strong> is the formal concept of language. These are words we print in the dictionary, distribute via educational institutions, and reprimand one another for getting it wrong.</li>
<li><strong>La parole</strong> is the speech of everyday life. These are the informal, diverse, and creative speech acts we perform in conversations, social gatherings, and text to the group WhatsApp. This is where language evolves.</li>
</ul>
<p>We have designed a system that automates a standardised way of writing. We have codified <!-- --><em>la langue</em> at a specific point in time.</p>
<p>What we have left to play with is <em>la parole</em>. No language model will be able to keep up with the pace of weird internet lingo and memes. I expect we'll lean into this. Using neologisms, jargon, euphemistic emoji, unusual phrases, ingroup dialects, and memes-of-the-moment will help signal your humanity.</p>
<p>Not unlike teenagers using language to subvert their elders, or oppressed communities developing dialects that allow them to safely communicate amongst themselves.</p>
<h3 id="4-consider-institutional-verification" class="Typography__Title3-sc-1dhc7go-3 jIUqxb">4. Consider institutional verification</h3>
<p>This solution feels the least interesting. We're already hearing rumblings of how “verification” by centralised institutions or companies might help us distinguish between meat brains and metal brains.</p>
<p>The idea is something like this: you show up in person to register your online accounts or domains. You then get some kind of special badge or mark online legitimising you as a Real Human. It may or may not be on the blockchain somehow.</p>
<p>Google might look something like this:</p>
<figure class="ImageFrame__Container-sc-1c93cul-0 jlxTrp"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/human_google.jpg" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/human_google-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/human_google-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/human_google-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/human_google-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/human_google-1800.jpg 1800w" alt="Google search results showing a 'certified human' badge on some items" width="1300px" class="ImageFrame__StyledImageFrame-sc-1c93cul-1 dlXCP"></figure>
<p>The whole thing seems fraught with problems, susceptible to abuse, and ultimately impractical. Would it even be the web if everyone knew you were really a dog?</p>
<!-- -->
<figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/Internet_dog.jpeg" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/Internet_dog-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/Internet_dog-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/Internet_dog-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/Internet_dog-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/Internet_dog-1800.jpg 1800w" alt="The original internet dog meme: 'On the internet, no one knows you're a dog'" width="460px" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 klXNGD"><figcaption>The original internet dog meme: 'On the internet, no one knows you're a dog'</figcaption></figure>
<h3 id="5-show-up-in-meatspace" class="Typography__Title3-sc-1dhc7go-3 jIUqxb">5. Show up in meatspace</h3>
<!-- -->
<p>The final edge we have over language models is that we can prove we're real humans by showing up IRL with our real human bodies. We can arrange to meet Twitter mutuals offline over coffee. We can organise meetups and events and conferences and unconferences and hangouts and pub nights.</p>
<p>In <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.fortressofdoors.com/ai-markets-for-lemons-and-the-great-logging-off/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Markets for Lemons and the Great Logging Off</span></a></div></span>, Lars Doucet proposed several knock-on effects from this offline-first future. We might see increased <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.fortressofdoors.com/ai-markets-for-lemons-and-the-great-logging-off/#:~:text=a%20resurgence%20and%20even%20fetishization%20of%20explicitly%20%22offline%22%20culture%2C%20where%20the%20%22Great%20Logging%20Off%22%20becomes%20literal" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>fetishisation</span></a></div></span> of anti-screen culture, as well as <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.fortressofdoors.com/ai-markets-for-lemons-and-the-great-logging-off/#:~:text=Seventh%2C%20real,amenities%20are%20available" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>real estate</span></a></div></span> price increases in densely populated areas.</p>
<p>For the moment we can still check humanness over Zoom, but live video generation is getting good enough that I don't think that defence will last long.</p>
<p>There are, of course, many people who can't move to an offline-first life; people with physical disabilities. People who live in remote, rural places. People with limited time and caretaking responsibilities for the very young or the very old. They will have a harder time verifying their humanness online. I don't have any grand ideas to help solve this, but I hope we find better solutions than my paltry list.</p>
<p>As the forest grows darker, noisier, and less human, I expect to invest more time in in-person relationships and communities. And while I love meatspace, this still feels like a loss.</p>
</article>


<hr>

<footer>
<p>
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
</svg> Suivre</a> •
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
</svg> Pro</a> •
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
</svg> Email</a> •
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
</svg> Légal</abbr>
</p>
<template id="theme-selector">
<form>
<fieldset>
<legend><svg class="icon icon-brightness-contrast">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
</svg> Thème</legend>
<label>
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
</label>
<label>
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé
</label>
<label>
<input type="radio" value="light" name="chosen-color-scheme"> Clair
</label>
</fieldset>
</form>
</template>
</footer>
<script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
<script>
function loadThemeForm(templateName) {
const themeSelectorTemplate = document.querySelector(templateName)
const form = themeSelectorTemplate.content.firstElementChild
themeSelectorTemplate.replaceWith(form)

form.addEventListener('change', (e) => {
const chosenColorScheme = e.target.value
localStorage.setItem('theme', chosenColorScheme)
toggleTheme(chosenColorScheme)
})

const selectedTheme = localStorage.getItem('theme')
if (selectedTheme && selectedTheme !== 'undefined') {
form.querySelector(`[value="${selectedTheme}"]`).checked = true
}
}

const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
window.addEventListener('load', () => {
let hasDarkRules = false
for (const styleSheet of Array.from(document.styleSheets)) {
let mediaRules = []
for (const cssRule of styleSheet.cssRules) {
if (cssRule.type !== CSSRule.MEDIA_RULE) {
continue
}
// WARNING: Safari does not have/supports `conditionText`.
if (cssRule.conditionText) {
if (cssRule.conditionText !== prefersColorSchemeDark) {
continue
}
} else {
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
continue
}
}
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
}

// WARNING: do not try to insert a Rule to a styleSheet you are
// currently iterating on, otherwise the browser will be stuck
// in a infinite loop…
for (const mediaRule of mediaRules) {
styleSheet.insertRule(mediaRule.cssText)
hasDarkRules = true
}
}
if (hasDarkRules) {
loadThemeForm('#theme-selector')
}
})
</script>
</body>
</html>

+ 79
- 0
cache/2024/140458968f9f7da7d14e181d0a80e799/index.md View File

@@ -0,0 +1,79 @@
title: The Expanding Dark Forest and Generative AI
url: https://maggieappleton.com/ai-dark-forest
hash_url: 140458968f9f7da7d14e181d0a80e799
archive_date: 2024-02-19
og_image: https://maggieappleton.com//images/og/fe37968757d0ac03e4b01c7496b2e8ac.png
description: Proving you're a human on a web flooded with generative AI content
favicon: https://maggieappleton.com//images/favicon/favicon.ico
language: en_GB

<div class="AssumedAudience__AssumedAudienceContainer-gnzma-0 LlqKU"><span class="label">Assumed Audience</span><div><p>People who have heard of GPT-3 / ChatGPT, and are vaguely following the
advances in machine learning, large language models, and image generators.
Also people who care about making the web a flourishing social and
intellectual space.</p></div></div>
<div class="Spacer-zsy3ll-0 jLPklF"></div>
<!-- --><p class="IntroParagraph-l306ci-0 hlDXQj"><p>The <span aria-expanded="false"><div class="InternalTooltipLink__StyledContainer-sc-11bupup-1 eqmyTL"><a href="/cozy-web" class="InternalTooltipLink__StyledLink-sc-11bupup-2 hvOxza"><span>dark forest theory</span></a></div></span> of the web points to the increasingly life-like but life-less state of being online.<aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="1" class="margin-toggle footnote-number"></label><input type="checkbox" id="1" class="margin-toggle"><span class="footnote"><span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://onezero.medium.com/the-dark-forest-theory-of-the-internet-7dc3e68a7cb1" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Dark Forest</span></a></div></span> <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://onezero.medium.com/the-dark-forest-theory-of-the-internet-7dc3e68a7cb1" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Theory of</span></a></div></span> <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://onezero.medium.com/the-dark-forest-theory-of-the-internet-7dc3e68a7cb1" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>the Internet</span></a></div></span> by Yancey Strickler</span></aside> Most open and publicly available spaces on the web are overrun with bots, advertisers, trolls, data scrapers, clickbait, keyword-stuffing “content creators,” and algorithmically manipulated junk.</p></p>
<p>It's like a dark forest that seems eerily devoid of human life – all the living creatures are hidden beneath the ground or up in trees. If they reveal themselves, they risk being attacked by automated predators.</p>
<p>Humans who want to engage in informal, unoptimised, personal interactions have to hide in closed spaces like invite-only Slack channels, Discord groups, email newsletters, small-scale blogs, and <span aria-expanded="false"><div class="InternalTooltipLink__StyledContainer-sc-11bupup-1 eqmyTL"><a href="/garden-history" class="InternalTooltipLink__StyledLink-sc-11bupup-2 hvOxza"><span>digital gardens</span></a></div></span>. Or make themselves <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.ribbonfarm.com/2010/07/26/a-big-little-idea-called-legibility/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>illegible</span></a></div></span> and algorithmically incoherent in public venues.</p>
<!-- --><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/cozyweb.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/cozyweb-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/cozyweb-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/cozyweb-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/cozyweb-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/cozyweb-1800.jpg 1800w" alt="An illustration of layers of the web: the dark forest on top, followed by layers of cozyweb holes where people hide away from bots and ad scavengers" width="1000px" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 daiAzl"></figure>
<p>That dark forest is about to <div style="transform: scaleX(1.85); display: inline-flex; margin: 0px 2.2rem;">expand</div>. Large Language Models (LLMs) that can instantly generate coherent swaths of human-like text have just joined the party.</p>
<!-- --><p>Over the last six months, we've seen a flood of LLM copywriting and content-generation products come out: <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.jasper.ai/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Jasper</span></a></div></span>, <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.gomoonbeam.com/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Moonbeam</span></a></div></span>, <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.copy.ai/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Copy.ai</span></a></div></span>, and <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://anyword.com/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Anyword</span></a></div></span> are just a few. They're designed to pump out advertising copy, blog posts, emails, social media updates, and marketing pages. And they're <em>really</em> good at it.<aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="2" class="margin-toggle footnote-number"></label><input type="checkbox" id="2" class="margin-toggle"><span class="footnote">Primarily because <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://en.wikipedia.org/wiki/GPT-3" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>GPT-3</span></a></div></span> which powers many of these products was specifically trained on text from the web. It's intimately familiar with the style of language we use online.</span></aside></p>
<p>These models became competent copywriters much faster than people expected – too fast for us to fully process the implications. Many people had their come-to-Jesus moment a few weeks ago when OpenAI released <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://openai.com/blog/chatgpt/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>ChatGPT</span></a></div></span>, a slightly more capable version of GPT-3 with an accessible chat-bot style interface. <aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="3" class="margin-toggle footnote-number"></label><input type="checkbox" id="3" class="margin-toggle"><span class="footnote">They're calling it GPT-3.5. It's the same model with human <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://huggingface.co/blog/rlhf" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>reinforcement learning</span></a></div></span> layered on top.</span></aside> The <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://twitter.com/elonmusk/status/1599128577068650498?s=20&amp;t=MgaSdgsaF0uU1lITCVPghw" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>collective</span></a></div></span> <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://twitter.com/volodarik/status/1600854935515844610?s=20&amp;t=MgaSdgsaF0uU1lITCVPghw" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>shock</span></a></div></span> and <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://twitter.com/yu_angela/status/1599808692085743616?s=20&amp;t=MgaSdgsaF0uU1lITCVPghw" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>awe</span></a></div></span> <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://twitter.com/levie/status/1599156293050433536?s=20&amp;t=MgaSdgsaF0uU1lITCVPghw" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>reaction</span></a></div></span> made clear how few people had been tracking the progress of these models.</p>
<p>To complicate matters, language models are not the only mimicry machines gathering speed right now. Image generators like <!-- --><span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.midjourney.com/home/?callbackUrl=/app/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Midjourney</span></a></div></span>, <!-- --><span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://openai.com/dall-e-2/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>DALL-E</span></a></div></span>, and <!-- --><span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://en.wikipedia.org/wiki/Stable_Diffusion" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Stable Diffusion</span></a></div></span> have been on a year-long sprint. In January they could barely render a low-resolution, disfigured human face. By the autumn they reliably produced images indistinguishable from the work of human photographers and illustrators.<!-- --></p>
<div class="TwoColumn__TwoColumnContainer-sc-2qlq9z-0 ePKlxc"><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/mj8.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/mj8-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/mj8-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/mj8-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/mj8-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/mj8-1800.jpg 1800w" alt="..." width="100%" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 iGepOK"></figure><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/mj1.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/mj1-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/mj1-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/mj1-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/mj1-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/mj1-1800.jpg 1800w" alt="..." width="100%" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 iGepOK"></figure><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/mj7.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/mj7-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/mj7-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/mj7-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/mj7-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/mj7-1800.jpg 1800w" alt="..." width="100%" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 iGepOK"></figure><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/mj3.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/mj3-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/mj3-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/mj3-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/mj3-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/mj3-1800.jpg 1800w" alt="..." width="100%" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 iGepOK"></figure><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/mj9.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/mj9-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/mj9-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/mj9-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/mj9-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/mj9-1800.jpg 1800w" alt="..." width="100%" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 iGepOK"></figure><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/mj4.png" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/mj4-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/mj4-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/mj4-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/mj4-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/mj4-1800.jpg 1800w" alt="..." width="100%" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 iGepOK"></figure></div>
<aside class="Typography__Subtext-sc-1dhc7go-6 cHqTEw">Images I generated with Midjourney's V4 model</aside>
<!-- --><a href="#a-generated-web"><h2 id="a-generated-web" class="Typography__Title2-sc-1dhc7go-1 eFwLIG">A Generated Web</h2></a>
<p>There's a swirl of optimism around how these models will save us from a suite of boring busywork: writing formal emails, internal memos, technical documentation, marketing copy, product announcement, advertisements, cover letters, and even negotiating with medical <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://twitter.com/StuartBlitz/status/1602834224284897282" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>insurance companies</span></a></div></span>.</p>
<p>But we'll also need to reckon with the trade-offs of making insta-paragraphs and 1-click cover images. These new models are poised to flood the web with generic, generated content.</p>
<p>You thought the first page of Google was bunk before? You haven't seen Google where SEO optimizer bros pump out billions of perfectly coherent but predictably dull informational articles for every longtail keyword combination under the sun.</p>
<p>Marketers, influencers, and growth hackers will set up <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://zapier.com/apps/openai/integrations" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>OpenAI → Zapier</span></a></div></span> pipelines that auto-publish a relentless and impossibly banal stream of LinkedIn #MotivationMonday posts, “engaging” tweet <span role="img">🧵</span> threads, Facebook outrage monologues, and corporate blog posts.</p>
<p>It goes beyond text too: <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://twitter.com/SamRo/status/1605919856808714240?s=20&amp;t=QB-eYoISuymlqbHFFDnrWw" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>video essays on YouTube</span></a></div></span>, TikTok clips, podcasts, slide decks, and Instagram stories can all be generated by <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://runwayml.com/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>patchworking</span></a></div></span> together ML systems. And then <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://byautomata.io/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>regurgitated</span></a></div></span> for each medium.</p>
<p>We're about to drown in a sea of pedestrian takes. An explosion of noise that will drown out any signal. Goodbye to finding original human insights or authentic connections under that pile of cruft.</p>
<p>Many people will say we already live in this reality. We've already become skilled at sifting through unhelpful piles of “optimised content” designed to gather clicks and advertising impressions.</p>
<p>4chan proposed <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.theatlantic.com/technology/archive/2021/08/dead-internet-theory-wrong-but-feels-true/619937/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>dead internet theory</span></a></div></span> years ago: that most of the internet is “empty and devoid of people” and has been taken over by artificial intelligence. A milder version of this theory is simply that we're overrun <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://nymag.com/intelligencer/2018/12/how-much-of-the-internet-is-fake.html" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>with bots</span></a></div></span>. Most of us take that for granted at this point.</p>
<p>But I think the sheer volume and scale of what's coming will be meaningfully different. And I think we're unprepared. Or at least, I am.</p>
<hr>
<a href="#passing-the-reverse-turing-test"><h2 id="passing-the-reverse-turing-test" class="Typography__Title2-sc-1dhc7go-1 eFwLIG">Passing the Reverse Turing Test</h2></a>
<p>Our new challenge as little snowflake humans will be to prove we aren't language models. It's the reverse <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://en.wikipedia.org/wiki/Turing_test" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>turing test</span></a></div></span>.</p>
<div class="TweetEmbed__TweetContainer-sc-1j7oyq8-0 dYplAO tweet"><div></div></div>
<div class="TweetEmbed__TweetContainer-sc-1j7oyq8-0 dYplAO tweet"><div></div></div>
<p>After the forest expands, we will become deeply sceptical of one another's <em>realness</em>. Every time you find a new favourite blog or Twitter account or Tiktok personality online, you'll have to ask: Is this really a whole human with a rich and complex life like mine? Is there a <em>being</em> on the other end of this web interface I can form a relationship with?<aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="4" class="margin-toggle footnote-number"></label><input type="checkbox" id="4" class="margin-toggle"><span class="footnote">“Relationship” in the holistic sense – friend, acquaintance, pen pal, intellectual interlocutor, frenemy, drinking buddy, and sure, maybe a lover.</span></aside></p>
<p>Before you continue, pause and consider: How would <em>you</em> prove you're not a language model generating predictive text? What special human tricks can you do that a language model can't?</p>
<h3 id="1-triangulate-objective-reality" class="Typography__Title3-sc-1dhc7go-3 jIUqxb">1. Triangulate objective reality</h3>
<p>As language models become increasingly capable and impressive, we should remember they are, at their core, linguistic <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.datacamp.com/blog/a-beginners-guide-to-gpt-3#:~:text=Language%20modeling%20is,predicting%20word%20sequences." class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>prediction systems</span></a></div></span>. They cannot (yet) reason like a human.</p>
<p>They do not have beliefs based on evidence, claims, and principles. They cannot consult external sources and run experiments against objective reality. They cannot go outside and touch grass.</p>
<p>In short, they do not have access to the same shared reality we do. They do not have embodied experiences, and cannot sense the world as we can sense it; they don't have vision, sound, taste, or touch. They cannot feel emotion or tightly hold a coherent set of values. They are not part of cultures, communities, or histories.</p>
<p>They are a language model in a box. If a historical event, fact, person, or concept wasn't part of their training data, they can't tell you about it. They don't know about events that happened after a certain cutoff date. <aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="5" class="margin-toggle footnote-number"></label><input type="checkbox" id="5" class="margin-toggle"><span class="footnote">Currently 2021 for GPT-3 / ChatGPT, but we can expect that to regularly update as new models are trained</span></aside></p>
<p>I found Murray Shanahan's paper on <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="http://arxiv.org/abs/2212.03551" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Talking About Large Language Models</span></a></div></span> (2022) full of helpful reflections on this point:</p>
<figure><blockquote class="BlockquoteCitation__Blockquote-sc-15uv93b-1 jMOCbH"><p><p>Humans are members of a community of language-users inhabiting a shared world, and this primal fact makes them essentially different to large language models. We can consult the world to settle our disagreements and update our beliefs. We can, so to speak, “triangulate” on objective reality.</p></p><figcaption><cite class="BlockquoteCitation__Cite-sc-15uv93b-0 bcodDR"><span>Murray Shanahan – </span><a href="http://arxiv.org/abs/2212.03551">Talking About Large Language Models</a></cite></figcaption></blockquote></figure>
<p>This leaves us with some low-hanging fruit for humanness. We can tell richly detailed stories grounded in our specific contexts and cultures: place names, sensual descriptions, local knowledge, and, well the <!-- --><em>je ne sais quoi</em> of being alive. Language models can decently mimic this style of writing but most don't without extensive prompt engineering. They stick to generics. They hedge. They leave out details. They have trouble maintaining a coherent sense of self over thousands of words.</p>
<p>Hipsterism and recency bias will help us here. Referencing obscure concepts, friends who are real but not famous, niche interests, and recent events all make you plausibly more human.<aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="6" class="margin-toggle footnote-number"></label><input type="checkbox" id="6" class="margin-toggle"><span class="footnote">This feels eerily like a hostage holding up yesterday's newspaper to prove they are actively in danger. Perhaps a premonition.</span></aside></p>
<h3 id="2-be-original-critical-and-sophisticated" class="Typography__Title3-sc-1dhc7go-3 jIUqxb">2. Be original, critical, and sophisticated</h3>
<p>Easier said than done, but one of the best ways to prove you're not a predictive language model is to demonstrate critical and sophisticated thinking.</p>
<p>Language models spit out text that sounds like a B+ college essay. Coherent, seemingly comprehensive, but never truly insightful or original (at least for now).</p>
<p>In a repulsively evocative metaphor, they engage in “<span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://en.wikipedia.org/wiki/The_Human_Centipede_(First_Sequence)" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>human centipede</span></a></div></span> epistemology.”<aside class="Footnote__FootnoteContainer-sc-1ju9tgv-0 dfVcgp"><label for="7" class="margin-toggle footnote-number"></label><input type="checkbox" id="7" class="margin-toggle"><span class="footnote">I found this phrase via Twitter, but posted from a private account so I won't cite the original author.</span></aside> Language models regurgitate text from across the web, which some humans read and recycle into "original creations," which then become fodder to train other language models, and around and around we go recycling generic ideas and arguments and tropes and ways of thinking.</p>
<p>Hard exiting out of this cycle requires coming up with unquestionably original thoughts and theories. It means seeing and synthesising patterns across a broad range of sources: books, blogs, cultural narratives served up by media outlets, conversations, podcasts, lived experiences, and market trends. We can observe and analyse a much fuller range of inputs than bots and generative models can.</p>
<p>It will raise the stakes for everyone. As both consumers of content and creators of it, we'll have to foster a greater sense of critical thinking and scepticism.</p>
<p>This all sounds a bit rough, but there's a lot of hope in this vision. In a world of automated intelligence, our goalposts for intelligence will shift. We'll raise our quality bar for what we expect from humans. When a machine can pump out a great literature review or summary of existing work, there's no value in a person doing it.</p>
<h3 id="3-develop-creative-language-quirks-dialects-memes-and-jargon" class="Typography__Title3-sc-1dhc7go-3 jIUqxb">3. Develop creative language quirks, dialects, memes, and jargon</h3>
<p>The linguist <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://en.wikipedia.org/wiki/Ferdinand_de_Saussure" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Ferdinand de Saussure</span></a></div></span> argued there are two kinds of language:</p>
<ul>
<li><strong>La langue</strong> is the formal concept of language. These are words we print in the dictionary, distribute via educational institutions, and reprimand one another for getting it wrong.</li>
<li><strong>La parole</strong> is the speech of everyday life. These are the informal, diverse, and creative speech acts we perform in conversations, social gatherings, and text to the group WhatsApp. This is where language evolves.</li>
</ul>
<p>We have designed a system that automates a standardised way of writing. We have codified <!-- --><em>la langue</em> at a specific point in time.</p>
<p>What we have left to play with is <em>la parole</em>. No language model will be able to keep up with the pace of weird internet lingo and memes. I expect we'll lean into this. Using neologisms, jargon, euphemistic emoji, unusual phrases, ingroup dialects, and memes-of-the-moment will help signal your humanity.</p>
<p>Not unlike teenagers using language to subvert their elders, or oppressed communities developing dialects that allow them to safely communicate amongst themselves.</p>
<h3 id="4-consider-institutional-verification" class="Typography__Title3-sc-1dhc7go-3 jIUqxb">4. Consider institutional verification</h3>
<p>This solution feels the least interesting. We're already hearing rumblings of how “verification” by centralised institutions or companies might help us distinguish between meat brains and metal brains.</p>
<p>The idea is something like this: you show up in person to register your online accounts or domains. You then get some kind of special badge or mark online legitimising you as a Real Human. It may or may not be on the blockchain somehow.</p>
<p>Google might look something like this:</p>
<figure class="ImageFrame__Container-sc-1c93cul-0 jlxTrp"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/human_google.jpg" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/human_google-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/human_google-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/human_google-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/human_google-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/human_google-1800.jpg 1800w" alt="Google search results showing a 'certified human' badge on some items" width="1300px" class="ImageFrame__StyledImageFrame-sc-1c93cul-1 dlXCP"></figure>
<p>The whole thing seems fraught with problems, susceptible to abuse, and ultimately impractical. Would it even be the web if everyone knew you were really a dog?</p>
<!-- --><figure class="BasicImage__Container-sc-12ox3yv-0 ChLlc"><img src="https://maggieappleton.com//images/posts/ai-dark-forest/Internet_dog.jpeg" srcset="https://maggieappleton.com//images/posts/ai-dark-forest/Internet_dog-440.jpg 440w, https://maggieappleton.com//images/posts/ai-dark-forest/Internet_dog-800.jpg 800w, https://maggieappleton.com//images/posts/ai-dark-forest/Internet_dog-1100.jpg 1100w, https://maggieappleton.com//images/posts/ai-dark-forest/Internet_dog-1300.jpg 1300w, https://maggieappleton.com//images/posts/ai-dark-forest/Internet_dog-1800.jpg 1800w" alt="The original internet dog meme: 'On the internet, no one knows you're a dog'" width="460px" class="BasicImage__StyledBasicImage-sc-12ox3yv-1 klXNGD"><figcaption>The original internet dog meme: 'On the internet, no one knows you're a dog'</figcaption></figure>
<h3 id="5-show-up-in-meatspace" class="Typography__Title3-sc-1dhc7go-3 jIUqxb">5. Show up in meatspace</h3>
<!-- --><p>The final edge we have over language models is that we can prove we're real humans by showing up IRL with our real human bodies. We can arrange to meet Twitter mutuals offline over coffee. We can organise meetups and events and conferences and unconferences and hangouts and pub nights.</p>
<p>In <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.fortressofdoors.com/ai-markets-for-lemons-and-the-great-logging-off/" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>Markets for Lemons and the Great Logging Off</span></a></div></span>, Lars Doucet proposed several knock-on effects from this offline-first future. We might see increased <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.fortressofdoors.com/ai-markets-for-lemons-and-the-great-logging-off/#:~:text=a%20resurgence%20and%20even%20fetishization%20of%20explicitly%20%22offline%22%20culture%2C%20where%20the%20%22Great%20Logging%20Off%22%20becomes%20literal" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>fetishisation</span></a></div></span> of anti-screen culture, as well as <span aria-expanded="false"><div class="TooltipLink__StyledContainer-sc-1azn7hi-1 hSnOot"><a href="https://www.fortressofdoors.com/ai-markets-for-lemons-and-the-great-logging-off/#:~:text=Seventh%2C%20real,amenities%20are%20available" class="TooltipLink__StyledLink-sc-1azn7hi-2 ijKyXp"><span>real estate</span></a></div></span> price increases in densely populated areas.</p>
<p>For the moment we can still check humanness over Zoom, but live video generation is getting good enough that I don't think that defence will last long.</p>
<p>There are, of course, many people who can't move to an offline-first life; people with physical disabilities. People who live in remote, rural places. People with limited time and caretaking responsibilities for the very young or the very old. They will have a harder time verifying their humanness online. I don't have any grand ideas to help solve this, but I hope we find better solutions than my paltry list.</p>
<p>As the forest grows darker, noisier, and less human, I expect to invest more time in in-person relationships and communities. And while I love meatspace, this still feels like a loss.</p>

+ 469
- 0
cache/2024/6bfc6bd7bc1d9158aa7f6591123e7f4b/index.html View File

@@ -0,0 +1,469 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="en">
<!-- Has to be within the first 1024 bytes, hence before the `title` element
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>The Simplest Ways to Handle HTML Includes (archive) — David Larlet</title>
<meta name="description" content="Publication mise en cache pour en conserver une trace.">
<!-- That good ol' feed, subscribe :). -->
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
<!-- Generated from https://realfavicongenerator.net/ such a mess. -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
<link rel="manifest" href="/static/david/icons2/site.webmanifest">
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
<meta name="msapplication-TileColor" content="#f7f7f7">
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
<meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
<!-- Is that even respected? Retrospectively? What a shAItshow…
https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/ -->
<meta name="robots" content="noai, noimageai">
<!-- Documented, feel free to shoot an email. -->
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<script>
function toggleTheme(themeName) {
document.documentElement.classList.toggle(
'forced-dark',
themeName === 'dark'
)
document.documentElement.classList.toggle(
'forced-light',
themeName === 'light'
)
}
const selectedTheme = localStorage.getItem('theme')
if (selectedTheme !== 'undefined') {
toggleTheme(selectedTheme)
}
</script>

<meta name="robots" content="noindex, nofollow">
<meta content="origin-when-cross-origin" name="referrer">
<!-- Canonical URL for SEO purposes -->
<link rel="canonical" href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/">

<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">


<article>
<header>
<h1>The Simplest Ways to Handle HTML Includes</h1>
</header>
<nav>
<p class="center">
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/" title="Lien vers le contenu original">Source originale</a>
<br>
Mis en cache le 2024-02-19
</p>
</nav>
<hr>
<p>It’s extremely surprising to me that HTML has never had any way to include other HTML files within it. Nor does there seem to be anything on the horizon that addresses it. I’m talking about straight up <em>includes</em>, like taking a chunk of HTML and plopping it right into another. For example the use case for much of the entire internet, an included header and footer for all pages:</p>

<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">...
&lt;body&gt;
&lt;include src="./header.html"&gt;&lt;/include&gt;

Content

&lt;include src="./footer.html"&gt;&lt;/include&gt;
&lt;/body&gt;
...</code></pre>

<p>That’s not real, by the way. I just wish it was.</p>

<p><span id="more-286228"></span></p>
<p>People have been looking to other languages to solve this problem for them forever. It’s HTML preprocessing, in a sense. Long before we were preprocessing our CSS, we were using tools to manipulate our HTML. And we still are, because the idea of includes is useful on pretty much every website in the world.</p>

<h3 class="wp-block-heading" id="h-use-php"><a href="#aa-use-php" aria-hidden="true" class="aal_anchor" id="aa-use-php"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use PHP</h3>

<p>Can you use PHP instead?</p>

<pre rel="PHP" class="wp-block-csstricks-code-block language-javascript" data-line=""><code markup="tt">...
&lt;body&gt;
&lt;?php include "./header.html" ?&gt;

Content

&lt;?php include "./footer.html" ?&gt;
&lt;/body&gt;
...</code></pre>

<p>This will perform the include at the server level, making the request for it happen at the file system level on the server, so it should be far quicker than a client-side solution.</p>

<h3 class="wp-block-heading" id="h-use-gulp"><a href="#aa-use-gulp" aria-hidden="true" class="aal_anchor" id="aa-use-gulp"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Gulp</h3>

<p>What’s even faster than a server-side include? If the include is preprocessed before it’s even on the server. <a href="https://gulpjs.com/" rel="noopener">Gulp</a> has a variety of processors that can do this. One is <a href="https://www.npmjs.com/package/gulp-file-include" rel="noopener">gulp-file-include</a>.</p>

<p>That would look like this:</p>

<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">...
&lt;body&gt;
@@include('./header.html')

Content

@@include('./footer.html')
&lt;/body&gt;
...</code></pre>

<p>And you’d process it like:</p>

<pre rel="JavaScript" class="wp-block-csstricks-code-block language-javascript" data-line=""><code markup="tt">var fileinclude = require('gulp-file-include'),
gulp = require('gulp');

gulp.task('fileinclude', function() {
gulp.src(['index.html'])
.pipe(fileinclude({
prefix: '@@',
basepath: '@file'
}))
.pipe(gulp.dest('./'));
});</code></pre>

<p>Looks like this particular plugin has fancy features where you can pass in variables to the includes, making it possible to make little data-driven components.</p>

<h3 class="wp-block-heading" id="h-use-grunt"><a href="#aa-use-grunt" aria-hidden="true" class="aal_anchor" id="aa-use-grunt"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Grunt</h3>

<p>This is what the <a href="https://www.npmjs.com/package/grunt-bake" rel="noopener">grunt-bake</a> plugin does. You’d configure Grunt to process your HTML:</p>

<pre rel="JavaScript" class="wp-block-csstricks-code-block language-javascript" data-line=""><code markup="tt">grunt.initConfig({
bake: {
your_target: {
files: {
"dist/index.html": "app/index.html",
}
}
}
});</code></pre>

<p>Then your HTML can use this special syntax for includes:</p>

<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">...
&lt;body&gt;
&lt;!--(bake header.html)--&gt;

Content

&lt;!--(bake footer.html)--&gt;
&lt;/body&gt;
...</code></pre>

<h3 class="wp-block-heading" id="h-use-handlebars"><a href="#aa-use-handlebars" aria-hidden="true" class="aal_anchor" id="aa-use-handlebars"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Handlebars</h3>

<p>Handlebars <a href="https://handlebarsjs.com/partials.html" rel="noopener">has partials</a>.</p>

<p>You register them:</p>

<pre rel="JavaScript" class="wp-block-csstricks-code-block language-javascript" data-line=""><code markup="tt">Handlebars.registerPartial('myPartial', '{{name}}')</code></pre>

<p>Then use them:</p>

<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">{{&gt; myPartial }}</code></pre>

<p>There is also fancy features of this that allow for evaluation and passing data. You’ll still need a processor to run it, probably something like <a href="https://www.npmjs.com/package/gulp-handlebars" rel="noopener">gulp-handlebars</a>.</p>

<p>Speaking of templating languages which make use of curly braces… Mustache <a href="https://github.com/janl/mustache.js#include-templates" rel="noopener">has them, too</a>.</p>

<h3 class="wp-block-heading" id="h-use-pug"><a href="#aa-use-pug" aria-hidden="true" class="aal_anchor" id="aa-use-pug"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Pug</h3>

<p><a href="https://pugjs.org/" rel="noopener">Pug</a> is an HTML preprocessor that has a whole new syntax for HTML that is a bit more terse. <a href="https://pugjs.org/language/includes.html" rel="noopener">It’s got includes though</a>.</p>

<pre rel="Pug" class="wp-block-csstricks-code-block language-none" data-line=""><code markup="tt">...
body
include ./header.html"

p Content

include ./footer.html"

...</code></pre>

<p>Then you run it with something like <a href="https://www.npmjs.com/package/gulp-pug" rel="noopener">gulp-pug</a>.</p>

<h3 class="wp-block-heading" id="h-use-nunjucks"><a href="#aa-use-nunjucks" aria-hidden="true" class="aal_anchor" id="aa-use-nunjucks"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Nunjucks</h3>

<p><a href="https://css-tricks.com/killer-features-of-nunjucks/">I love me some Nunjucks!</a> <a href="https://mozilla.github.io/nunjucks/" rel="noopener">Nunjucks</a> has <a href="https://mozilla.github.io/nunjucks/templating.html#include" rel="noopener">includes</a>. You’d do it like this:</p>

<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">...
&lt;body&gt;
{% include "./header.html" %}

Content

{% include "./footer.html" %}
&lt;/body&gt;
...</code></pre>

<p>If you put that in a file called <code>index.njk</code>, you could process it with a simple Node script into index.html like this:</p>

<pre rel="JavaScript" class="wp-block-csstricks-code-block language-javascript" data-line=""><code markup="tt">const nunjucks = require("nunjucks");
const fs = require("fs");

fs.writeFile("index.html", nunjucks.render("index.njk"), function(err, data) {
if (err) console.log(err);
console.log("Compiled the Nunjucks, captain.");
});</code></pre>

<p>Or process it with something like <a href="https://www.npmjs.com/package/gulp-nunjucks" rel="noopener">gulp-nunjucks</a>.</p>

<p>11ty has <a href="https://www.11ty.io/docs/languages/nunjucks/" rel="noopener">Nunjucks built-in</a>, along with many of the other mentioned so far. Might be good for you if you’re actually building a little site.</p>

<h3 class="wp-block-heading" id="h-use-ajax"><a href="#aa-use-ajax" aria-hidden="true" class="aal_anchor" id="aa-use-ajax"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Ajax</h3>

<p>Say you had…</p>

<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;body&gt;

&lt;header&gt;&lt;/header&gt;

Content.

&lt;footer&gt;&lt;/footer&gt;

&lt;/body&gt;</code></pre>

<p>You could fetch the contents for the header and footer from respective files and dump the contents in.</p>

<pre rel="JavaScript" class="wp-block-csstricks-code-block language-javascript" data-line=""><code markup="tt">fetch("./header.html")
.then(response =&gt; {
return response.text()
})
.then(data =&gt; {
document.querySelector("header").innerHTML = data;
});

fetch("./footer.html")
.then(response =&gt; {
return response.text()
})
.then(data =&gt; {
document.querySelector("footer").innerHTML = data;
});</code></pre>

<p>Speaking of JavaScript… If you’re building your site using a JavaScript framework of just about any kind, building through components is kind of the main deal there and breaking parts you want to include in other files should be no problem. Some kind of <code>import Header from "./header.js";</code> and <code>&lt;Header /&gt;</code> is the territory you’d be in in React land.</p>

<h3 class="wp-block-heading" id="h-use-iframes"><a href="#aa-use-iframes" aria-hidden="true" class="aal_anchor" id="aa-use-iframes"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use iframes</h3>

<p>You could do this:</p>

<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;body&gt;

&lt;iframe src="./header.html"&gt;&lt;/iframe&gt;

Content.

&lt;iframe src="./footer.html"&gt;&lt;/iframe&gt;

&lt;/body&gt;</code></pre>

<p>But the content in those iframes does not share the same DOM, so it’s a bit weird, not to mention slow and awkward to style (since iframes don’t know the heights of their contents).</p>

<p><a href="https://www.filamentgroup.com/lab/html-includes/" rel="noopener">Scott Jehl documented a cool idea</a> though: You can have the iframe inject the content of itself onto the parent page then remove itself.</p>

<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;body&gt;

&lt;iframe src="header.html" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"&gt;&lt;/iframe&gt;

Content.

&lt;iframe src="footer.html" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"&gt;&lt;/iframe&gt;

&lt;/body&gt;</code></pre>

<p>Kolya Korruptis wrote in with this adaptation which will include more than the first child of the body in case your HTML file has that:</p>

<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;iframe src="included.html" onload="this.insertAdjacentHTML('afterend', (this.contentDocument.body||this.contentDocument).innerHTML);this.remove()"&gt;&lt;/iframe&gt;</code></pre>

<h3 class="wp-block-heading" id="use-jekyll"><a href="#aa-use-jekyll" aria-hidden="true" class="aal_anchor" id="aa-use-jekyll"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Jekyll</h3>

<p><a href="https://jekyllrb.com/" rel="noopener">Jekyll</a> is a Ruby-based static site generator with <a href="https://jekyllrb.com/docs/includes/" rel="noopener">includes</a>. You keep your includes in the <code>/_includes/</code> folder, then:</p>

<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;body&gt;
{% include header.html %}

Content.

{% include footer.html %}
&lt;/body&gt;</code></pre>

<p>Jekyll is a big one, so I’m calling it out here, but there are <a href="https://www.staticgen.com/" rel="noopener">a ton of static site generators</a> and I’d wager any of them can do includes.</p>

<h3 class="wp-block-heading" id="use-sergey"><a href="#aa-use-sergey" aria-hidden="true" class="aal_anchor" id="aa-use-sergey"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/#use-sergey"></a>Use Sergey</h3>

<p>OK, I’ll call out one more SSG because it’s new and super focused. <a href="https://sergey.cool/" rel="noopener">Sergey</a> has a web components style format:</p>

<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;body&gt;
&lt;sergey-import src="header" /&gt;

Content.

&lt;sergey-import src="footer" /&gt;
&lt;/body&gt;</code></pre>

<p>You’d name the files <code>header.html</code> and <code>footer.html</code> and put them in <code>/includes/</code> and then it’ll make a build with the includes processed when you run the npm script it has you do.</p>

<h3 class="wp-block-heading" id="use-apache-ssi"><a href="#aa-use-apache-ssi" aria-hidden="true" class="aal_anchor" id="aa-use-apache-ssi"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/#use-apache-ssi"></a>Use Apache SSI</h3>

<p>Apache, a super duper common web server, can <a href="https://httpd.apache.org/docs/2.4/mod/mod_include.html" rel="noopener">do includes</a>. You do it like this:</p>

<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;body&gt;

&lt;!--#include file="./header.html" --&gt;

Content

&lt;!--#include file="./footer.html" --&gt;

&lt;/body&gt;</code></pre>

<p>But you need the right Apache configuration to allow stuff. I tried my best to get a working demo going but didn’t have much luck.</p>

<p>I tried using <code>.htaccess</code> within a folder on an Apache server and flipping on what I thought was the right stuff:</p>

<pre rel="HTAccess" class="wp-block-csstricks-code-block language-none" data-line=""><code markup="tt">Options +Includes

AddType text/html .html
AddOutputFilter INCLUDES .html</code></pre>

<p>I’m sure there is some way to get it working though, and if you do, it’s kinda neat that it needs zero other dependencies.</p>

<h3 class="wp-block-heading" id="use-codekit"><a href="#aa-use-codekit" aria-hidden="true" class="aal_anchor" id="aa-use-codekit"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/#use-codekit"></a>Use CodeKit</h3>

<p>Mac only, but CodeKit has <a href="https://codekitapp.com/help/kit/" rel="noopener">a special language called Kit</a> it processes where 90% of the point of it is HTML includes. It uses special HTML comments:</p>

<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">...
&lt;body&gt;
&lt;!-- @import "./header.html" --&gt;

Content

&lt;!-- @import "./footer.html" --&gt;
&lt;/body&gt;
...</code></pre>

<h3 class="wp-block-heading" id="use-dreamweaver"><a href="#aa-use-dreamweaver" aria-hidden="true" class="aal_anchor" id="aa-use-dreamweaver"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/#use-dreamweaver"></a>Use Dreamweaver</h3>

<p>Lol jk. But it <a href="https://helpx.adobe.com/dreamweaver/using/server-side-includes.html" rel="noopener">really is a thing</a>. <a href="http://shop.pixelmill.com/support/al0/kb101502.htm" rel="noopener">DWTs</a>, baby.</p>

<h3 class="wp-block-heading" id="holy-crap"><a href="#aa-holy-crap" aria-hidden="true" class="aal_anchor" id="aa-holy-crap"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/#holy-crap"></a>Holy Crap</h3>

<p>That’s a lot of ways, isn’t it?</p>

<p>Like I said at the top, it’s very surprising to me that HTML itself hasn’t addressed this directly. Not that I think it would be a great idea for performance to have <code>&lt;include&gt;</code> statements that trigger network requests all over our code, but it seems in-line with the platform. Using ES6 imports directly without bundling isn’t a great idea always either, but we have them. <code>@import</code>ing CSS within CSS isn’t a great idea always, but we have it. If the platform had a native syntax, perhaps other tooling would key off that, much like JavaScript bundlers support the ES6 import format.</p>
</article>


<hr>

<footer>
<p>
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
</svg> Suivre</a> •
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
</svg> Pro</a> •
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
</svg> Email</a> •
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
</svg> Légal</abbr>
</p>
<template id="theme-selector">
<form>
<fieldset>
<legend><svg class="icon icon-brightness-contrast">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
</svg> Thème</legend>
<label>
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
</label>
<label>
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé
</label>
<label>
<input type="radio" value="light" name="chosen-color-scheme"> Clair
</label>
</fieldset>
</form>
</template>
</footer>
<script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
<script>
function loadThemeForm(templateName) {
const themeSelectorTemplate = document.querySelector(templateName)
const form = themeSelectorTemplate.content.firstElementChild
themeSelectorTemplate.replaceWith(form)

form.addEventListener('change', (e) => {
const chosenColorScheme = e.target.value
localStorage.setItem('theme', chosenColorScheme)
toggleTheme(chosenColorScheme)
})

const selectedTheme = localStorage.getItem('theme')
if (selectedTheme && selectedTheme !== 'undefined') {
form.querySelector(`[value="${selectedTheme}"]`).checked = true
}
}

const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
window.addEventListener('load', () => {
let hasDarkRules = false
for (const styleSheet of Array.from(document.styleSheets)) {
let mediaRules = []
for (const cssRule of styleSheet.cssRules) {
if (cssRule.type !== CSSRule.MEDIA_RULE) {
continue
}
// WARNING: Safari does not have/supports `conditionText`.
if (cssRule.conditionText) {
if (cssRule.conditionText !== prefersColorSchemeDark) {
continue
}
} else {
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
continue
}
}
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
}

// WARNING: do not try to insert a Rule to a styleSheet you are
// currently iterating on, otherwise the browser will be stuck
// in a infinite loop…
for (const mediaRule of mediaRules) {
styleSheet.insertRule(mediaRule.cssText)
hasDarkRules = true
}
}
if (hasDarkRules) {
loadThemeForm('#theme-selector')
}
})
</script>
</body>
</html>

+ 427
- 0
cache/2024/6bfc6bd7bc1d9158aa7f6591123e7f4b/index.md View File

@@ -0,0 +1,427 @@
title: The Simplest Ways to Handle HTML Includes
url: https://css-tricks.com/the-simplest-ways-to-handle-html-includes/
hash_url: 6bfc6bd7bc1d9158aa7f6591123e7f4b
archive_date: 2024-02-19
og_image: https://css-tricks.com/wp-json/social-image-generator/v1/image/286228
description: It's extremely surprising to me that HTML has never had any way to include other HTML files within it. Nor does there seem to be anything on the horizon that
favicon: https://css-tricks.com/favicon.svg
language: en_US
<p>It’s extremely surprising to me that HTML has never had any way to include other HTML files within it. Nor does there seem to be anything on the horizon that addresses it. I’m talking about straight up <em>includes</em>, like taking a chunk of HTML and plopping it right into another. For example the use case for much of the entire internet, an included header and footer for all pages:</p>



<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">...
&lt;body&gt;
&lt;include src="./header.html"&gt;&lt;/include&gt;

Content

&lt;include src="./footer.html"&gt;&lt;/include&gt;
&lt;/body&gt;
...</code></pre>



<p>That’s not real, by the way. I just wish it was.</p>



<span id="more-286228"></span>



<p>People have been looking to other languages to solve this problem for them forever. It’s HTML preprocessing, in a sense. Long before we were preprocessing our CSS, we were using tools to manipulate our HTML. And we still are, because the idea of includes is useful on pretty much every website in the world.</p>


<h3 class="wp-block-heading" id="h-use-php"><a href="#aa-use-php" aria-hidden="true" class="aal_anchor" id="aa-use-php"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use PHP</h3>


<p>Can you use PHP instead?</p>



<pre rel="PHP" class="wp-block-csstricks-code-block language-javascript" data-line=""><code markup="tt">...
&lt;body&gt;
&lt;?php include "./header.html" ?&gt;

Content

&lt;?php include "./footer.html" ?&gt;
&lt;/body&gt;
...</code></pre>



<p>This will perform the include at the server level, making the request for it happen at the file system level on the server, so it should be far quicker than a client-side solution.</p>


<h3 class="wp-block-heading" id="h-use-gulp"><a href="#aa-use-gulp" aria-hidden="true" class="aal_anchor" id="aa-use-gulp"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Gulp</h3>


<p>What’s even faster than a server-side include? If the include is preprocessed before it’s even on the server. <a href="https://gulpjs.com/" rel="noopener">Gulp</a> has a variety of processors that can do this. One is <a href="https://www.npmjs.com/package/gulp-file-include" rel="noopener">gulp-file-include</a>.</p>



<p>That would look like this:</p>



<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">...
&lt;body&gt;
@@include('./header.html')

Content

@@include('./footer.html')
&lt;/body&gt;
...</code></pre>



<p>And you’d process it like:</p>



<pre rel="JavaScript" class="wp-block-csstricks-code-block language-javascript" data-line=""><code markup="tt">var fileinclude = require('gulp-file-include'),
gulp = require('gulp');
gulp.task('fileinclude', function() {
gulp.src(['index.html'])
.pipe(fileinclude({
prefix: '@@',
basepath: '@file'
}))
.pipe(gulp.dest('./'));
});</code></pre>



<p>Looks like this particular plugin has fancy features where you can pass in variables to the includes, making it possible to make little data-driven components.</p>


<h3 class="wp-block-heading" id="h-use-grunt"><a href="#aa-use-grunt" aria-hidden="true" class="aal_anchor" id="aa-use-grunt"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Grunt</h3>


<p>This is what the <a href="https://www.npmjs.com/package/grunt-bake" rel="noopener">grunt-bake</a> plugin does. You’d configure Grunt to process your HTML:</p>



<pre rel="JavaScript" class="wp-block-csstricks-code-block language-javascript" data-line=""><code markup="tt">grunt.initConfig({
bake: {
your_target: {
files: {
"dist/index.html": "app/index.html",
}
}
}
});</code></pre>



<p>Then your HTML can use this special syntax for includes:</p>



<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">...
&lt;body&gt;
&lt;!--(bake header.html)--&gt;

Content

&lt;!--(bake footer.html)--&gt;
&lt;/body&gt;
...</code></pre>


<h3 class="wp-block-heading" id="h-use-handlebars"><a href="#aa-use-handlebars" aria-hidden="true" class="aal_anchor" id="aa-use-handlebars"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Handlebars</h3>


<p>Handlebars <a href="https://handlebarsjs.com/partials.html" rel="noopener">has partials</a>.</p>



<p>You register them:</p>



<pre rel="JavaScript" class="wp-block-csstricks-code-block language-javascript" data-line=""><code markup="tt">Handlebars.registerPartial('myPartial', '{{name}}')</code></pre>



<p>Then use them:</p>



<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">{{&gt; myPartial }}</code></pre>



<p>There is also fancy features of this that allow for evaluation and passing data. You’ll still need a processor to run it, probably something like <a href="https://www.npmjs.com/package/gulp-handlebars" rel="noopener">gulp-handlebars</a>.</p>



<p>Speaking of templating languages which make use of curly braces… Mustache <a href="https://github.com/janl/mustache.js#include-templates" rel="noopener">has them, too</a>.</p>


<h3 class="wp-block-heading" id="h-use-pug"><a href="#aa-use-pug" aria-hidden="true" class="aal_anchor" id="aa-use-pug"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Pug</h3>


<p><a href="https://pugjs.org/" rel="noopener">Pug</a> is an HTML preprocessor that has a whole new syntax for HTML that is a bit more terse. <a href="https://pugjs.org/language/includes.html" rel="noopener">It’s got includes though</a>.</p>



<pre rel="Pug" class="wp-block-csstricks-code-block language-none" data-line=""><code markup="tt">...
body
include ./header.html"

p Content

include ./footer.html"

...</code></pre>



<p>Then you run it with something like <a href="https://www.npmjs.com/package/gulp-pug" rel="noopener">gulp-pug</a>.</p>


<h3 class="wp-block-heading" id="h-use-nunjucks"><a href="#aa-use-nunjucks" aria-hidden="true" class="aal_anchor" id="aa-use-nunjucks"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Nunjucks</h3>


<p><a href="https://css-tricks.com/killer-features-of-nunjucks/">I love me some Nunjucks!</a> <a href="https://mozilla.github.io/nunjucks/" rel="noopener">Nunjucks</a> has <a href="https://mozilla.github.io/nunjucks/templating.html#include" rel="noopener">includes</a>. You’d do it like this:</p>



<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">...
&lt;body&gt;
{% include "./header.html" %}

Content

{% include "./footer.html" %}
&lt;/body&gt;
...</code></pre>



<p>If you put that in a file called <code>index.njk</code>, you could process it with a simple Node script into index.html like this:</p>



<pre rel="JavaScript" class="wp-block-csstricks-code-block language-javascript" data-line=""><code markup="tt">const nunjucks = require("nunjucks");
const fs = require("fs");

fs.writeFile("index.html", nunjucks.render("index.njk"), function(err, data) {
if (err) console.log(err);
console.log("Compiled the Nunjucks, captain.");
});</code></pre>



<p>Or process it with something like <a href="https://www.npmjs.com/package/gulp-nunjucks" rel="noopener">gulp-nunjucks</a>.</p>



<p>11ty has <a href="https://www.11ty.io/docs/languages/nunjucks/" rel="noopener">Nunjucks built-in</a>, along with many of the other mentioned so far. Might be good for you if you’re actually building a little site.</p>


<h3 class="wp-block-heading" id="h-use-ajax"><a href="#aa-use-ajax" aria-hidden="true" class="aal_anchor" id="aa-use-ajax"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Ajax</h3>


<p>Say you had…</p>



<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;body&gt;
&lt;header&gt;&lt;/header&gt;
Content.
&lt;footer&gt;&lt;/footer&gt;

&lt;/body&gt;</code></pre>



<p>You could fetch the contents for the header and footer from respective files and dump the contents in.</p>



<pre rel="JavaScript" class="wp-block-csstricks-code-block language-javascript" data-line=""><code markup="tt">fetch("./header.html")
.then(response =&gt; {
return response.text()
})
.then(data =&gt; {
document.querySelector("header").innerHTML = data;
});

fetch("./footer.html")
.then(response =&gt; {
return response.text()
})
.then(data =&gt; {
document.querySelector("footer").innerHTML = data;
});</code></pre>



<p>Speaking of JavaScript… If you’re building your site using a JavaScript framework of just about any kind, building through components is kind of the main deal there and breaking parts you want to include in other files should be no problem. Some kind of <code>import Header from "./header.js";</code> and <code>&lt;Header /&gt;</code> is the territory you’d be in in React land.</p>


<h3 class="wp-block-heading" id="h-use-iframes"><a href="#aa-use-iframes" aria-hidden="true" class="aal_anchor" id="aa-use-iframes"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use iframes</h3>


<p>You could do this:</p>



<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;body&gt;
&lt;iframe src="./header.html"&gt;&lt;/iframe&gt;
Content.
&lt;iframe src="./footer.html"&gt;&lt;/iframe&gt;
&lt;/body&gt;</code></pre>



<p>But the content in those iframes does not share the same DOM, so it’s a bit weird, not to mention slow and awkward to style (since iframes don’t know the heights of their contents).</p>



<p><a href="https://www.filamentgroup.com/lab/html-includes/" rel="noopener">Scott Jehl documented a cool idea</a> though: You can have the iframe inject the content of itself onto the parent page then remove itself.</p>



<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;body&gt;
&lt;iframe src="header.html" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"&gt;&lt;/iframe&gt;
Content.
&lt;iframe src="footer.html" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"&gt;&lt;/iframe&gt;
&lt;/body&gt;</code></pre>



<p>Kolya Korruptis wrote in with this adaptation which will include more than the first child of the body in case your HTML file has that:</p>



<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;iframe src="included.html" onload="this.insertAdjacentHTML('afterend', (this.contentDocument.body||this.contentDocument).innerHTML);this.remove()"&gt;&lt;/iframe&gt;</code></pre>


<h3 class="wp-block-heading" id="use-jekyll"><a href="#aa-use-jekyll" aria-hidden="true" class="aal_anchor" id="aa-use-jekyll"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Jekyll</h3>


<p><a href="https://jekyllrb.com/" rel="noopener">Jekyll</a> is a Ruby-based static site generator with <a href="https://jekyllrb.com/docs/includes/" rel="noopener">includes</a>. You keep your includes in the <code>/_includes/</code> folder, then:</p>



<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;body&gt;
{% include header.html %}
Content.

{% include footer.html %}
&lt;/body&gt;</code></pre>



<p>Jekyll is a big one, so I’m calling it out here, but there are <a href="https://www.staticgen.com/" rel="noopener">a ton of static site generators</a> and I’d wager any of them can do includes.</p>


<h3 class="wp-block-heading" id="use-sergey"><a href="#aa-use-sergey" aria-hidden="true" class="aal_anchor" id="aa-use-sergey"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/#use-sergey"></a>Use Sergey</h3>


<p>OK, I’ll call out one more SSG because it’s new and super focused. <a href="https://sergey.cool/" rel="noopener">Sergey</a> has a web components style format:</p>



<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;body&gt;
&lt;sergey-import src="header" /&gt;

Content.

&lt;sergey-import src="footer" /&gt;
&lt;/body&gt;</code></pre>



<p>You’d name the files <code>header.html</code> and <code>footer.html</code> and put them in <code>/includes/</code> and then it’ll make a build with the includes processed when you run the npm script it has you do.</p>


<h3 class="wp-block-heading" id="use-apache-ssi"><a href="#aa-use-apache-ssi" aria-hidden="true" class="aal_anchor" id="aa-use-apache-ssi"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/#use-apache-ssi"></a>Use Apache SSI</h3>


<p>Apache, a super duper common web server, can <a href="https://httpd.apache.org/docs/2.4/mod/mod_include.html" rel="noopener">do includes</a>. You do it like this:</p>



<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">&lt;body&gt;
&lt;!--#include file="./header.html" --&gt;
Content
&lt;!--#include file="./footer.html" --&gt;
&lt;/body&gt;</code></pre>



<p>But you need the right Apache configuration to allow stuff. I tried my best to get a working demo going but didn’t have much luck.</p>



<p>I tried using <code>.htaccess</code> within a folder on an Apache server and flipping on what I thought was the right stuff:</p>



<pre rel="HTAccess" class="wp-block-csstricks-code-block language-none" data-line=""><code markup="tt">Options +Includes

AddType text/html .html
AddOutputFilter INCLUDES .html</code></pre>



<p>I’m sure there is some way to get it working though, and if you do, it’s kinda neat that it needs zero other dependencies.</p>


<h3 class="wp-block-heading" id="use-codekit"><a href="#aa-use-codekit" aria-hidden="true" class="aal_anchor" id="aa-use-codekit"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/#use-codekit"></a>Use CodeKit</h3>


<p>Mac only, but CodeKit has <a href="https://codekitapp.com/help/kit/" rel="noopener">a special language called Kit</a> it processes where 90% of the point of it is HTML includes. It uses special HTML comments:</p>



<pre rel="HTML" class="wp-block-csstricks-code-block language-markup" data-line=""><code markup="tt">...
&lt;body&gt;
&lt;!-- @import "./header.html" --&gt;

Content

&lt;!-- @import "./footer.html" --&gt;
&lt;/body&gt;
...</code></pre>


<h3 class="wp-block-heading" id="use-dreamweaver"><a href="#aa-use-dreamweaver" aria-hidden="true" class="aal_anchor" id="aa-use-dreamweaver"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/#use-dreamweaver"></a>Use Dreamweaver</h3>


<p>Lol jk. But it <a href="https://helpx.adobe.com/dreamweaver/using/server-side-includes.html" rel="noopener">really is a thing</a>. <a href="http://shop.pixelmill.com/support/al0/kb101502.htm" rel="noopener">DWTs</a>, baby.</p>


<h3 class="wp-block-heading" id="holy-crap"><a href="#aa-holy-crap" aria-hidden="true" class="aal_anchor" id="aa-holy-crap"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/#holy-crap"></a>Holy Crap</h3>


<p>That’s a lot of ways, isn’t it?</p>



<p>Like I said at the top, it’s very surprising to me that HTML itself hasn’t addressed this directly. Not that I think it would be a great idea for performance to have <code>&lt;include&gt;</code> statements that trigger network requests all over our code, but it seems in-line with the platform. Using ES6 imports directly without bundling isn’t a great idea always either, but we have them. <code>@import</code>ing CSS within CSS isn’t a great idea always, but we have it. If the platform had a native syntax, perhaps other tooling would key off that, much like JavaScript bundlers support the ES6 import format.</p>

+ 233
- 0
cache/2024/88df28660094efbc5a13bb09d70dfea6/index.html View File

@@ -0,0 +1,233 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="en">
<!-- Has to be within the first 1024 bytes, hence before the `title` element
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>HTML Includes That Work Today (archive) — David Larlet</title>
<meta name="description" content="Publication mise en cache pour en conserver une trace.">
<!-- That good ol' feed, subscribe :). -->
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
<!-- Generated from https://realfavicongenerator.net/ such a mess. -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
<link rel="manifest" href="/static/david/icons2/site.webmanifest">
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
<meta name="msapplication-TileColor" content="#f7f7f7">
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
<meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
<!-- Is that even respected? Retrospectively? What a shAItshow…
https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/ -->
<meta name="robots" content="noai, noimageai">
<!-- Documented, feel free to shoot an email. -->
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<script>
function toggleTheme(themeName) {
document.documentElement.classList.toggle(
'forced-dark',
themeName === 'dark'
)
document.documentElement.classList.toggle(
'forced-light',
themeName === 'light'
)
}
const selectedTheme = localStorage.getItem('theme')
if (selectedTheme !== 'undefined') {
toggleTheme(selectedTheme)
}
</script>

<meta name="robots" content="noindex, nofollow">
<meta content="origin-when-cross-origin" name="referrer">
<!-- Canonical URL for SEO purposes -->
<link rel="canonical" href="https://www.filamentgroup.com/lab/html-includes/">

<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">


<article>
<header>
<h1>HTML Includes That Work Today</h1>
</header>
<nav>
<p class="center">
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="https://www.filamentgroup.com/lab/html-includes/" title="Lien vers le contenu original">Source originale</a>
<br>
Mis en cache le 2024-02-19
</p>
</nav>
<hr>
<p class="note">Note: this post describes an experimental technique that we still need to test for performance implications. It may end up being a useful tool, and it may end up being a practice we won't recommend. Either way, it's fascinating to us that it works!</p>
<p>As long as I have been working on the web, I’ve desired a simple HTML-driven means of including the contents of another file directly into the page. For example, I often want to append additional HTML to a page after it is delivered, or embed the contents of an SVG file so that we can animate and style its elements. Typically here at Filament, we have achieved this embedding by either <a href="https://www.filamentgroup.com/lab/ajax-includes-modular-content">using JavaScript to fetch a file and append its contents</a> to a particular element, or by <a href="https://www.filamentgroup.com/lab/inlining-cache">including the file on the server side</a>, but in many cases, neither of those approaches is quite what we want.</p>
<p>This week I was thinking about ways I might be able to achieve this using some of the new <code>fetch</code>-related markup patterns, like <code>rel="preload"</code>, or HTML imports, but I kept coming back to the same conclusion that none of these give you easy access to the contents of the fetched file. Then I thought, perhaps a good old <code>iframe</code> could be a nice primitive for the pattern, assuming the browser would allow me to retrieve the <code>iframe</code>’s contents in the parent document. As it turns out, it sure would!</p>
<p><span class="heading-wrapper"></p>
<h2 id="a-quick-demo%3A-including-svg" tabindex="-1">A Quick Demo: including SVG</h2>
<p></span></p>
<p>Below is an inline (embedded) SVG graphic. It was loaded from an external file called <a href="/images/includespost/signal.svg"><code>signal.svg</code></a>.</p>

<p>To load and embed the SVG file, I used the following markup:</p>
<pre><code>&lt;iframe src="signal.svg" onload="this.before((this.contentDocument.body || this.contentDocument).children[0]);this.remove()"&gt;&lt;/iframe&gt;
</code></pre>
<p>Despite the fact that this markup starts out as an <code>iframe</code>, if you inspect the graphic above using developer tools, you’ll see the SVG markup for the icon, inlined right in the HTML DOM, with no <code>iframe</code> element to be found. This is because the code uses an <code>iframe</code> to load the file, and an <code>onload</code> event to inject the <code>iframe</code>’s content just before the <code>iframe</code> in the HTML, before deleting the <code>iframe</code> itself.</p>
<p>The approach also works with an <code>object</code> element, which is commonly used to reference SVG anyway, so I think that’s particularly nice. With an <code>object</code>, the <code>src</code> attribute needs to be <code>data</code> instead:</p>
<pre><code>&lt;object data="signal.svg" onload="this.before((this.contentDocument.body || this.contentDocument).children[0]);this.remove()"&gt;&lt;/object&gt;
</code></pre>
<p><span class="heading-wrapper"></p>
<h3 id="another-demo%3A-including-another-html-file" tabindex="-1">Another demo: including another HTML file</h3>
<p></span></p>
<p>Maybe even more useful… here’s an example that uses HTML rather than SVG!</p>

<p>It was loaded using the following markup:</p>
<pre><code>&lt;iframe src="/images/includespost/htmlexample.html" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"&gt;&lt;/iframe&gt;
</code></pre>
<p>One note about this one: you might have noticed that the markup snippet checks for either the <code>contentDocument.body</code> or just the <code>contentDocument</code>. This is a check to normalize between HTML and SVG includes. It’s necessary because even though the HTML file itself contains nothing more than a paragraph element, the browser creates a full HTML document to surround that paragraph, complete with an HTML element, a head, a body, etc. So the snippet tries to get the <code>iframe</code>’s <code>body</code> element if it exists, and if not, it goes for the entire document.</p>
<p>Notably, if you’re importing an HTML file that contains more than one element in it, I’d recommend wrapping it all in a <code>div</code> to keep the <code>iframe</code> markup able to simply look for the first childnode in the <code>body</code>.</p>
<p><span class="heading-wrapper"></p>
<h2 id="benefits!" tabindex="-1">Benefits!</h2>
<p></span></p>
<p>There are some nice benefits to this pattern over others we’ve used in the past:</p>
<ul>
<li>It’s declarative. Unlike most custom JavaScript approaches, this one is HTML-driven and its purpose in the markup is pretty clear at a glance.</li>
<li>It works for HTML or SVG. I’m not sure what else you’d want to include like this client-side, but this covers my own wishlist at least.</li>
<li>It’s asynchronous! The content will load in without blocking page rendering, as is the nature of an <code>iframe</code>.</li>
<li>It’s cache-friendly. Unlike server-side embedding, this pattern lets us include an external file while allowing the file to be cached naturally for subsequent reuse. (With server-side included content, <a href="https://www.filamentgroup.com/lab/inlining-cache">client-side caching is possible, but harder to do</a>).</li>
<li>It will show the content regardless of whether JavaScript runs at all, since that’s what an <code>iframe</code> is designed to do. The JavaScript is there to move the <code>iframe</code>’s content into the parent document, but if anythign fails, you’ll still see the included content.</li>
<li>It leaves no trace: the <code>iframe</code> is deleted after it imports the content into the page. Note: you may want to give the <code>iframe</code> a <code>border:0;</code> or even safely hide it while loading (perhaps showing it again via an onerror event?).</li>
<li>It works across browsers: in my brief testing so far, this works in Chrome, Firefox, Safari, and Edge. IE will show the fallback content in the <code>iframe</code>, but I think I can probably get IE support to work by adjusting the JS in the <code>onload</code> handler, as it’s currently using syntax that IE doesn’t like. With a little tweaking, I expect IE support will be possible.</li>
<li>It could even be wrapped in a web component if you’d like, as <a href="https://codepen.io/andybelldesign/project/full/DyVyPG">Andy Bell has cleverly demonstrated here</a> (which is a little cleaner markup, but a little more fragile as far as JS dependence goes).</li>
</ul>
<p>It’s fun to think of other possible uses… Perhaps you could pull in HTML modules along with their relevant CSS link. Or embed a tweet or code examples in documentation or a blog post. It could probably even be used to load and apply a regular <code>rel=stylesheet</code> link asynchronously, and at a low priority, which is otherwise surprisingly hard to do (note: I didn’t test this idea much to say for sure).</p>
<p><span class="heading-wrapper"></p>
<h2 id="can-it-be-lazy-loaded-too%3F-yes%2C-soon!" tabindex="-1">Can it be lazy loaded too? Yes, soon!</h2>
<p></span></p>
<p>Another nice thing about using an <code>iframe</code> for this pattern is that <code>iframe</code>s will soon gain the native ability to lazy-load when they enter the viewport. This will be achieved using the <code>loading="lazy"</code> attribute, which also will also work for <code>img</code> elements. Here’s how that markup will look:</p>
<pre><code>&lt;iframe src="signal.svg" loading="lazy" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"&gt;&lt;/iframe&gt;
</code></pre>
<p><span class="heading-wrapper"></p>
<h2 id="possible-drawbacks" tabindex="-1">Possible Drawbacks</h2>
<p></span></p>
<p><code>Iframe</code>s are very commonly used on the web, but it’s possible that overusing them in a page could lead to a performance or memory consumption problem. It’s possible that using this for all the icons on a page would be too heavy, for example, but it could be nice to use for just the particular icons that need to be animated and styled. I’ll have to do more testing before I can say.</p>
<p>There’s also the possibility of XSS problems, though I’m not sure this is any different than other situations where you’d want to be careful with external content. The usual safechecks apply, and it’s probably best to consider it a same-domain technique, though again I’m not sure on that either.</p>
<p>For now, this approach feels promising as an improvement over prior methods we’ve used for including another file directly into a page.</p>
<p><span class="heading-wrapper"></p>
<h2 id="feedback%3F" tabindex="-1">Feedback?</h2>
<p></span></p>
<p>We’ll be continuing to test this pattern and may post a followup soon if we find anything interesting. If you have any feedback or ideas, feel free to <a href="https://twitter.com/filamentgroup">hit us up on twitter</a>. Thanks for reading!</p>
<p><small><b>Note:</b> This post is a followup and improvement on <a href="https://twitter.com/scottjehl/status/1116761767617519617">an earlier experiment I posted on Codepen</a>.</small></p>
</article>


<hr>

<footer>
<p>
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
</svg> Suivre</a> •
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
</svg> Pro</a> •
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
</svg> Email</a> •
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
</svg> Légal</abbr>
</p>
<template id="theme-selector">
<form>
<fieldset>
<legend><svg class="icon icon-brightness-contrast">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
</svg> Thème</legend>
<label>
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
</label>
<label>
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé
</label>
<label>
<input type="radio" value="light" name="chosen-color-scheme"> Clair
</label>
</fieldset>
</form>
</template>
</footer>
<script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
<script>
function loadThemeForm(templateName) {
const themeSelectorTemplate = document.querySelector(templateName)
const form = themeSelectorTemplate.content.firstElementChild
themeSelectorTemplate.replaceWith(form)

form.addEventListener('change', (e) => {
const chosenColorScheme = e.target.value
localStorage.setItem('theme', chosenColorScheme)
toggleTheme(chosenColorScheme)
})

const selectedTheme = localStorage.getItem('theme')
if (selectedTheme && selectedTheme !== 'undefined') {
form.querySelector(`[value="${selectedTheme}"]`).checked = true
}
}

const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
window.addEventListener('load', () => {
let hasDarkRules = false
for (const styleSheet of Array.from(document.styleSheets)) {
let mediaRules = []
for (const cssRule of styleSheet.cssRules) {
if (cssRule.type !== CSSRule.MEDIA_RULE) {
continue
}
// WARNING: Safari does not have/supports `conditionText`.
if (cssRule.conditionText) {
if (cssRule.conditionText !== prefersColorSchemeDark) {
continue
}
} else {
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
continue
}
}
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
}

// WARNING: do not try to insert a Rule to a styleSheet you are
// currently iterating on, otherwise the browser will be stuck
// in a infinite loop…
for (const mediaRule of mediaRules) {
styleSheet.insertRule(mediaRule.cssText)
hasDarkRules = true
}
}
if (hasDarkRules) {
loadThemeForm('#theme-selector')
}
})
</script>
</body>
</html>

+ 66
- 0
cache/2024/88df28660094efbc5a13bb09d70dfea6/index.md View File

@@ -0,0 +1,66 @@
title: HTML Includes That Work Today
url: https://www.filamentgroup.com/lab/html-includes/
hash_url: 88df28660094efbc5a13bb09d70dfea6
archive_date: 2024-02-19
og_image: https://www.filamentgroup.com/images/icons/twittercard.png
description: Read this page on the Filament Group website
favicon: https://www.filamentgroup.com/images/icons/favicon-32x32.png
language: en_US

<p class="note">Note: this post describes an experimental technique that we still need to test for performance implications. It may end up being a useful tool, and it may end up being a practice we won't recommend. Either way, it's fascinating to us that it works!</p>
<p>As long as I have been working on the web, I’ve desired a simple HTML-driven means of including the contents of another file directly into the page. For example, I often want to append additional HTML to a page after it is delivered, or embed the contents of an SVG file so that we can animate and style its elements. Typically here at Filament, we have achieved this embedding by either <a href="https://www.filamentgroup.com/lab/ajax-includes-modular-content">using JavaScript to fetch a file and append its contents</a> to a particular element, or by <a href="https://www.filamentgroup.com/lab/inlining-cache">including the file on the server side</a>, but in many cases, neither of those approaches is quite what we want.</p>
<p>This week I was thinking about ways I might be able to achieve this using some of the new <code>fetch</code>-related markup patterns, like <code>rel="preload"</code>, or HTML imports, but I kept coming back to the same conclusion that none of these give you easy access to the contents of the fetched file. Then I thought, perhaps a good old <code>iframe</code> could be a nice primitive for the pattern, assuming the browser would allow me to retrieve the <code>iframe</code>’s contents in the parent document. As it turns out, it sure would!</p>
<span class="heading-wrapper">
<h2 id="a-quick-demo%3A-including-svg" tabindex="-1">A Quick Demo: including SVG</h2>
</span>
<p>Below is an inline (embedded) SVG graphic. It was loaded from an external file called <a href="/images/includespost/signal.svg"><code>signal.svg</code></a>.</p>

<p>To load and embed the SVG file, I used the following markup:</p>
<pre><code>&lt;iframe src="signal.svg" onload="this.before((this.contentDocument.body || this.contentDocument).children[0]);this.remove()"&gt;&lt;/iframe&gt;
</code></pre>
<p>Despite the fact that this markup starts out as an <code>iframe</code>, if you inspect the graphic above using developer tools, you’ll see the SVG markup for the icon, inlined right in the HTML DOM, with no <code>iframe</code> element to be found. This is because the code uses an <code>iframe</code> to load the file, and an <code>onload</code> event to inject the <code>iframe</code>’s content just before the <code>iframe</code> in the HTML, before deleting the <code>iframe</code> itself.</p>
<p>The approach also works with an <code>object</code> element, which is commonly used to reference SVG anyway, so I think that’s particularly nice. With an <code>object</code>, the <code>src</code> attribute needs to be <code>data</code> instead:</p>
<pre><code>&lt;object data="signal.svg" onload="this.before((this.contentDocument.body || this.contentDocument).children[0]);this.remove()"&gt;&lt;/object&gt;
</code></pre>
<span class="heading-wrapper">
<h3 id="another-demo%3A-including-another-html-file" tabindex="-1">Another demo: including another HTML file</h3>
</span>
<p>Maybe even more useful… here’s an example that uses HTML rather than SVG!</p>

<p>It was loaded using the following markup:</p>
<pre><code>&lt;iframe src="/images/includespost/htmlexample.html" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"&gt;&lt;/iframe&gt;
</code></pre>
<p>One note about this one: you might have noticed that the markup snippet checks for either the <code>contentDocument.body</code> or just the <code>contentDocument</code>. This is a check to normalize between HTML and SVG includes. It’s necessary because even though the HTML file itself contains nothing more than a paragraph element, the browser creates a full HTML document to surround that paragraph, complete with an HTML element, a head, a body, etc. So the snippet tries to get the <code>iframe</code>’s <code>body</code> element if it exists, and if not, it goes for the entire document.</p>
<p>Notably, if you’re importing an HTML file that contains more than one element in it, I’d recommend wrapping it all in a <code>div</code> to keep the <code>iframe</code> markup able to simply look for the first childnode in the <code>body</code>.</p>
<span class="heading-wrapper">
<h2 id="benefits!" tabindex="-1">Benefits!</h2>
</span>
<p>There are some nice benefits to this pattern over others we’ve used in the past:</p>
<ul>
<li>It’s declarative. Unlike most custom JavaScript approaches, this one is HTML-driven and its purpose in the markup is pretty clear at a glance.</li>
<li>It works for HTML or SVG. I’m not sure what else you’d want to include like this client-side, but this covers my own wishlist at least.</li>
<li>It’s asynchronous! The content will load in without blocking page rendering, as is the nature of an <code>iframe</code>.</li>
<li>It’s cache-friendly. Unlike server-side embedding, this pattern lets us include an external file while allowing the file to be cached naturally for subsequent reuse. (With server-side included content, <a href="https://www.filamentgroup.com/lab/inlining-cache">client-side caching is possible, but harder to do</a>).</li>
<li>It will show the content regardless of whether JavaScript runs at all, since that’s what an <code>iframe</code> is designed to do. The JavaScript is there to move the <code>iframe</code>’s content into the parent document, but if anythign fails, you’ll still see the included content.</li>
<li>It leaves no trace: the <code>iframe</code> is deleted after it imports the content into the page. Note: you may want to give the <code>iframe</code> a <code>border:0;</code> or even safely hide it while loading (perhaps showing it again via an onerror event?).</li>
<li>It works across browsers: in my brief testing so far, this works in Chrome, Firefox, Safari, and Edge. IE will show the fallback content in the <code>iframe</code>, but I think I can probably get IE support to work by adjusting the JS in the <code>onload</code> handler, as it’s currently using syntax that IE doesn’t like. With a little tweaking, I expect IE support will be possible.</li>
<li>It could even be wrapped in a web component if you’d like, as <a href="https://codepen.io/andybelldesign/project/full/DyVyPG">Andy Bell has cleverly demonstrated here</a> (which is a little cleaner markup, but a little more fragile as far as JS dependence goes).</li>
</ul>
<p>It’s fun to think of other possible uses… Perhaps you could pull in HTML modules along with their relevant CSS link. Or embed a tweet or code examples in documentation or a blog post. It could probably even be used to load and apply a regular <code>rel=stylesheet</code> link asynchronously, and at a low priority, which is otherwise surprisingly hard to do (note: I didn’t test this idea much to say for sure).</p>
<span class="heading-wrapper">
<h2 id="can-it-be-lazy-loaded-too%3F-yes%2C-soon!" tabindex="-1">Can it be lazy loaded too? Yes, soon!</h2>
</span>
<p>Another nice thing about using an <code>iframe</code> for this pattern is that <code>iframe</code>s will soon gain the native ability to lazy-load when they enter the viewport. This will be achieved using the <code>loading="lazy"</code> attribute, which also will also work for <code>img</code> elements. Here’s how that markup will look:</p>
<pre><code>&lt;iframe src="signal.svg" loading="lazy" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"&gt;&lt;/iframe&gt;
</code></pre>
<span class="heading-wrapper">
<h2 id="possible-drawbacks" tabindex="-1">Possible Drawbacks</h2>
</span>
<p><code>Iframe</code>s are very commonly used on the web, but it’s possible that overusing them in a page could lead to a performance or memory consumption problem. It’s possible that using this for all the icons on a page would be too heavy, for example, but it could be nice to use for just the particular icons that need to be animated and styled. I’ll have to do more testing before I can say.</p>
<p>There’s also the possibility of XSS problems, though I’m not sure this is any different than other situations where you’d want to be careful with external content. The usual safechecks apply, and it’s probably best to consider it a same-domain technique, though again I’m not sure on that either.</p>
<p>For now, this approach feels promising as an improvement over prior methods we’ve used for including another file directly into a page.</p>
<span class="heading-wrapper">
<h2 id="feedback%3F" tabindex="-1">Feedback?</h2>
</span>
<p>We’ll be continuing to test this pattern and may post a followup soon if we find anything interesting. If you have any feedback or ideas, feel free to <a href="https://twitter.com/filamentgroup">hit us up on twitter</a>. Thanks for reading!</p>
<p><small><b>Note:</b> This post is a followup and improvement on <a href="https://twitter.com/scottjehl/status/1116761767617519617">an earlier experiment I posted on Codepen</a>.</small></p>

+ 215
- 0
cache/2024/a005801f0e596f9ecb99037a992ecc1b/index.html View File

@@ -0,0 +1,215 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="en">
<!-- Has to be within the first 1024 bytes, hence before the `title` element
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>What’s the fun in writing on the internet anymore? (archive) — David Larlet</title>
<meta name="description" content="Publication mise en cache pour en conserver une trace.">
<!-- That good ol' feed, subscribe :). -->
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
<!-- Generated from https://realfavicongenerator.net/ such a mess. -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
<link rel="manifest" href="/static/david/icons2/site.webmanifest">
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
<meta name="msapplication-TileColor" content="#f7f7f7">
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
<meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
<!-- Is that even respected? Retrospectively? What a shAItshow…
https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/ -->
<meta name="robots" content="noai, noimageai">
<!-- Documented, feel free to shoot an email. -->
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<script>
function toggleTheme(themeName) {
document.documentElement.classList.toggle(
'forced-dark',
themeName === 'dark'
)
document.documentElement.classList.toggle(
'forced-light',
themeName === 'light'
)
}
const selectedTheme = localStorage.getItem('theme')
if (selectedTheme !== 'undefined') {
toggleTheme(selectedTheme)
}
</script>

<meta name="robots" content="noindex, nofollow">
<meta content="origin-when-cross-origin" name="referrer">
<!-- Canonical URL for SEO purposes -->
<link rel="canonical" href="https://jamesshelley.com/blog/writing-on-the-internet.html">

<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">


<article>
<header>
<h1>What’s the fun in writing on the internet anymore?</h1>
</header>
<nav>
<p class="center">
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="https://jamesshelley.com/blog/writing-on-the-internet.html" title="Lien vers le contenu original">Source originale</a>
<br>
Mis en cache le 2024-02-19
</p>
</nav>
<hr>
<p>You are reading some words on the internet.</p>

<p>Think about all the things you could do with these words.</p>

<p>You could copy and paste this article into ChatGPT and say, “Please rewrite and paraphrase this blog post in such a way as to keep its main points and observations, but substantively reconfigure the text to make the original version undetectable.” And then, just like that, you have content for your own blog. So easy.</p>

<p>Or you could just copy the contents of this page and paste it into a site like plagiarism-remover.com so you could, as advertised, “Easily Convert Your Plagiarism article Into Plagiarism Free article.” Or you could use Spinbot. Or Jasper. Or QuillBot. Or Paraphraser. And so on.</p>

<p>You can now spin up <a href="https://slate.com/technology/2023/01/chat-gpt-openai-jasper-hugging-face-plagiarism-big-technology.html">new, “original” articles</a> faster and easier than even <em>reading</em> the originals. This is a dizzying and dumbfounding new reality, when you stop and think about it: <em>automated plagiarism is now more efficient than reading itself.</em></p>

<p>All the same, if you want to skip the whole paraphrase/spin step, you could instead <a href="https://jamesshelley.com/blog/on-being-plagiarized.html">copy and paste this article verbatim into a newsletter served up behind a paywall</a>. This strategy drastically reduces the odds that it will be recognized as plagiarism on the open web. And, hey, why not make a few extra bucks? (Perhaps ironically, turbo-charged content spinning is so pervasive that <a href="https://www.niemanlab.org/2024/02/six-months-in-journalist-owned-tech-publication-404-media-is-profitable/">evermore sites require user logins just to access content</a>. This seems vicious: repurposing content engenders the proliferation of walled gardens and walled gardens, in turn, engenders the proliferation of repurposed content.)</p>

<p>In summary, it feels like the fate of words on the internet is to be paraphrased. Emerging tools like <a href="https://www.perplexity.ai/search/google-search-results-ET4ll7tdT6axzwgifCC3Gw?s=c" rel="nofollow">Perplexity.ai respond to quiries with fulsome answers that do not require users to even click off the site</a>. In other words, search itself is becoming the delivery of paraphrase and summary. Waning are the days of sifting through “search results” to find a specific source. Henceforth, digital words are little more than raw data to be crunched, processed, and served up by third-party intermediaries.</p>

<p>The “moral rights” of the author. <em>Copyright</em>. <em>Attribution</em>. We have grown to assume these concepts as givens, but they are rapidly sliding into practical irrelevance in the age of AI and paywalls. To put any thoughtful labour into crafting words online today is to watch them get sucked up, repurposed, and often monetized by someone else. It feels a bit like a digital wasteland; overrun with pirates, replete with armies of robots regurgitating everything into a gooey cocktail of digital sludge.</p>

<p>It is interesting to speculate about the future. It seems like people might eventually grow skeptical about investing their personal creativity in such a space, right? Will anyone bother writing on the internet when they know their words will be pilfered and junkified? What happens to the craft of <em>writing itself</em> when our de facto global platform for sharing text no longer reinforces or recognizes the role or rights of <em>authorship</em>?</p>

<p>To ponder this question, we can look back. In some ways, today’s internet evermore reminds of the world I encountered back in classical studies. There are bits of papyrus and parchment are flying around everywhere. Some texts claim attribution, some are anonymous, and a lot are pseudonymous—and you can’t tease any of this apart with any certainty. There are competing manuscripts, copies of copies, and significant “versioning issues” everywhere you look. Ultimately, the credence and authority you give to any specific text typically reflects the trust your community bestows on it. The only words that survive are the ones that get copied. This all sounds strangely familiar, yes?</p>

<p>If you were lucky and wealthy enough to write in antiquity, your scribbles went out into the world to completely unknown ends. Authorship, accompanied by newfangled attributions of moral and legal entitlements, is not yet a refined concept. Once you “release” the words, you categorically relinquish control of them. And you are fully aware that the more clever and helpful your words are to others, the more likely it is that future readers will attribute your words to someone else.</p>

<p><em>Sic semper erat, et sic semper erit.</em> The better your words, the more likely it is that somebody will poach them. Somebody will probably “paraphrase” your work beyond detection. Somebody will “republish” it as their “original.” Somebody else will train their large language model on your text and serve it up without citations or footnotes. To write on today’s internet and assume universal respect for your “moral rights of authorship” is an act of grand delusion.</p>

<p>You might as well write anonymous papyrus fragments.</p>

<p>And this is the point.</p>

<p>None of this really matters.</p>

<p>Whether papyrus or the internet, humans doggedly write for influence, status, wealth, conviction, and pleasure. But the so-called sanctity of “authorship” is only a very recent idea. These “rights” of authorship are only true if they are enforced. They are a kind of fiction that only make sense in occasional times, places, and cultures. For the next chapter of the human experiment, I wonder if “authorship” will again recede into the background, as it often seems to do in times of disruptive changes in communication technology.</p>

<p>But the banishment of the author doesn’t mean writing ends. Writers still write even when “authorship” functionally means nothing. And what they write still influences their world, with or without the universe dutifully paying homage to their bylines. In the long arcs of history, <em>what</em> is written typically goes on to mean much more than <em>who</em> wrote it. The future, like today, is built on ideas, not on the people who had them, because people die but ideas never stop evolving.</p>

<p>And the future <em>needs</em> ideas—not auto-generated “summaries” of old ones.</p>

<p>So, what’s the fun of writing on the internet anymore? Well, if your aim is to be respected as an author, there’s probably not much fun to be had here at all. Don’t write online for fame and glory. Oblivion, obscurity and exploitation are all but guaranteed. Write here because <em>ideas</em> matter, not authorship. Write here because the more robots, pirates, and single-minded trolls swallow up cyberspace, the more we need independent writing in order to think new thoughts in the future — even if your words are getting dished up and plated by an algorithm.</p>

<p>Those who <em>write</em> — those who add ideas instead of paraphrasing and regurgitating them — inform the lexicology and mental corpus of how we think in the future. Indeed, the point isn’t “being an author,” but contributing one’s perspective, even if one’s personal identity is silenced, erased, and anonymized along the way.</p>
</article>


<hr>

<footer>
<p>
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
</svg> Suivre</a> •
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
</svg> Pro</a> •
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
</svg> Email</a> •
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
</svg> Légal</abbr>
</p>
<template id="theme-selector">
<form>
<fieldset>
<legend><svg class="icon icon-brightness-contrast">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
</svg> Thème</legend>
<label>
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
</label>
<label>
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé
</label>
<label>
<input type="radio" value="light" name="chosen-color-scheme"> Clair
</label>
</fieldset>
</form>
</template>
</footer>
<script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
<script>
function loadThemeForm(templateName) {
const themeSelectorTemplate = document.querySelector(templateName)
const form = themeSelectorTemplate.content.firstElementChild
themeSelectorTemplate.replaceWith(form)

form.addEventListener('change', (e) => {
const chosenColorScheme = e.target.value
localStorage.setItem('theme', chosenColorScheme)
toggleTheme(chosenColorScheme)
})

const selectedTheme = localStorage.getItem('theme')
if (selectedTheme && selectedTheme !== 'undefined') {
form.querySelector(`[value="${selectedTheme}"]`).checked = true
}
}

const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
window.addEventListener('load', () => {
let hasDarkRules = false
for (const styleSheet of Array.from(document.styleSheets)) {
let mediaRules = []
for (const cssRule of styleSheet.cssRules) {
if (cssRule.type !== CSSRule.MEDIA_RULE) {
continue
}
// WARNING: Safari does not have/supports `conditionText`.
if (cssRule.conditionText) {
if (cssRule.conditionText !== prefersColorSchemeDark) {
continue
}
} else {
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
continue
}
}
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
}

// WARNING: do not try to insert a Rule to a styleSheet you are
// currently iterating on, otherwise the browser will be stuck
// in a infinite loop…
for (const mediaRule of mediaRules) {
styleSheet.insertRule(mediaRule.cssText)
hasDarkRules = true
}
}
if (hasDarkRules) {
loadThemeForm('#theme-selector')
}
})
</script>
</body>
</html>

+ 48
- 0
cache/2024/a005801f0e596f9ecb99037a992ecc1b/index.md View File

@@ -0,0 +1,48 @@
title: What’s the fun in writing on the internet anymore?
url: https://jamesshelley.com/blog/writing-on-the-internet.html
hash_url: a005801f0e596f9ecb99037a992ecc1b
archive_date: 2024-02-19
og_image: https://jamesshelley.com/images/favicon.png
description: The moment you release your words, you relinquish all control.
favicon: https://jamesshelley.com/images/favicon.png
language: en_US

<p>You are reading some words on the internet.</p>

<p>Think about all the things you could do with these words.</p>

<p>You could copy and paste this article into ChatGPT and say, “Please rewrite and paraphrase this blog post in such a way as to keep its main points and observations, but substantively reconfigure the text to make the original version undetectable.” And then, just like that, you have content for your own blog. So easy.</p>

<p>Or you could just copy the contents of this page and paste it into a site like plagiarism-remover.com so you could, as advertised, “Easily Convert Your Plagiarism article Into Plagiarism Free article.” Or you could use Spinbot. Or Jasper. Or QuillBot. Or Paraphraser. And so on.</p>

<p>You can now spin up <a href="https://slate.com/technology/2023/01/chat-gpt-openai-jasper-hugging-face-plagiarism-big-technology.html">new, “original” articles</a> faster and easier than even <em>reading</em> the originals. This is a dizzying and dumbfounding new reality, when you stop and think about it: <em>automated plagiarism is now more efficient than reading itself.</em></p>

<p>All the same, if you want to skip the whole paraphrase/spin step, you could instead <a href="https://jamesshelley.com/blog/on-being-plagiarized.html">copy and paste this article verbatim into a newsletter served up behind a paywall</a>. This strategy drastically reduces the odds that it will be recognized as plagiarism on the open web. And, hey, why not make a few extra bucks? (Perhaps ironically, turbo-charged content spinning is so pervasive that <a href="https://www.niemanlab.org/2024/02/six-months-in-journalist-owned-tech-publication-404-media-is-profitable/">evermore sites require user logins just to access content</a>. This seems vicious: repurposing content engenders the proliferation of walled gardens and walled gardens, in turn, engenders the proliferation of repurposed content.)</p>

<p>In summary, it feels like the fate of words on the internet is to be paraphrased. Emerging tools like <a href="https://www.perplexity.ai/search/google-search-results-ET4ll7tdT6axzwgifCC3Gw?s=c" rel="nofollow">Perplexity.ai respond to quiries with fulsome answers that do not require users to even click off the site</a>. In other words, search itself is becoming the delivery of paraphrase and summary. Waning are the days of sifting through “search results” to find a specific source. Henceforth, digital words are little more than raw data to be crunched, processed, and served up by third-party intermediaries.</p>

<p>The “moral rights” of the author. <em>Copyright</em>. <em>Attribution</em>. We have grown to assume these concepts as givens, but they are rapidly sliding into practical irrelevance in the age of AI and paywalls. To put any thoughtful labour into crafting words online today is to watch them get sucked up, repurposed, and often monetized by someone else. It feels a bit like a digital wasteland; overrun with pirates, replete with armies of robots regurgitating everything into a gooey cocktail of digital sludge.</p>

<p>It is interesting to speculate about the future. It seems like people might eventually grow skeptical about investing their personal creativity in such a space, right? Will anyone bother writing on the internet when they know their words will be pilfered and junkified? What happens to the craft of <em>writing itself</em> when our de facto global platform for sharing text no longer reinforces or recognizes the role or rights of <em>authorship</em>?</p>

<p>To ponder this question, we can look back. In some ways, today’s internet evermore reminds of the world I encountered back in classical studies. There are bits of papyrus and parchment are flying around everywhere. Some texts claim attribution, some are anonymous, and a lot are pseudonymous—and you can’t tease any of this apart with any certainty. There are competing manuscripts, copies of copies, and significant “versioning issues” everywhere you look. Ultimately, the credence and authority you give to any specific text typically reflects the trust your community bestows on it. The only words that survive are the ones that get copied. This all sounds strangely familiar, yes?</p>

<p>If you were lucky and wealthy enough to write in antiquity, your scribbles went out into the world to completely unknown ends. Authorship, accompanied by newfangled attributions of moral and legal entitlements, is not yet a refined concept. Once you “release” the words, you categorically relinquish control of them. And you are fully aware that the more clever and helpful your words are to others, the more likely it is that future readers will attribute your words to someone else.</p>

<p><em>Sic semper erat, et sic semper erit.</em> The better your words, the more likely it is that somebody will poach them. Somebody will probably “paraphrase” your work beyond detection. Somebody will “republish” it as their “original.” Somebody else will train their large language model on your text and serve it up without citations or footnotes. To write on today’s internet and assume universal respect for your “moral rights of authorship” is an act of grand delusion.</p>

<p>You might as well write anonymous papyrus fragments.</p>

<p>And this is the point.</p>

<p>None of this really matters.</p>

<p>Whether papyrus or the internet, humans doggedly write for influence, status, wealth, conviction, and pleasure. But the so-called sanctity of “authorship” is only a very recent idea. These “rights” of authorship are only true if they are enforced. They are a kind of fiction that only make sense in occasional times, places, and cultures. For the next chapter of the human experiment, I wonder if “authorship” will again recede into the background, as it often seems to do in times of disruptive changes in communication technology.</p>

<p>But the banishment of the author doesn’t mean writing ends. Writers still write even when “authorship” functionally means nothing. And what they write still influences their world, with or without the universe dutifully paying homage to their bylines. In the long arcs of history, <em>what</em> is written typically goes on to mean much more than <em>who</em> wrote it. The future, like today, is built on ideas, not on the people who had them, because people die but ideas never stop evolving.</p>

<p>And the future <em>needs</em> ideas—not auto-generated “summaries” of old ones.</p>

<p>So, what’s the fun of writing on the internet anymore? Well, if your aim is to be respected as an author, there’s probably not much fun to be had here at all. Don’t write online for fame and glory. Oblivion, obscurity and exploitation are all but guaranteed. Write here because <em>ideas</em> matter, not authorship. Write here because the more robots, pirates, and single-minded trolls swallow up cyberspace, the more we need independent writing in order to think new thoughts in the future — even if your words are getting dished up and plated by an algorithm.</p>

<p>Those who <em>write</em> — those who add ideas instead of paraphrasing and regurgitating them — inform the lexicology and mental corpus of how we think in the future. Indeed, the point isn’t “being an author,” but contributing one’s perspective, even if one’s personal identity is silenced, erased, and anonymized along the way.</p>

+ 8
- 0
cache/2024/index.html View File

@@ -128,6 +128,8 @@
<li><a href="/david/cache/2024/9750840b448f07a2f2594bb25da23836/" title="Accès à l’article dans le cache local : Tech doesn’t make our lives easier. It makes them faster">Tech doesn’t make our lives easier. It makes them faster</a> (<a href="https://brettscott.substack.com/p/tech-doesnt-make-our-lives-easier" title="Accès à l’article original distant : Tech doesn’t make our lives easier. It makes them faster">original</a>)</li>
<li><a href="/david/cache/2024/88df28660094efbc5a13bb09d70dfea6/" title="Accès à l’article dans le cache local : HTML Includes That Work Today">HTML Includes That Work Today</a> (<a href="https://www.filamentgroup.com/lab/html-includes/" title="Accès à l’article original distant : HTML Includes That Work Today">original</a>)</li>
<li><a href="/david/cache/2024/b80f5159ee7ac70bcaa6a9fde16c2408/" title="Accès à l’article dans le cache local : Behind the controversy at Basecamp">Behind the controversy at Basecamp</a> (<a href="https://www.theverge.com/2021/4/27/22406673/basecamp-political-speech-policy-controversy" title="Accès à l’article original distant : Behind the controversy at Basecamp">original</a>)</li>
<li><a href="/david/cache/2024/34fec23081019abd741e0578b050c40e/" title="Accès à l’article dans le cache local : Tools shape practices shape tools…">Tools shape practices shape tools…</a> (<a href="https://www.quaternum.net/2024/01/08/tools-shape-practices-shape-tools/" title="Accès à l’article original distant : Tools shape practices shape tools…">original</a>)</li>
@@ -138,6 +140,8 @@
<li><a href="/david/cache/2024/faa1d8cae94da6838ff9351e5df791ca/" title="Accès à l’article dans le cache local : Make the indie web easier">Make the indie web easier</a> (<a href="https://gilest.org/indie-easy.html" title="Accès à l’article original distant : Make the indie web easier">original</a>)</li>
<li><a href="/david/cache/2024/140458968f9f7da7d14e181d0a80e799/" title="Accès à l’article dans le cache local : The Expanding Dark Forest and Generative AI">The Expanding Dark Forest and Generative AI</a> (<a href="https://maggieappleton.com/ai-dark-forest" title="Accès à l’article original distant : The Expanding Dark Forest and Generative AI">original</a>)</li>
<li><a href="/david/cache/2024/3debc675a055d691b32c7d6904531eb4/" title="Accès à l’article dans le cache local : How Google perfected the web">How Google perfected the web</a> (<a href="https://www.theverge.com/c/23998379/google-search-seo-algorithm-webpage-optimization" title="Accès à l’article original distant : How Google perfected the web">original</a>)</li>
<li><a href="/david/cache/2024/036789c955419215be9d88c6823b55aa/" title="Accès à l’article dans le cache local : The fundamentals of the AGPLv3">The fundamentals of the AGPLv3</a> (<a href="https://www.fsf.org/bulletin/2021/fall/the-fundamentals-of-the-agplv3" title="Accès à l’article original distant : The fundamentals of the AGPLv3">original</a>)</li>
@@ -198,6 +202,8 @@
<li><a href="/david/cache/2024/0676c7ccf1ab2b380641866789366d26/" title="Accès à l’article dans le cache local : The Performance Inequality Gap, 2024">The Performance Inequality Gap, 2024</a> (<a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/" title="Accès à l’article original distant : The Performance Inequality Gap, 2024">original</a>)</li>
<li><a href="/david/cache/2024/a005801f0e596f9ecb99037a992ecc1b/" title="Accès à l’article dans le cache local : What’s the fun in writing on the internet anymore?">What’s the fun in writing on the internet anymore?</a> (<a href="https://jamesshelley.com/blog/writing-on-the-internet.html" title="Accès à l’article original distant : What’s the fun in writing on the internet anymore?">original</a>)</li>
<li><a href="/david/cache/2024/e8748af541273328d9aa9f1aeb1087b2/" title="Accès à l’article dans le cache local : Redeployment Part Three">Redeployment Part Three</a> (<a href="https://brr.fyi/posts/redeployment-part-three" title="Accès à l’article original distant : Redeployment Part Three">original</a>)</li>
<li><a href="/david/cache/2024/55477786fc56b6fc37bb97231b634d90/" title="Accès à l’article dans le cache local : Fabrique : concept">Fabrique : concept</a> (<a href="https://www.quaternum.net/2023/06/02/fabrique-concept/" title="Accès à l’article original distant : Fabrique : concept">original</a>)</li>
@@ -208,6 +214,8 @@
<li><a href="/david/cache/2024/1929f7183f694c7abeafeddb891fcf50/" title="Accès à l’article dans le cache local : Crise des opioïdes : pourquoi il ne faut ni l'oublier ni l'ignorer">Crise des opioïdes : pourquoi il ne faut ni l'oublier ni l'ignorer</a> (<a href="https://basta.media/crise-des-opioides-pourquoi-il-ne-faut-ni-oublier-ni-ignorer" title="Accès à l’article original distant : Crise des opioïdes : pourquoi il ne faut ni l'oublier ni l'ignorer">original</a>)</li>
<li><a href="/david/cache/2024/6bfc6bd7bc1d9158aa7f6591123e7f4b/" title="Accès à l’article dans le cache local : The Simplest Ways to Handle HTML Includes">The Simplest Ways to Handle HTML Includes</a> (<a href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/" title="Accès à l’article original distant : The Simplest Ways to Handle HTML Includes">original</a>)</li>
<li><a href="/david/cache/2024/7136e0810bfa42c4a9ca798a55cd2d53/" title="Accès à l’article dans le cache local : Where have all the flowers gone?">Where have all the flowers gone?</a> (<a href="https://daverupert.com/2024/01/where-have-all-the-websites-gone/" title="Accès à l’article original distant : Where have all the flowers gone?">original</a>)</li>
<li><a href="/david/cache/2024/b692faaa55fd2775e957b20e833e9e5e/" title="Accès à l’article dans le cache local : fraîchement">fraîchement</a> (<a href="https://www.la-grange.net/2024/01/26/fraichement" title="Accès à l’article original distant : fraîchement">original</a>)</li>

Loading…
Cancel
Save