<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sharing what we learn about the responsive web &#8211; Cloud Four</title>
	<atom:link href="https://cloudfour.com/thinks/feed/" rel="self" type="application/rss+xml" />
	<link>https://cloudfour.com</link>
	<description>Responsive web design and development, progressive web apps</description>
	<lastBuildDate>Mon, 15 Jun 2026 19:07:38 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
<site xmlns="com-wordpress:feed-additions:1">225560371</site>	<item>
		<title>Improvements to Web for AI Should Benefit All Users</title>
		<link>https://cloudfour.com/thinks/improvements-to-web-for-ai-should-benefit-all-users/</link>
					<comments>https://cloudfour.com/thinks/improvements-to-web-for-ai-should-benefit-all-users/#comments</comments>
		
		<dc:creator><![CDATA[Jason Grigsby]]></dc:creator>
		<pubDate>Mon, 15 Jun 2026 19:07:36 +0000</pubDate>
				<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Standards]]></category>
		<guid isPermaLink="false">https://cloudfour.com/?p=8571</guid>

					<description><![CDATA[Proposed changes to the web platform to support AI should also support users and assistive technology whenever possible.]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full">
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400" width="100%" height="100%" aria-hidden="true" focusable="false" role="presentation">
    <!-- Row 1 -->
    <rect x="0" y="0" width="100" height="100" fill="#215cca" class="tile" />
    <text x="50" y="72" text-anchor="middle"  class="c4emoji">🧏‍♀️</text>
    <rect x="100" y="0" width="100" height="100" fill="#d9118f" class="tile" />
    <text x="150" y="72" text-anchor="middle"  class="c4emoji">👩🏽‍🦼‍➡️</text>
    <rect x="200" y="0" width="100" height="100" fill="#0e1c43" class="tile" />
    <text x="250" y="72" text-anchor="middle"  class="c4emoji agent">🤖</text>
    <rect x="300" y="0" width="100" height="100" fill="#f2f5f7" class="tile" />
    <text x="350" y="72" text-anchor="middle"  class="c4emoji">👵🏿</text>
    <rect x="400" y="0" width="100" height="100" fill="#f27041" class="tile" />
    <text x="450" y="72" text-anchor="middle"  class="c4emoji">🧒🏼</text>
    <rect x="500" y="0" width="100" height="100" fill="#158466" class="tile" />
    <text x="550" y="72" text-anchor="middle"  class="c4emoji">👨🏻‍🦯</text>
    <rect x="600" y="0" width="100" height="100" fill="#950cde" class="tile" />
    <text x="650" y="72" text-anchor="middle"  class="c4emoji">👩🏾</text>
    <rect x="700" y="0" width="100" height="100" fill="#0e1c43" class="tile" />
    <text x="750" y="72" text-anchor="middle"  class="c4emoji agent">🤖</text>

    <!-- Row 2 -->
    <rect x="0" y="100" width="100" height="100" fill="#950cde" class="tile" />
    <text x="50" y="172" text-anchor="middle"  class="c4emoji">👨🏽</text>
    <rect x="100" y="100" width="100" height="100" fill="#f27041" class="tile" />
    <text x="150" y="172" text-anchor="middle"  class="c4emoji">🧓🏻</text>
    <rect x="200" y="100" width="100" height="100" fill="#158466" class="tile" />
    <text x="250" y="172" text-anchor="middle"  class="c4emoji">🧑‍🦽</text>
    <rect x="300" y="100" width="100" height="100" fill="#0e1c43" class="tile" />
    <text x="350" y="172" text-anchor="middle"  class="c4emoji agent">🤖</text>
    <rect x="400" y="100" width="100" height="100" fill="#f2f5f7" class="tile" />
    <text x="450" y="172" text-anchor="middle"  class="c4emoji">🧑🏼</text>
    <rect x="500" y="100" width="100" height="100" fill="#215cca" class="tile" />
    <text x="550" y="172" text-anchor="middle"  class="c4emoji">👩‍🦳</text>
    <rect x="600" y="100" width="100" height="100" fill="#d9118f" class="tile" />
    <text x="650" y="172" text-anchor="middle"  class="c4emoji">🧑‍🦲</text>
    <rect x="700" y="100" width="100" height="100" fill="#158466" class="tile" />
    <text x="750" y="172" text-anchor="middle"  class="c4emoji">🧏‍♂️</text>

    <!-- Row 3 -->
    <rect x="0" y="200" width="100" height="100" fill="#f2f5f7" class="tile" />
    <text x="50" y="272" text-anchor="middle"  class="c4emoji">👩🏾‍🦯‍➡️</text>
    <rect x="100" y="200" width="100" height="100" fill="#215cca" class="tile" />
    <text x="150" y="272" text-anchor="middle"  class="c4emoji">👨🏿</text>
    <rect x="200" y="200" width="100" height="100" fill="#d9118f" class="tile" />
    <text x="250" y="272" text-anchor="middle"  class="c4emoji">🧓🏽</text>
    <rect x="300" y="200" width="100" height="100" fill="#215cca" class="tile" />
    <text x="350" y="272" text-anchor="middle"  class="c4emoji">👩🏻‍🦰</text>
    <rect x="400" y="200" width="100" height="100" fill="#950cde" class="tile" />
    <text x="450" y="272" text-anchor="middle"  class="c4emoji">🧑‍🦼</text>
    <rect x="500" y="200" width="100" height="100" fill="#0e1c43" class="tile" />
    <text x="550" y="272" text-anchor="middle"  class="c4emoji agent">🤖</text>
    <rect x="600" y="200" width="100" height="100" fill="#158466" class="tile" />
    <text x="650" y="272" text-anchor="middle"  class="c4emoji">🧏🏿</text>
    <rect x="700" y="200" width="100" height="100" fill="#f27041" class="tile" />
    <text x="750" y="272" text-anchor="middle"  class="c4emoji">👩🏼‍⚕️</text>

    <!-- Row 4 -->
    <rect x="0" y="300" width="100" height="100" fill="#158466" class="tile" />
    <text x="50" y="372" text-anchor="middle"  class="c4emoji">👨🏼‍🦽</text>
    <rect x="100" y="300" width="100" height="100" fill="#0e1c43" class="tile" />
    <text x="150" y="372" text-anchor="middle"  class="c4emoji agent">🤖</text>
    <rect x="200" y="300" width="100" height="100" fill="#950cde" class="tile" />
    <text x="250" y="372" text-anchor="middle"  class="c4emoji">👴🏾</text>
    <rect x="300" y="300" width="100" height="100" fill="#f27041" class="tile" />
    <text x="350" y="372" text-anchor="middle"  class="c4emoji">👧🏻</text>
    <rect x="400" y="300" width="100" height="100" fill="#d9118f" class="tile" />
    <text x="450" y="372" text-anchor="middle"  class="c4emoji">🥷🏻</text>
    <rect x="500" y="300" width="100" height="100" fill="#215cca" class="tile" />
    <text x="550" y="372" text-anchor="middle"  class="c4emoji">🧑🏽‍🦯</text>
    <rect x="600" y="300" width="100" height="100" fill="#f2f5f7" class="tile" />
    <text x="650" y="372" text-anchor="middle"  class="c4emoji">👨‍👩‍👦</text>
    <rect x="700" y="300" width="100" height="100" fill="#950cde" class="tile" />
    <text x="750" y="372" text-anchor="middle"  class="c4emoji">👩🏾‍🦱</text>
  </svg>
</figure>
<style type="text/css">
 .c4emoji {
    font-family: "Apple Color c4emoji", "Segoe UI c4emoji", "Noto Color c4emoji", "Android c4emoji", sans-serif;
    font-size: 3em;
    transition: opacity .4s ease-in-out;
  }

  .c4emoji:not(.agent) {
    opacity: 0;
  }

  .c4emoji.reveal {
    opacity: 1;
  }
</style>

<script>
  const c4emojis = document.querySelectorAll(".c4emoji:not(.agent)");
  const shuffled = [...c4emojis].sort(() => Math.random() - 0.5);
  setTimeout(() => {
    shuffled.forEach((c4emoji, i) => { setTimeout(() => {   c4emoji.classList.add("reveal"); }, i * 75); // stagger between each c4emoji
    });
  }, 1000); // initial pause before any appear
</script>




<p class="wp-block-paragraph">Last week, the <a href="https://github.com/WebKit/standards-positions/issues/670#issuecomment-4608432694">Safari team formally expressed their opposition to the WebMCP API</a>. In Safari&#8217;s explanation of why they oppose WebMCP, they captured something I&#8217;ve been trying to articulate.</p>



<p class="wp-block-paragraph">In the comment explaining the Safari team position, Mike Wyrzykowski writes:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">When a site&#8217;s actions are hard for an agent to use, that is a gap in the page&#8217;s own semantics, and the fix, in our opinion, is to close it in the platform&#8217;s shared layers (HTML and ARIA), where the user, assistive technology, and agents all benefit.&nbsp;</p>
</blockquote>



<p class="wp-block-paragraph">Amen. </p>



<p class="wp-block-paragraph">In fact, this sentiment should guide any efforts to change the web to support AI agents better. It&#8217;s possible that not every enhancement for AI can be structured in a way that supports all of the web&#8217;s shared layers, but we should strive to do so first before reaching for solutions that only benefit AI and not the humans the web is supposed to serve.</p>



<p class="wp-block-paragraph">The Safari teams continues:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Our deeper concern is architectural. An agent acting on a user&#8217;s behalf is, in effect,&nbsp;<strong>assistive technology</strong>: it should operate a site as the user would, and the site should not single it out for different treatment.&nbsp;</p>
</blockquote>



<p class="wp-block-paragraph">And on accessibility:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">The proposal says WebMCP &#8220;is not designed for ingestion by accessibility technology&#8221;, the same fork: richer, actionable semantics reach agents while screen-reader and keyboard users get less.</p>
</blockquote>



<p class="wp-block-paragraph">All of this reminds me of a recent discussion on the Web Incubator Community Group (WICG) mailing list about a <a href="https://ai-domain-data.org/spec/v0.1/" data-type="link" data-id="https://ai-domain-data.org/spec/v0.1/">proposed standard</a> to help AI understand domain authority. The proposed standard is designed to solve the following problem:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">AI assistants often misidentify or misrepresent domains because there is no consistent, machine-readable, domain-controlled source of identity data. Today, models rely on scraped pages, inconsistent metadata, third-party aggregators, or outdated indexes. There is no canonical place where a domain can declare who they are, what they represent, or which resources are authoritative.</p>
</blockquote>



<p class="wp-block-paragraph">The proposed solution suggests adding a JSON-LD document to every website to solve the problem.</p>



<p class="wp-block-paragraph">Humans struggle with domain authority as well. People have trouble telling what websites are legitimate and which aren&#8217;t. If we&#8217;re solving this problem for AI, perhaps we can find a solution that works for end users too.</p>



<p class="wp-block-paragraph">And let&#8217;s set aside for the moment the irony that AI is supposed to replace all of our jobs and become a super intelligence and at the same time we also need to add special AI training wheels for it to use the web.</p>



<p class="wp-block-paragraph">I&#8217;d like to see the Safari team&#8217;s response to the Web MCP API canonized as a W3C Design Principle. Maybe a slight rewrite like this:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">When a site&#8217;s actions are hard for an AI agent to use, that is a gap in the page&#8217;s own semantics, and we should first seek to close it in the platform&#8217;s shared layers (HTML and ARIA), where the user, assistive technology, and agents all benefit.&nbsp;</p>
</blockquote>



<p class="wp-block-paragraph">We can put it right next to the <a href="https://www.w3.org/TR/design-principles/#priority-of-constituencies">W3C&#8217;s Priority of Constituencies</a>:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">If a trade-off needs to be made, always put user needs above all…</p>



<p class="wp-block-paragraph">User needs come before the needs of web page authors, which come before the needs of user agent implementors, which come before the needs of specification writers, which come before theoretical purity.</p>
</blockquote>



<p class="wp-block-paragraph">You&#8217;ll notice AI agents aren&#8217;t in that priority of constituencies, but assuming agents stick around, it might be worth considering where we&#8217;d put them. </p>



<p class="wp-block-paragraph">I hope we can all agree that user needs come before agent needs. We should keep this in mind as we consider proposals to modify the web to support AI.</p>



<p class="wp-block-paragraph"></p>

<hr>
<h2>We’re Cloud Four</h2>
<p>We solve complex responsive web design and development challenges for ecommerce, healthcare, fashion, B2B, SaaS, and nonprofit organizations.</p>

<p><a href="https://cloudfour.com/made/"><b>See our work</b></a></p>]]></content:encoded>
					
					<wfw:commentRss>https://cloudfour.com/thinks/improvements-to-web-for-ai-should-benefit-all-users/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">8571</post-id><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://cloudfour.com/wp-content/uploads/2026/06/users-of-the-web-1024x513-1.jpg" width="550" height="275" medium="image" /><enclosure url="https://cloudfour.com/wp-content/uploads/2026/06/users-of-the-web-1024x513-1.jpg" length="0" type="image/jpg" />	</item>
		<item>
		<title>Ending Responsive Images</title>
		<link>https://cloudfour.com/thinks/ending-responsive-images/</link>
					<comments>https://cloudfour.com/thinks/ending-responsive-images/#respond</comments>
		
		<dc:creator><![CDATA[Jason Grigsby]]></dc:creator>
		<pubDate>Thu, 11 Jun 2026 15:54:13 +0000</pubDate>
				<category><![CDATA[Images]]></category>
		<category><![CDATA[Mobile Web]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Responsive Web Design]]></category>
		<guid isPermaLink="false">https://cloudfour.com/?p=8565</guid>

					<description><![CDATA[Mat Marquis isn't known for pulling his punches. And yet, Marquis stopped short when he declared The End of Responsive Images. Mat left responsive images on the ropes. I hope to finish them.]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img fetchpriority="high" width="1024" height="576" src="https://cloudfour.com/wp-content/uploads/2026/06/feature-srcset-r1-1024x576.jpg" alt="An cartoon illustration of the grim reaper carrying a scythe on dark blue background. A word balloon shows the grim reaper saying one word: srcset. " class="wp-image-8566" srcset="https://cloudfour.com/wp-content/uploads/2026/06/feature-srcset-r1-1024x576.jpg 1024w, https://cloudfour.com/wp-content/uploads/2026/06/feature-srcset-r1-300x169.jpg 300w, https://cloudfour.com/wp-content/uploads/2026/06/feature-srcset-r1-768x432.jpg 768w, https://cloudfour.com/wp-content/uploads/2026/06/feature-srcset-r1-1536x864.jpg 1536w, https://cloudfour.com/wp-content/uploads/2026/06/feature-srcset-r1-2048x1152.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">Mat Marquis, former <a href="https://www.w3.org/community/respimg/">Responsive Images Working Group</a> (RICG) chair and <a href="https://www.indiegogo.com/en/projects/matmarquis/wilto-s-first-fight-night">amateur boxer</a>, isn&#8217;t known for pulling his punches. And yet, Marquis stopped short when he declared <a href="https://piccalil.li/blog/the-end-of-responsive-images/" data-type="link" data-id="https://piccalil.li/blog/the-end-of-responsive-images/">The End of Responsive Images</a>. Mat left responsive images on the ropes. I hope to finish them.</p>



<p class="wp-block-paragraph">Or rather, finish most responsive images. The ones below the fold. Let me explain.</p>



<h2 class="wp-block-heading">The responsive images race condition</h2>



<p class="wp-block-paragraph">In the beginning of our search for a responsive images solution, the challenge seemed simple: the <code>img</code> element only supported one source file, and we needed multiple sources to support responsive designs. However, if we supply multiple image sources, how will the browser know which source to choose?</p>



<p class="wp-block-paragraph">Therein lies the rub. Browsers download images before they&#8217;ve calculated the layout of the page. And if the browser doesn&#8217;t know the page layout, it doesn&#8217;t know the size of the image in the page. As I put it back <a href="https://cloudfour.com/thinks/the-real-conflict-behind-picture-and-srcset/" data-type="link" data-id="https://cloudfour.com/thinks/the-real-conflict-behind-picture-and-srcset/">in 2012</a>:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">How do we reconcile a pre-parser that wants to know what size image to download ahead of time with an image technique that wants to respond to its environment once the page layout has been calculated?</p>
</blockquote>



<p class="wp-block-paragraph">Solving this problem is how we ended up with <code>srcset</code> and <code>sizes</code>. One tells the browser what source options it can choose from and the other provides the browser with the information it needs to calculate the size of the image in the page based on a measurement the browser always knows—the viewport size.</p>



<h2 class="wp-block-heading">Lazy loading changes everything</h2>



<p class="wp-block-paragraph">In the years since, lazy-loading images has become a common practice. We can safely defer loading images outside the initial view (aka, below the fold) in order to ensure that the browser&#8217;s resources are focused on the assets that are immediately visible.</p>



<p class="wp-block-paragraph">So many developers adopted this practice that it is now a web standard. Adding <code>loading="lazy"</code> to any image will tell the browser to delay downloading the image until it will be visible in the viewport.</p>



<p class="wp-block-paragraph">Because lazy-loaded images won&#8217;t download until they are visible, the race condition described earlier no longer exists. When lazy-loaded images are downloaded, the browser knows their size.</p>



<p class="wp-block-paragraph">Lazy-loaded images now allow us to simplify the markup for <code>sizes</code> as Mat Marquis explained:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">A few weeks ago, two patches landed in&nbsp;<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1819581">Gecko</a>&nbsp;and&nbsp;<a href="https://bugs.webkit.org/show_bug.cgi?id=310025">WebKit</a>&nbsp;— championed by Simon Pieters and Yoav Weiss, respectively, two of the RICG’s finest. These patches landed to little fanfare, quietly aligning Gecko and WebKit with&nbsp;<a href="https://issues.chromium.org/issues/40862170#comment27">Blink</a>&nbsp;in supporting a relatively recent addition to the HTML specification: support for an&nbsp;<code>auto</code>&nbsp;value in&nbsp;<code>sizes</code>&nbsp;attributes. Automatic&nbsp;<code>sizes</code>&nbsp;— the potential sizes of the rendered image, left up to the browser to determine alongside all those other factors. Fully automatic responsive images. Supply the browser with a list of candidates using&nbsp;<code>srcset</code>, bolt on&nbsp;<code>sizes="auto"</code>, and let the browser do the rest.</p>
</blockquote>



<p class="wp-block-paragraph">So long as an image has <code>loading="lazy"</code> you can use <code>sizes="auto"</code>. Here is the sample Mat provided (with a few cat-related tweaks on my part):</p>


<pre class="wp-block-code"><span><code class="hljs language-handlebars"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> 
  <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span>
  <span class="hljs-attr">src</span>=<span class="hljs-string">"cat.jpeg"</span> 
  <span class="hljs-attr">srcset</span>=<span class="hljs-string">"cat-650.jpeg 650w, cat-960.jpeg 960w, cat-1400.jpeg 1400w"</span>
  <span class="hljs-attr">sizes</span>=<span class="hljs-string">"auto, (min-width: 1040px) 650px, calc(94.44vw - 15px)"</span>
  <span class="hljs-attr">width</span>=<span class="hljs-string">"650"</span>
  <span class="hljs-attr">height</span>=<span class="hljs-string">"400"</span>
  <span class="hljs-attr">alt</span>=<span class="hljs-string">"My cat Boyle is super cute."</span>&gt;</span></span></code></span></pre>


<p class="wp-block-paragraph">You&#8217;ll notice that Mat includes fallback <code>sizes</code> values to support older browsers. But with Safari and Firefox now supporting <code>sizes="auto"</code> we likely won&#8217;t need the fallback for long.</p>



<p class="has-gray-lighter-background-color has-background wp-block-paragraph"><strong>Caution:</strong> <em><a href="https://cloudfour.com/thinks/stop-lazy-loading-product-and-hero-images/">Images above the fold shouldn&#8217;t be lazy-loaded</a></em>. In fact, hero images are likely your <a href="https://web.dev/articles/lcp">Largest Content Paint (LCP)</a> image in <a href="https://web.dev/explore/learn-core-web-vitals" data-type="link" data-id="https://web.dev/explore/learn-core-web-vitals">Web Core Vitals</a> and should be loaded as early as possible. Therefore, images in the initial viewport will likely always require responsive images syntax.</p>



<h2 class="wp-block-heading">Removing srcset</h2>



<p class="wp-block-paragraph">Simplifying <code>sizes</code> is a good start, but I believe we can go further and radically simplify the markup for lazy-loaded images using <a href="https://wicg.github.io/responsive-image-client-hints/">Responsive Image Client Hints</a>. Responsive Image Client Hints is a draft specification being stewarded by <a href="https://ericportis.com/" data-type="link" data-id="https://ericportis.com/">Eric Portis</a> also of RICG fame.</p>



<p class="wp-block-paragraph">Responsive Image Client Hints builds on the existing Client Hints standard that has been implemented by Blink and thus supported by Chrome, Edge, and other browsers built on the Blink engine. Web page authors can declare support for Client Hints and ask for specific hints like the size of a requested image. The browser then sends this information in HTTP headers.</p>



<p class="wp-block-paragraph">For example, a server might send the following HTTP headers along with an HTML document:</p>


<pre class="wp-block-code"><span><code class="hljs language-php">Accept-CH: Sec-CH-Width
Permissions-Policy: ch-width=(<span class="hljs-keyword">self</span> <span class="hljs-string">"https://images.cloudfour.com"</span>)</code></span></pre>


<p class="wp-block-paragraph">The first line says that the server will accept client hints and is looking for Secure Client Hints Width (<code>Sec-CH-Width</code>). The permissions policy line helps reduce the potential for passive fingerprinting by restricting access to the specified domains. A similar declaration can be made via a meta tag:</p>


<pre class="wp-block-code"><span><code class="hljs language-handlebars"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"delegate-ch"</span> 
      <span class="hljs-attr">content</span>=<span class="hljs-string">"sec-ch-width https://images.cloudfour.com;"</span>&gt;</span></span></code></span></pre>


<p class="wp-block-paragraph">And then when an image on the page is requested by the browser, it will supply the requested Client Hints—in this case, the width of the image in the page:</p>


<pre class="wp-block-code"><span><code class="hljs language-yaml"><span class="hljs-string">GET</span> <span class="hljs-string">cat.jpg</span>
<span class="hljs-attr">Accept:</span> <span class="hljs-string">image/webp,image/*,*/*;q=0.8</span>
<span class="hljs-attr">Sec-CH-Width:</span> <span class="hljs-number">650</span></code></span></pre>


<p class="wp-block-paragraph"><code>Sec-CH-Width</code> value will contain the pixel width of the image in the page multipled by the display density. So if the image is 400 pixels wide on a 2x display, the value sent to the server will be <code>Sec-CH Width: 800</code>. </p>



<p class="wp-block-paragraph">If both the browser and server support client hints, and the image is lazy-loaded, we can greatly simplify our markup:</p>


<pre class="wp-block-code"><span><code class="hljs language-handlebars"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> 
  <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span>
  <span class="hljs-attr">src</span>=<span class="hljs-string">"cat.jpeg"</span>
  <span class="hljs-attr">width</span>=<span class="hljs-string">"650"</span>
  <span class="hljs-attr">height</span>=<span class="hljs-string">"400"</span>
  <span class="hljs-attr">sizes</span>=<span class="hljs-string">"auto"</span>
  <span class="hljs-attr">alt</span>=<span class="hljs-string">"My cat Boyle is super cute."</span>&gt;</span></span></code></span></pre>


<p class="wp-block-paragraph">We no longer need <code>srcset</code> because the server knows what image sizes are available or can resize the image as needed based on the image size supplied by Client Hints. </p>



<p class="wp-block-paragraph">Because the image is lazy-loaded, we also know the size of the image in the page which means we shouldn&#8217;t need <code>sizes</code> at all. Unfortunately, the Client Hints standard expects the <code>sizes</code> attribute so we still need to supply <code>sizes="auto"</code>. Perhaps this can change in the future and we can remove the <code>sizes</code> attribute as well.</p>



<h2 class="wp-block-heading">How is an image source selected?</h2>



<p class="wp-block-paragraph">If we&#8217;re not supplying a list of image sources in <code>srcset</code> to the browser, how will one be selected? For this to work, you need an image resizing service on the server to respond to the image request. If you don&#8217;t have one, you can continue to use <code>srcset</code> and <code>sizes</code>.</p>



<p class="wp-block-paragraph">If this approach takes off, image resizing services may want to change the way they select what image size to return. Instead of working from a list of image sizes that the web page author <em>thinks</em> might be needed, the server can monitor what sizes are requested the most and make sure those sizes are cached. The server can optimize the cached image sizes based on real world usage.</p>



<h2 class="wp-block-heading">What about browsers that don&#8217;t support Client Hints?</h2>



<p class="wp-block-paragraph">Client Hints aren&#8217;t new. Chrome shipped them in v46 back in 2015. I <a href="https://cloudfour.com/thinks/responsive-images-201-client-hints/">wrote about their possible uses</a> in 2016. But developers haven&#8217;t widely adopted Client Hints because Firefox and Safari don&#8217;t support them.</p>



<p class="wp-block-paragraph">Because of this reality, I gave up on Clients Hints for many years. Three developments have caused me to revisit them:</p>



<ol class="wp-block-list">
<li>The proliferation of lazy-loading images and the standard to support them means we have a large body of images for which the speculative downloader&#8217;s race condition doesn&#8217;t apply.</li>



<li>In <a href="https://cloudfour.com/thinks/imageengine-deserves-a-second-look/" data-type="link" data-id="https://cloudfour.com/thinks/imageengine-deserves-a-second-look/">my review of ImageEngine</a>, I was impressed with how simple it is to use. Some of this simplicity is due to leveraging Client Hints when they are available.</li>



<li>Eric Portis has created a <a href="https://github.com/eeeps/w_auto-without-ch">small JavaScript library</a> that provides similar functionality for <a href="https://cloudinary.com/">Cloudinary</a> users in browsers that don&#8217;t support Client Hints.</li>
</ol>



<p class="wp-block-paragraph">Eric&#8217;s script works like this:</p>



<ul class="wp-block-list">
<li>If the browser supports Responsive Image Client Hints, the script does nothing.</li>



<li>If Client Hints aren&#8217;t supported, the script looks for images with the <code>loading="lazy"</code> attribute.</li>



<li>It also checks for some specific Cloudinary parameters in image&#8217;s <code>src</code> URL which tell the script that this image is one that it should modify.</li>



<li>The script then updates the width value in the Cloudinary URL to send along the actual size of the image in the page.</li>
</ul>



<p class="wp-block-paragraph">I&#8217;ve modified the sample markup from above to show how it would look using Cloudinary and supporting Eric&#8217;s script:</p>


<pre class="wp-block-code"><span><code class="hljs language-handlebars"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> 
  <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span>
  <span class="hljs-attr">src</span>=<span class="hljs-string">"&#91;…]/upload/c_limit,w_auto:breakpoints:650/v1716911991/catbeans_zbh3iu.jpg"</span>
  <span class="hljs-attr">width</span>=<span class="hljs-string">"650"</span>
  <span class="hljs-attr">height</span>=<span class="hljs-string">"366"</span>
  <span class="hljs-attr">sizes</span>=<span class="hljs-string">"auto"</span>
  <span class="hljs-attr">alt</span>=<span class="hljs-string">"My cat Boyle is super cute."</span>&gt;</span></span></code></span></pre>


<p class="wp-block-paragraph">The key section in the image URL is <code><a href="https://cloudinary.com/documentation/transformation_reference#w_auto">w_auto:breakpoints:650</a></code>:</p>



<ul class="wp-block-list">
<li><code>w_auto</code> — This tells Cloudinary that the image is responsive and should be dynamically resized to fit the size of the image in the page.</li>



<li><code>breakpoints</code> — This tells Cloudinary to pick image sizes using a performance budget—a <a href="https://cloudfour.com/thinks/responsive-images-breakpoint-generator/" data-type="link" data-id="https://cloudfour.com/thinks/responsive-images-breakpoint-generator/">feature</a> they created based on <a href="https://cloudfour.com/thinks/sensible-jumps-in-responsive-image-file-sizes/" data-type="link" data-id="https://cloudfour.com/thinks/sensible-jumps-in-responsive-image-file-sizes/">one of my articles</a>. If performance budgets aren&#8217;t your speed, you can set a value for how many pixels before a new image is created on the server.</li>



<li><code>650</code> — this is the fallback width that should be used if the browser doesn&#8217;t send additional information via Client Hints.</li>
</ul>



<p class="wp-block-paragraph">If the image in the page was actually 900 pixels wide at 2x display density, the script would update the <code>src</code> to be:</p>


<pre class="wp-block-code"><span><code class="hljs language-bash">  src=<span class="hljs-string">"&#91;…]/upload/c_limit,w_auto:breakpoints:1800/v1716911991/catbeans_zbh3iu.jpg"</span></code></span></pre>


<p class="wp-block-paragraph">For browsers that don&#8217;t support Client Hints, the actual size of the image in the page is added to the URL. This technique could be modified to work with other image resizing servers.</p>



<p class="wp-block-paragraph">There are a few caveats with this script:</p>



<ul class="wp-block-list">
<li>It must be placed in the <code>&lt;head&gt;</code></li>



<li>It has to be a blocking script. You can&#8217;t <code>async</code>, <code>defer</code>, or use <code>type="module"</code>.</li>
</ul>



<p class="wp-block-paragraph">Eric <a href="https://github.com/eeeps/w_auto-without-ch" data-type="link" data-id="https://github.com/eeeps/w_auto-without-ch">explains</a>:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">This script needs to see&nbsp;<code>&lt;img&gt;</code>s as soon as they are parsed, so that it can prepare to re-write their URLs as soon as they’re laid out. If the script executes after an&nbsp;<code>&lt;img&gt;</code>&nbsp;has been parsed, it won’t get a chance to do any of that; it’ll do nothing.</p>



<p class="wp-block-paragraph">Luckily, it’s only ~950 bytes (~600B compressed).</p>
</blockquote>



<p class="wp-block-paragraph">Eric has created a couple of CodePen examples that show the script in action. One uses <a href="https://codepen.io/editor/eeeps/pen/019eae66-575e-77ba-948d-68059a65ec5a">placeholder images</a> and the other <a href="https://codepen.io/editor/eeeps/pen/019eb2ca-c06f-709e-885f-573ef897ff56">real images from WikiPedia</a>. </p>



<p class="wp-block-paragraph">I normally wouldn&#8217;t advocate for a blocking script, but this seems lightweight and the tradeoff is worth evaluating. Make sure to measure the performance impact on your site.</p>



<h2 class="wp-block-heading">A JavaScript Solution? Really?</h2>



<p class="wp-block-paragraph">During the halcyon days of the RICG, not a month went by without someone proposing a way to solve responsive images using JavaScript. We repeatedly and patiently explained why JavaScript couldn&#8217;t be used because images are downloaded before JavaScript is processed.</p>



<p class="wp-block-paragraph">Lazy-loading images outside the initial viewport changes this equation. We now have a small window of opportunity to modify lazy-loaded images so we can add the equivalent of Client Hints to their URLs when their size is known.</p>



<h2 class="wp-block-heading">The End of Most Responsive Images</h2>



<figure class="wp-block-image size-large"><img width="1024" height="576" src="https://cloudfour.com/wp-content/uploads/2026/06/catbeans-1024x576.jpg" alt="Our adorable black and white cat Boyle sleeps on the back of the sofa. His little paws are out in front of him like he is super man. " class="wp-image-8569" srcset="https://cloudfour.com/wp-content/uploads/2026/06/catbeans-1024x576.jpg 1024w, https://cloudfour.com/wp-content/uploads/2026/06/catbeans-300x169.jpg 300w, https://cloudfour.com/wp-content/uploads/2026/06/catbeans-768x432.jpg 768w, https://cloudfour.com/wp-content/uploads/2026/06/catbeans.jpg 1200w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Meet Boyle, the super cute cat I alluded to in earlier examples. </figcaption></figure>



<p class="wp-block-paragraph">Responsive images syntax will always have a role to play. Not every web page will have a image resizing server and images visible in the initial viewport will still face the race condition that gave the RICG fits. Any images in the initial viewport <a href="https://cloudfour.com/thinks/stop-lazy-loading-product-and-hero-images/">shouldn&#8217;t be lazy-loaded</a>. </p>



<p class="wp-block-paragraph">Fortunately, most images on the web live below the fold and thus can be lazy-loaded. If they can be lazy-loaded, then we no longer face the intractable race condition that forced us to place presentation information in the <code>sizes</code> attribute where it doesn&#8217;t belong.</p>



<p class="wp-block-paragraph">Moving to simpler responsive images will require some work. According to CanIUse.com, <a href="https://caniuse.com/?search=client+hints">78% of users have access to Client Hints</a>. That&#8217;s a great start, but ideally we&#8217;d get other browsers on board. Firefox and Safari expressed privacy concerns with client hints which is why they didn&#8217;t implement them. I&#8217;m hopeful that some combination a mandatory permissions policy (e.g., primary domain and subdomains only would be ideal) and a more limited set of hints (image width and dpr only?), that we might be able to get other browser makers on board.</p>



<p class="wp-block-paragraph">But even without these changes, it is possible now to remove <code>srcset</code> and simplify <code>sizes</code> using a combination of lazy-loading, Client Hints, and the techniques that Eric Portis has pioneered. </p>



<p class="wp-block-paragraph">Mat concluded his article by saying:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">I won’t miss all those hand-hewn <code>sizes</code> attributes; I never had any love for them to begin with. I will never experience a shred of nostalgia for a thing that I helped make real and inexorably bound to my name. A syntax was never the goal; the goal was always a <em>mechanism</em>. At the time, the web platform lacked a way for browsers to make smarter decisions about what image asset to request and when, and no amount of clever scripting or markup trickery would ever result in an asset request as fast or efficient as one the browser itself could make.</p>
</blockquote>



<p class="wp-block-paragraph">None of us working in the RICG were ever enamored with our solutions. We wanted something simpler, but <code>srcset</code> and <code>sizes</code> was the best we could do with the constraints we were given. Now that lazy-loading has removed one of the constraints, I believe we can do better.</p>



<p class="wp-block-paragraph"><em>Special thanks to Eric Portis, Mat Marquis, and Scott Vandehey for their feedback and to Tyler Sticka for the grim reaper illustration.</em></p>

<hr>
<h2>We’re Cloud Four</h2>
<p>We solve complex responsive web design and development challenges for ecommerce, healthcare, fashion, B2B, SaaS, and nonprofit organizations.</p>

<p><a href="https://cloudfour.com/made/"><b>See our work</b></a></p>]]></content:encoded>
					
					<wfw:commentRss>https://cloudfour.com/thinks/ending-responsive-images/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">8565</post-id><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://cloudfour.com/wp-content/uploads/2026/06/feature-srcset-r1.jpg" width="550" height="309" medium="image" /><enclosure url="https://cloudfour.com/wp-content/uploads/2026/06/feature-srcset-r1.jpg" length="0" type="image/jpg" />	</item>
		<item>
		<title>How We Use CI to Check Code Standards on Every PR</title>
		<link>https://cloudfour.com/thinks/ci-for-code-standards/</link>
					<comments>https://cloudfour.com/thinks/ci-for-code-standards/#respond</comments>
		
		<dc:creator><![CDATA[Scott Vandehey]]></dc:creator>
		<pubDate>Tue, 05 May 2026 17:00:00 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[bestpractices]]></category>
		<category><![CDATA[cd]]></category>
		<category><![CDATA[ci]]></category>
		<category><![CDATA[workflows]]></category>
		<guid isPermaLink="false">https://cloudfour.com/?p=8557</guid>

					<description><![CDATA[Automating your code checks ensures every contribution meets standards, reduces the review burden, and increases confidence in AI-generated code.]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img width="1024" height="576" src="https://cloudfour.com/wp-content/uploads/2026/04/ci-standards-feature-r2-1024x576.jpg" alt="A cheerful-looking robot wearing a hard hat and holding a clipboard stands before a conveyor belt full of icons representing code changes, like a line inspector in a factory." class="wp-image-8560" srcset="https://cloudfour.com/wp-content/uploads/2026/04/ci-standards-feature-r2-1024x576.jpg 1024w, https://cloudfour.com/wp-content/uploads/2026/04/ci-standards-feature-r2-300x169.jpg 300w, https://cloudfour.com/wp-content/uploads/2026/04/ci-standards-feature-r2-768x432.jpg 768w, https://cloudfour.com/wp-content/uploads/2026/04/ci-standards-feature-r2-1536x864.jpg 1536w, https://cloudfour.com/wp-content/uploads/2026/04/ci-standards-feature-r2-2048x1152.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">When I first heard the term continuous integration (CI), I was intimidated. As a former art major, I struggle with imposter syndrome when other devs rattle off terms I assume they picked up in computer science classes.</p>



<p class="wp-block-paragraph">In this case, I was relieved to learn that CI is a complicated label for a basic concept: Developers should merge (integrate) their code back to the main branch as often as possible (continuously). This stands in contrast to a common scenario where devs work on a feature in isolation for so long that it drifts out of sync with the main code branch. When the time comes to merge, it creates a confusing mess.</p>



<p class="wp-block-paragraph">CI is typically paired with another term, continuous deployment (CD), which says your main branch should be deployed automatically as changes are made. The idea is to avoid issues that arise from infrequent releases. When you have unreleased (or unreleasable) code in your main branch, it’s very difficult to make emergency bug fixes or urgent change requests.</p>



<p class="wp-block-paragraph">So, CI means that devs regularly merge their code into the main branch, and CD means those merges automatically trigger a deployment. That’s CI/CD workflow in a nutshell. Sounds great, right?</p>



<h2 class="wp-block-heading">How Do You Ensure Code is Safe to Deploy?</h2>



<p class="wp-block-paragraph">You may have noticed a potential problem. If every commit is automatically deployed, then any bugs that are merged get deployed, too! By necessity, adopting a CI/CD workflow brings with it an expectation that your team should only merge code that’s safe to deploy.</p>



<p class="wp-block-paragraph">The best way to address this concern is to require all code be <a href="https://cloudfour.com/thinks/how-we-do-code-reviews-at-cloud-four/">carefully reviewed</a>. Of course, those reviews take time, so teams typically invest in tooling to run automated quality control checks, like: Does the code compile without errors? Is it formatted to match the style guide? Do the tests pass? If any check fails, the changes are blocked until the issues are addressed. When most people talk about CI, they’re referring not only to the workflow, but also the tools that run those automated checks.</p>



<p class="wp-block-paragraph">Note that automated checks are not a substitute for human review! Even if all the checks pass, there could be bugs that aren’t covered by tests or are difficult to automate, such as accessibility issues. The goal is to increase confidence by checking for obvious problems before a developer spends time reviewing it.</p>



<h2 class="wp-block-heading">Our Standard CI Setup</h2>



<p class="wp-block-paragraph">We work on a lot of projects, and have a fairly standard setup we use to keep things consistent for devs switching between them. It all starts in <code>package.json</code>, where we define a standard set of scripts to run our tests, <a href="https://cloudfour.com/thinks/code-linting-for-web-designers/">linters</a>, and type checkers. Here’s an example from a Vue project:</p>


<pre class="wp-block-code"><span><code class="hljs language-json"><span class="hljs-comment">// package.json</span>
{
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"vitest run"</span>,
    <span class="hljs-attr">"test:watch"</span>: <span class="hljs-string">"vitest watch"</span>,
    <span class="hljs-attr">"lint"</span>: <span class="hljs-string">"npm run lint:js &amp;&amp; npm run lint:css &amp;&amp; npm run lint:prettier"</span>,
    <span class="hljs-attr">"lint:check"</span>: <span class="hljs-string">"npm run lint:js:check &amp;&amp; npm run lint:css:check &amp;&amp; npm run lint:prettier:check"</span>,
    <span class="hljs-attr">"lint:js"</span>: <span class="hljs-string">"eslint . --fix"</span>,
    <span class="hljs-attr">"lint:js:check"</span>: <span class="hljs-string">"eslint ."</span>,
    <span class="hljs-attr">"lint:css"</span>: <span class="hljs-string">"stylelint --fix '**/*.{css,vue}'"</span>,
    <span class="hljs-attr">"lint:css:check"</span>: <span class="hljs-string">"stylelint '**/*.{css,vue}'"</span>,
    <span class="hljs-attr">"lint:prettier"</span>: <span class="hljs-string">"prettier . --write"</span>,
    <span class="hljs-attr">"lint:prettier:check"</span>: <span class="hljs-string">"prettier . --check"</span>,
    <span class="hljs-attr">"type-check"</span>: <span class="hljs-string">"nuxt typecheck"</span>
  }
}</code></span></pre>


<p class="wp-block-paragraph">What those scripts actually do might vary. In a WordPress project, the <code>type-check</code> script could run PHPStan. In a project that uses Sass, the <code>lint:css</code> script would target <code>*.scss</code> files. The important part is the naming convention for the scripts. In any of our projects, a dev can confidently run <code>npm run lint</code> and trust that all the linters in the project will run. This sort of consistency makes life easier for devs, and makes them more likely to use these tools before putting code up for review.</p>



<p class="wp-block-paragraph">The next step is to run those scripts automatically on every pull request. The CI tool we use most often is GitHub Actions.<sup data-fn="e10b5e8f-ef6e-4466-8750-3cf13f6a077b" class="fn"><a href="#e10b5e8f-ef6e-4466-8750-3cf13f6a077b" id="e10b5e8f-ef6e-4466-8750-3cf13f6a077b-link">1</a></sup> By creating a single file in the repository, we can ensure that every time a PR is opened, GitHub automatically runs a series of actions. Here’s an example of a GitHub Actions CI script from one of our projects:</p>


<pre class="wp-block-code"><span><code class="hljs language-yaml"><span class="hljs-comment"># .github/workflows/ci.yml</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">CI</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">pull_request:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">main</span>

<span class="hljs-attr">concurrency:</span>
  <span class="hljs-attr">group:</span> <span class="hljs-string">${{</span> <span class="hljs-string">github.workflow</span> <span class="hljs-string">}}-${{</span> <span class="hljs-string">github.head_ref</span> <span class="hljs-string">||</span> <span class="hljs-string">github.run_id</span> <span class="hljs-string">}}</span>
  <span class="hljs-attr">cancel-in-progress:</span> <span class="hljs-literal">true</span>

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">test:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v6</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">persist-credentials:</span> <span class="hljs-literal">false</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Use</span> <span class="hljs-string">Node.js</span> <span class="hljs-number">24</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-node@v6</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">node-version:</span> <span class="hljs-number">24</span>
          <span class="hljs-attr">cache:</span> <span class="hljs-string">'npm'</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">Dependencies</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">ci</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">Tests</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">test</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">Lint</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">run</span> <span class="hljs-string">lint:check</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">Typing</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">run</span> <span class="hljs-string">type-check</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">Build</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">run</span> <span class="hljs-string">build</span></code></span></pre>


<p class="wp-block-paragraph">This script runs every time a PR is opened, and every time code is pushed to the <code>main</code> branch. It’s set to cancel any in-progress CI task if a new one is triggered. It checks out the code, installs the dependencies, and runs our npm scripts. We have all our repos configured to require that all status checks pass before merging. If any of the steps in our CI check fail, the PR is blocked and can’t be merged until the issues are addressed.</p>



<h2 class="wp-block-heading">CI Tooling is More Valuable in the AI Age</h2>



<p class="wp-block-paragraph">I’m a big believer in automated code checking. I can’t count the number of times it’s saved us. Imagine a senior dev who doesn’t think their tiny change warrants a full review, but is accidentally passing the wrong property type. (Perhaps, in this entirely fictional example, the dev’s name was Scott.) Or a designer who just wants to update the brand color, but unintentionally changes the CSS file from tabs to spaces. By running automated checks against every change, we’ve greatly increased our confidence. I love it.</p>



<p class="wp-block-paragraph">And as more developers start experimenting with AI coding agents, these CI tools are becoming even more valuable. AI is improving, but it&#8217;s still mostly operating at the level of an enthusiastic junior developer. Someone who knows how to code, but lacks real-world experience, and is perhaps a touch too eager to make clever changes to critical systems.</p>



<p class="wp-block-paragraph">I enjoy working with Claude, but I’ve watched it confidently make sweeping changes without running the tests. It will create new functions that are very useful, but don’t follow our house style. So far, we’ve used Claude in an extremely hands-on way, like a pair programming session. The human dev has a good understanding of what’s changed, and can redirect.</p>



<p class="wp-block-paragraph">But increasingly, I’m seeing my peers discuss using AI in a more hands-off fashion. They give it a directive, and allow it to run wild. They’re thrilled when the AI delivers, in an afternoon, more code than they could write in a week. But now they discover the real bottleneck is reviewing all that code.</p>



<p class="wp-block-paragraph">In short, automating your code checks ensures every contribution meets your enforcable standards, reduces the burden of code review on other devs, and can help increase your confidence in AI-generated code.</p>


<ol class="wp-block-footnotes"><li id="e10b5e8f-ef6e-4466-8750-3cf13f6a077b">GitHub Actions is the tool we use most often, not because it’s the best, but because it’s integrated into GitHub, where our code already lives, and is easy to configure via a single file in the repo. In the past we’ve used Jenkins, Travis CI, Circle CI, GitLab CI, and Bitbucket Pipelines. They’re all fine. Pick the one that works best for your team and your stack. <a href="#e10b5e8f-ef6e-4466-8750-3cf13f6a077b-link" aria-label="Jump to footnote reference 1">↩︎</a></li></ol>
<hr>
<h2>We’re Cloud Four</h2>
<p>We solve complex responsive web design and development challenges for ecommerce, healthcare, fashion, B2B, SaaS, and nonprofit organizations.</p>

<p><a href="https://cloudfour.com/made/"><b>See our work</b></a></p>]]></content:encoded>
					
					<wfw:commentRss>https://cloudfour.com/thinks/ci-for-code-standards/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">8557</post-id><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://cloudfour.com/wp-content/uploads/2026/04/ci-standards-feature-r2.jpg" width="550" height="309" medium="image" /><enclosure url="https://cloudfour.com/wp-content/uploads/2026/04/ci-standards-feature-r2.jpg" length="0" type="image/jpg" />	</item>
		<item>
		<title>Most Cookie Consent Banners Don&#8217;t Check for Compliance</title>
		<link>https://cloudfour.com/thinks/most-cookie-consent-banners-dont-check-for-compliance/</link>
					<comments>https://cloudfour.com/thinks/most-cookie-consent-banners-dont-check-for-compliance/#respond</comments>
		
		<dc:creator><![CDATA[Jason Grigsby]]></dc:creator>
		<pubDate>Thu, 16 Apr 2026 17:07:36 +0000</pubDate>
				<category><![CDATA[Privacy]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://cloudfour.com/?p=8553</guid>

					<description><![CDATA[Surprisingly, most cookie consent managers don't seem to check if websites are in compliance with CCPA and GPDR. Are you sure your website is in compliance?]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img width="1024" height="576" src="https://cloudfour.com/wp-content/uploads/2026/04/cookie-compliance-r1-1024x576.png" alt="" class="wp-image-8554" srcset="https://cloudfour.com/wp-content/uploads/2026/04/cookie-compliance-r1-1024x576.png 1024w, https://cloudfour.com/wp-content/uploads/2026/04/cookie-compliance-r1-300x169.png 300w, https://cloudfour.com/wp-content/uploads/2026/04/cookie-compliance-r1-768x432.png 768w, https://cloudfour.com/wp-content/uploads/2026/04/cookie-compliance-r1-1536x864.png 1536w, https://cloudfour.com/wp-content/uploads/2026/04/cookie-compliance-r1-2048x1152.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">As I&#8217;ve had more opportunities to work with cookie consent managers, I&#8217;ve come to the surprising realization that most of them (all of them?) fail to track if websites are in compliance with various privacy laws.</p>



<p class="wp-block-paragraph">One client we&#8217;ve been working with pays a lot of money for an enterprise-level cookie consent solution. Their cookie process is similar to what I&#8217;ve seen for other consent managers:</p>



<ul class="wp-block-list">
<li>The consent manager runs a scan across the client&#8217;s website to identify any cookies or other trackers.</li>



<li>The consent manager may provide a suggested category for any trackers that it recognizes.</li>



<li>The client has to verify that the suggested categorization is correct and categorize any cookies that the consent manager didn&#8217;t recognize.</li>



<li>There may be some additional work to make sure these categorizations are replicated in tag managers.</li>



<li>Once the categorization is complete, then the cookies <em>should</em> only be set when users provide the appropriate consent.</li>



<li>Periodically, the consent manager will scan the site to look for any new cookies or trackers. If any  are found, this process is repeated.</li>
</ul>



<p class="wp-block-paragraph">The realization I&#8217;ve had is that the subsequent scans aren&#8217;t checking to verify that the cookies are being set correctly or not. Their primary purpose is to look for new cookies. That&#8217;s valuable, but it doesn&#8217;t ensure compliance.</p>



<p class="wp-block-paragraph">Our client needed to be certain that non-required cookies weren&#8217;t getting set before consent was granted. I created a script that checks what trackers are set before and after consent. But in order to get this information from their enterprise solution, they had to request a special scan. </p>



<p class="wp-block-paragraph">Even after requesting the special scan, our client only knew what had been set before consent. Not whether cookies were getting set correctly based on the categories users have consented to.</p>



<p class="wp-block-paragraph">I wonder how many organizations think they&#8217;re in clear when it comes to CCPA or GPDR because they&#8217;ve implemented a cookie consent solution, but don&#8217;t realize that their solutions are never checking to make sure they are truly in compliance.</p>

<hr>
<h2>We’re Cloud Four</h2>
<p>We solve complex responsive web design and development challenges for ecommerce, healthcare, fashion, B2B, SaaS, and nonprofit organizations.</p>

<p><a href="https://cloudfour.com/made/"><b>See our work</b></a></p>]]></content:encoded>
					
					<wfw:commentRss>https://cloudfour.com/thinks/most-cookie-consent-banners-dont-check-for-compliance/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">8553</post-id><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://cloudfour.com/wp-content/uploads/2026/04/cookie-compliance-r1.png" width="550" height="309" medium="image" /><enclosure url="https://cloudfour.com/wp-content/uploads/2026/04/cookie-compliance-r1.png" length="0" type="image/png" />	</item>
		<item>
		<title>Weight Loss and the World Wide Web</title>
		<link>https://cloudfour.com/thinks/weight-loss-and-the-world-wide-web/</link>
					<comments>https://cloudfour.com/thinks/weight-loss-and-the-world-wide-web/#respond</comments>
		
		<dc:creator><![CDATA[Jason Grigsby]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 17:03:16 +0000</pubDate>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[Performance]]></category>
		<guid isPermaLink="false">https://cloudfour.com/?p=8530</guid>

					<description><![CDATA[On my successful journey with GLP-1 and my fruitless search to find a similar solution for the bloated mess the web has become.]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img width="1024" height="576" src="https://cloudfour.com/wp-content/uploads/2026/03/20260327-weight-loss-perf-r2-1024x576.jpg" alt="" class="wp-image-8545" srcset="https://cloudfour.com/wp-content/uploads/2026/03/20260327-weight-loss-perf-r2-1024x576.jpg 1024w, https://cloudfour.com/wp-content/uploads/2026/03/20260327-weight-loss-perf-r2-300x169.jpg 300w, https://cloudfour.com/wp-content/uploads/2026/03/20260327-weight-loss-perf-r2-768x432.jpg 768w, https://cloudfour.com/wp-content/uploads/2026/03/20260327-weight-loss-perf-r2-1536x864.jpg 1536w, https://cloudfour.com/wp-content/uploads/2026/03/20260327-weight-loss-perf-r2.jpg 1920w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">Of all the talks I&#8217;ve given, none scared me more than my presentation at the <a href="https://perfnow.nl/2024/">2024 performance.now() conference</a>. The talk was ostensibly about third-party scripts and web performance, but it also touched on a topic embarrassing to me—my weight—and equated it to what I was observing on the web.</p>



<p class="wp-block-paragraph">Two recent events reminded me of this talk, how much has changed for me since then because of GLP-1, and how the same can’t be said for the web.</p>



<h2 class="wp-block-heading"><strong>Struggling to get healthier</strong></h2>



<p class="wp-block-paragraph">I was in a strange place in Fall of 2024. We had spent three and a half years taking care of my father before he passed in October 2023. He had suffered a stroke right before COVID that left him bedridden with a tracheostomy. A respiratory pandemic is difficult enough to survive without a direct path to your lungs.</p>



<p class="wp-block-paragraph">To keep him safe, we took him into our home and became his nurses, respiratory therapists, PTs—anything necessary to keep him alive.&nbsp;</p>



<figure class="wp-block-image size-full"><img width="886" height="886" src="https://cloudfour.com/wp-content/uploads/2026/03/image.jpeg" alt="My father is asleep in a hospital bed in our house. In the foreground, a bag of food hangs off a pole where a machine slowly provided food via a  gastrostomy tube. In the background, a ventilator acts as a BiPap connected to his trach at night. A large leprechaun decoration hangs on the wall. My dad once joked the leprechaun was his childhood friend Gary and after that Gary stayed on the wall year round." class="wp-image-8534" srcset="https://cloudfour.com/wp-content/uploads/2026/03/image.jpeg 886w, https://cloudfour.com/wp-content/uploads/2026/03/image-300x300.jpeg 300w, https://cloudfour.com/wp-content/uploads/2026/03/image-150x150.jpeg 150w, https://cloudfour.com/wp-content/uploads/2026/03/image-768x768.jpeg 768w" sizes="(max-width: 886px) 100vw, 886px" /><figcaption class="wp-element-caption">This was the view from my bed every night for three and half years. I slept downstairs so I could keep an eye on my father and could assist him if his oxygen dropped suddenly.</figcaption></figure>



<p class="wp-block-paragraph">Taking care of him was all-consuming. As a result, our own health suffered. I gained a lot of weight and had a couple of health scares that sent me to the ER. I was pre-diabetic and while my bloodwork wasn’t dangerous yet, it was heading the wrong direction.</p>



<p class="wp-block-paragraph">After my father passed, I was determined to lose weight and get into shape. I didn’t want to put the same burden on our kids that my father had on us.</p>



<p class="wp-block-paragraph">So I set up a home gym in the space that had previously been his hospital room. I started rowing and lifting weights daily for the first time in my life. I purchased an underdesk treadmill so I could exercise while working.</p>



<figure class="wp-block-image size-full"><img width="1024" height="768" src="https://cloudfour.com/wp-content/uploads/2026/03/image-1.jpeg" alt="A photo of our home gym. On the wall is a Tonal system for weight lifting. It is stored away at the moment and looks like a vertical TV. Hanging to the left of the Tonal from the bottom of a shelf are its accessories: a rope, two handles, and bar. To the right of the Tonal is an actual TV. Below it is a Hydrow rowing machine. Around the room are various other workout accessories like dumbbells. The closet doors have mirrors on them." class="wp-image-8535" srcset="https://cloudfour.com/wp-content/uploads/2026/03/image-1.jpeg 1024w, https://cloudfour.com/wp-content/uploads/2026/03/image-1-300x225.jpeg 300w, https://cloudfour.com/wp-content/uploads/2026/03/image-1-768x576.jpeg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Our home gym occupies the same space where my father&#8217;s hospital bed once was. I often think about him while I work out.</figcaption></figure>



<p class="wp-block-paragraph">I saw some improvements. I was stronger than I had ever been and had lost some weight, but I had plateaued. I wasn’t losing weight any more. I felt stuck.</p>



<h2 class="wp-block-heading"><strong>Our clients were stuck too</strong></h2>



<p class="wp-block-paragraph">Around this same time, I was conducting performance audits for some of our clients. I love helping organizations make their websites run faster so working on performance audits is usually one of my favorite tasks. But in these cases, the audits were frustrating.</p>



<p class="wp-block-paragraph">Like the vast majority of websites we see in the wild, the biggest performance problems for our clients were due to third-party scripts. The good news was that I could identify which scripts caused the most issues. I could even show how much faster their site would be if they removed the scripts.</p>



<p class="wp-block-paragraph">The bad news was that even if they wanted to, our clients couldn’t remove the scripts. In one case, the client was using <a href="https://www.bolt.com/checkout">Bolt</a> for their cart and checkout. Bolt was a massive React app that weighed in at nearly 1MB. It slowed down the most critical parts of an ecommerce funnel. But <a href="https://cloudfour.com/thinks/who-can-you-trust-with-your-online-business/#call-2-the-ecommerce-company">they couldn’t remove it</a> without breaking core functionality.</p>



<h2 class="wp-block-heading"><strong>Ozempic and other GLP-1s</strong></h2>



<p class="wp-block-paragraph">It didn’t seem to matter how much I worked out. I wasn’t losing weight. So I started researching Ozempic and other GLP-1s.</p>



<p class="wp-block-paragraph">I was intrigued by the way <a href="https://chriscoyier.net/2023/03/09/semaglutide/">Chris Coyier</a> and Paul Ford described their own experiences. Paul Ford <a href="https://www.wired.com/story/new-drug-switched-off-appetite-mounjaro/">wrote</a>:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Where before my brain had been screaming, screaming, at air-raid volume—there was sudden silence. It was confusing. Would it last?</p>



<p class="wp-block-paragraph">I went alone that night to a Chinese restaurant, the old-school kind with tables, and ordered General Tso’s. I ate the broccoli, a few pieces of chicken, and thought: too gloopy. I left it unfinished, went home in confusion, a different kind of sleepwalker. I passed bodegas and shrugged. At an office I observed the stack of candies and treats with no particular interest.</p>



<p class="wp-block-paragraph">Decades of struggle—poof.&nbsp;</p>
</blockquote>



<p class="wp-block-paragraph">Before I started using GLP-1, it had already changed me. The success of these drugs made me reassess my relationship to weight loss. If the food noise in my head could be tamed with medication, then perhaps my weight wasn’t a personal failing.&nbsp;</p>



<p class="wp-block-paragraph">I wasn’t weak. I was just wired in a way that caused my brain to think I was hungry when I wasn’t. And I could be rewired.</p>



<h2 class="wp-block-heading"><strong>What about a GLP-1 for the web?</strong></h2>



<p class="wp-block-paragraph">As preparation for my talk heated up, I found myself researching third-party scripts during the day and GLP-1s at night. It’s no surprise I started to see parallels between them.</p>



<figure class="wp-block-image size-large"><img width="1024" height="379" src="https://cloudfour.com/wp-content/uploads/2026/03/image-4-1024x379.png" alt="A screenshot of a Jeffrey Zeldman tweet. In the tweet, he quotes me at An Event Apart Orlando saying, &quot;We've made the internet in our own image. Which, in the United States, means obese.&quot;" class="wp-image-8542" srcset="https://cloudfour.com/wp-content/uploads/2026/03/image-4-1024x379.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/image-4-300x111.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/image-4-768x284.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/image-4.png 1190w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">This isn&#8217;t the first time I&#8217;ve drawn a parallel between web performance and unhealthy weight. It used to be a punchline in my talks about the mobile web.</figcaption></figure>



<p class="wp-block-paragraph">Most website owners know how important performance is for user experience and how it impacts conversions and revenue. They want a fast site.&nbsp;</p>



<p class="wp-block-paragraph">And yet websites continue to grow in size. Even ecommerce sites which have a strong financial motivation to fix performance issues get larger every year on average.</p>



<p class="wp-block-paragraph">I knew I needed help to get unstuck. Maybe my clients did too?</p>



<p class="wp-block-paragraph">I started looking for something akin to a GLP-1 for the web. I knew it wouldn’t solve every problem, but maybe a little boost would help. Was there some way we could rewire the web like I hoped GLP-1 would rewire my brain?</p>



<p class="wp-block-paragraph">This became a focal point of my research. I looked into <a href="https://partytown.qwik.dev/">Partytown</a> which tries to move third-party scripts off the main thread and onto a web worker where they will have less impact on the user. I explored <a href="https://www.cloudflare.com/application-services/products/zaraz/">Cloudflare’s Zaraz</a> product which attempts something similar using Edge Workers. I revisited <a href="https://developers.google.com/tag-platform/tag-manager/server-side">server-side Google Tag Manager</a> for the umpteenth time hoping that this time it seemed more likely to work for our clients.</p>



<figure class="wp-block-image size-large is-style-outlined"><img width="1024" height="588" src="https://cloudfour.com/wp-content/uploads/2026/03/image-2-1024x588.png" alt="A diagram from the Partytown website that visualizes how it works. On the left in an image titled &quot;Without Partytown,&quot; it shows a funnel labeled main thread with orange and blue circles in it. The blue circles represent your code and the orange third-party scripts. Both are competing to get through the funnel.

On the right is a diagram entitled &quot;With Partytown.&quot; This diagram has two funnels. One is labeled main thread and only has blue circles representing your code. The second funnel is labeled worker thread where all of the third-party, orange circles are now found." class="wp-image-8533" srcset="https://cloudfour.com/wp-content/uploads/2026/03/image-2-1024x588.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/image-2-300x172.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/image-2-768x441.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/image-2-1536x882.png 1536w, https://cloudfour.com/wp-content/uploads/2026/03/image-2.png 1957w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Partytown has been a bit of an obsession for me. It makes so much sense to move JavaScript off the main thread, and it worked well on one project…until it didn&#8217;t and the client removed it.</figcaption></figure>



<p class="wp-block-paragraph">But every one of these solutions had significant drawbacks. They are all difficult to implement. I wasn’t certain how I could tell if third-party scripts were still working, especially when we don’t usually have access to the dashboards for these services.</p>



<p class="wp-block-paragraph">That’s not to say that some people aren’t having success with them. Julian Jandl shared <a href="https://www.youtube.com/watch?v=rFrqJQshh6M&amp;list=PLjnstNlepBvNBmLtuc8GHaVfjFUdI36Cq&amp;index=8">how they’ve been using Partytown successfully</a> at performance.sync() 2025. I think it is easier for internal teams to experiment with solutions like this than it is for our clients to sign up for something unproven.</p>



<p class="wp-block-paragraph">If I was working on the talk today, I’m sure someone in the audience would ask if AI could help. If AI will cure cancer, surely it can solve web site bloat.</p>



<p class="wp-block-paragraph">Unfortunately, most AI-generated websites seem to have performance problems. Tim Kadlec points out that <a href="https://bsky.app/profile/did:plc:vkym4t5ccdd3tidm32pkz2ke/post/3mhxwzlsqhc2b">JavaScript bytes on the web have exploded since May 2025</a>—the month when Claude Code, Github Copilot Coding Agent, and Cursor AI agents launched.</p>



<figure class="wp-block-image size-large"><a href="https://bsky.app/profile/did:plc:vkym4t5ccdd3tidm32pkz2ke/post/3mhxwzlsqhc2b"><img width="1024" height="399" src="https://cloudfour.com/wp-content/uploads/2026/03/image-1024x399.png" alt="Tim Kadlec's Blusky post says, &quot;p75 and p90 JavaScript bytes on the web have exploded since May, 2025—easily the largest 10 month period based on HTTP Archive data since 2023. 

The long-tail is getting worse, very quickly.

Gemini, what happened in May 2025?&quot;" class="wp-image-8531" srcset="https://cloudfour.com/wp-content/uploads/2026/03/image-1024x399.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/image-300x117.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/image-768x300.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/image.png 1174w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></figure>



<p class="wp-block-paragraph">I suppose it doesn’t have to be that way. In theory, you can add enough context or constraints to get a performant experience out of AI, but that would require people to prioritize it. It doesn’t happen by default. So I don’t see AI solving the web&#8217;s performance problems (or cancer) any time soon.</p>



<h2 class="wp-block-heading"><strong>Video of my presentation</strong></h2>



<p class="wp-block-paragraph">While I didn’t find a GLP-1 for the web, I’m still proud of the talk. There are many practical suggestions on how to analyze and manage third-party scripts.&nbsp;</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Third Party Woes | Jason Grigsby | performance.now() 2024" width="500" height="281" src="https://www.youtube.com/embed/wI5frInvfQM?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p class="wp-block-paragraph">I recommend watching the talk, but I’ll admit I have a hard time doing so. I was going to send it to a client last week and was shocked at how big I look in the video.</p>



<h2 class="wp-block-heading"><strong>My Tirzepatide journey</strong></h2>



<p class="wp-block-paragraph">I nearly started GLP-1 before the performance.now() conference, but I was worried about potential side effects before the trip. I didn’t want indigestion during the conference or after it when my family was meeting me for a vacation.</p>



<p class="wp-block-paragraph">After we returned home, the holidays took precedence. In early 2025, I read about the FDA <a href="https://thehill.com/policy/healthcare/5158023-ozempic-and-wegovy-officially-moved-off-fdas-drug-shortage-list/">removing some GLP-1s from the shortage list</a> which meant compounding pharmacies could no longer make it. Compounding pharmacies were providing affordable alternatives. I knew I couldn’t afford the full price, and my insurance wasn’t going to cover it.</p>



<p class="wp-block-paragraph">So I gave up for a bit until a friend who I hadn’t seen in a few months visited. I was stunned by his transformation. He was on Tirzepatide (a different GLP-1) and looked like an entirely different person.</p>



<figure class="wp-block-image size-large"><img width="1024" height="832" src="https://cloudfour.com/wp-content/uploads/2026/03/7062B6D6-668F-4B7D-A94F-C086885499EC_1_201_a-1024x832.jpeg" alt="A line graph from the health app shows my weight loss over the last several months. The graph shows a gentle increase in April and May of last year before a big drop starts in June." class="wp-image-8541" srcset="https://cloudfour.com/wp-content/uploads/2026/03/7062B6D6-668F-4B7D-A94F-C086885499EC_1_201_a-1024x832.jpeg 1024w, https://cloudfour.com/wp-content/uploads/2026/03/7062B6D6-668F-4B7D-A94F-C086885499EC_1_201_a-300x244.jpeg 300w, https://cloudfour.com/wp-content/uploads/2026/03/7062B6D6-668F-4B7D-A94F-C086885499EC_1_201_a-768x624.jpeg 768w, https://cloudfour.com/wp-content/uploads/2026/03/7062B6D6-668F-4B7D-A94F-C086885499EC_1_201_a.jpeg 1057w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Can you tell from this graph when I started taking Tirzepatide?</figcaption></figure>



<p class="wp-block-paragraph">His experience inspired me to give it another try. I took my first shot of Tirzepatide on June 27, 2025. I still have more to go, but I’ve lost 50 pounds so far. I’m at the lowest weight since college. I can now see the evidence of my daily workouts. And most importantly, my blood work is trending in the right direction.</p>



<figure class="wp-block-image size-full"><img width="768" height="1024" src="https://cloudfour.com/wp-content/uploads/2026/03/image-3.jpeg" alt="I photo of me taken in a mirror. I'm wearing jeans and a black Star Wars shirt. I'm not thin, but I'm much healthier than I was at performance.now() in 2024." class="wp-image-8537" srcset="https://cloudfour.com/wp-content/uploads/2026/03/image-3.jpeg 768w, https://cloudfour.com/wp-content/uploads/2026/03/image-3-225x300.jpeg 225w" sizes="(max-width: 768px) 100vw, 768px" /><figcaption class="wp-element-caption">I can&#8217;t remember the last time I took a photo of myself that I liked, but I don&#8217;t hate this recent one.</figcaption></figure>



<h2 class="wp-block-heading"><strong>The 49MB Web Page</strong></h2>



<p class="wp-block-paragraph">Unfortunately, the story for the web over the same period hasn’t been great. One of the triggers for revisiting my presentation was this excellent article by Shubham Bose examining a <a href="https://thatshubham.com/blog/news-audit">49MB New York Times article</a>.</p>



<figure class="wp-block-image size-large"><img width="1024" height="576" src="https://cloudfour.com/wp-content/uploads/2026/03/image-3-1024x576.png" alt="A screenshot of Shubham Bose's article entitled &quot;The 49MB Web Page.&quot; " class="wp-image-8538" srcset="https://cloudfour.com/wp-content/uploads/2026/03/image-3-1024x576.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/image-3-300x169.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/image-3-768x432.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/image-3-1536x864.png 1536w, https://cloudfour.com/wp-content/uploads/2026/03/image-3.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">Bose points out all of the privacy and user hostile code being used on the web these days. Most of this code comes from third-party scripts.</p>



<p class="wp-block-paragraph">And maybe it’s a bit of silly numerology, but I couldn’t help but feel some kinship to this random NYT article. The page weighs 49MB. I’ve lost 50 pounds.</p>



<p class="wp-block-paragraph">I wish I could share some of my Tirzepatide with these pages.</p>



<h2 class="wp-block-heading"><strong>Open for discussion</strong></h2>



<p class="wp-block-paragraph">I like helping people build faster websites, but I can only help so many clients at a time. It’s a drop in the bucket compared to the direction the web is headed. It feels as futile as dieting.</p>



<p class="wp-block-paragraph">The main purpose for my talk was to spur discussion in the web performance community because I believe only collective action on third-party scripts can make a difference. I don’t know if we will be able to find some miracle GLP-1-like solution for third-parties. But maybe we can make it easier for people to learn which third-party scripts are better from a performance standpoint. That would be a good start.</p>



<p class="wp-block-paragraph">In a similar vein, I’d like this article to be the starting point for discussion. If you want to brainstorm ways to handle third-parties and make the web faster, I’d love to hear about it—particularly if you’ve successfully used PartyTown, Zaraz, or server-side GTM.&nbsp;</p>



<p class="wp-block-paragraph">I’m also open to talking about weight loss and my experience with Tirzepatide. I’m keenly aware of how difficult it can be to talk about these things. I’ve been too embarrassed to do so for years. But Tirzepatide has made a huge difference for me so I’m happy to share what I’ve learned.</p>



<p class="wp-block-paragraph">So I’m open for discussion. You can ask me anything. You can reach out publicly or privately. I’m happy to talk about either topic or anything else that may be on your mind. We&#8217;re all in this together.</p>



<p class="wp-block-paragraph">P.S. <a href="https://cloudfour.com/thinks/more-projects-please/">We&#8217;re looking for projects</a>. Please spread the word.</p>

<hr>
<h2>We’re Cloud Four</h2>
<p>We solve complex responsive web design and development challenges for ecommerce, healthcare, fashion, B2B, SaaS, and nonprofit organizations.</p>

<p><a href="https://cloudfour.com/made/"><b>See our work</b></a></p>]]></content:encoded>
					
					<wfw:commentRss>https://cloudfour.com/thinks/weight-loss-and-the-world-wide-web/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">8530</post-id><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://cloudfour.com/wp-content/uploads/2026/03/20260327-weight-loss-perf-r2.jpg" width="550" height="309" medium="image" /><enclosure url="https://cloudfour.com/wp-content/uploads/2026/03/20260327-weight-loss-perf-r2.jpg" length="0" type="image/jpg" />	</item>
		<item>
		<title>More Projects Please</title>
		<link>https://cloudfour.com/thinks/more-projects-please/</link>
					<comments>https://cloudfour.com/thinks/more-projects-please/#respond</comments>
		
		<dc:creator><![CDATA[Tyler Sticka]]></dc:creator>
		<pubDate>Mon, 30 Mar 2026 15:38:36 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Process]]></category>
		<category><![CDATA[UX]]></category>
		<guid isPermaLink="false">https://cloudfour.com/?p=8529</guid>

					<description><![CDATA[We’re actively seeking new UX design, UI design or hybrid creative/development challenges to solve.]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img width="1920" height="960" src="https://cloudfour.com/wp-content/uploads/2026/03/cloud-four-and-you-r3-wide.png" alt="Cloud Four and you" class="wp-image-8544" srcset="https://cloudfour.com/wp-content/uploads/2026/03/cloud-four-and-you-r3-wide.png 1920w, https://cloudfour.com/wp-content/uploads/2026/03/cloud-four-and-you-r3-wide-300x150.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/cloud-four-and-you-r3-wide-1024x512.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/cloud-four-and-you-r3-wide-768x384.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/cloud-four-and-you-r3-wide-1536x768.png 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /></figure>



<p class="wp-block-paragraph">I&#8217;ll cut to the chase: Our calendar is light, and <a href="https://cloudfour.com/and-you/">we need more projects</a>. Especially projects with a <strong>UX design</strong>, <strong>UI design</strong> or <strong>hybrid creative/development</strong> focus.</p>



<p class="wp-block-paragraph"><strong>Small projects?</strong> No prob, we&#8217;ve got individual high-velocity contributors to spare, ready to slot in at any project stage.</p>



<p class="wp-block-paragraph"><strong>Large projects?</strong> Bring it on: Our unique approach scales well to big problems, like <a href="https://cloudfour.com/does/legacy-app-modernization/" data-type="link" data-id="https://cloudfour.com/does/legacy-app-modernization/">modernizing legacy applications</a> or building up <a href="https://cloudfour.com/made/baptist-health/">multi-brand design systems</a>. (Once you&#8217;ve made <a href="https://cloudfour.com/made/walmart/">Walmart&#8217;s cart and checkout responsive</a>, you can do anything!)</p>



<p class="wp-block-paragraph">(Already know us? <a href="#how-to-help" data-type="internal" data-id="#how-to-help">Skip to ways you can help</a>)</p>



<h2 class="wp-block-heading">Why Cloud Four?</h2>



<ul class="wp-block-list">
<li>Your audience deserves better than <em>just another</em> sluggish, inaccessible, generic web experience.</li>



<li>Our fast-paced, collaborative process keeps your team engaged and your goals in focus.</li>



<li>Interactive, browser-based deliverables remove guesswork from the review process while streamlining implementation.</li>



<li>You&#8217;ll support a small, independent company that&#8217;s served customers for almost 20 years while sharing more than 25 talks, 80 code repositories and 500 (!!) articles for free with their community.</li>
</ul>



<h2 class="wp-block-heading">What clients say</h2>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Cloud Four really dug in to understand what our customers needed and how our business worked. We chose Cloud Four for their web expertise, but <a href="https://cloudfour.com/made/imagequix/">what they delivered</a> would be world-class on any platform. I’m so proud of what we accomplished together.</p>
</blockquote>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Cloud Four’s process stands out for being so transparent, iterative and collaborative. They listened carefully to our goals, asked tough but important questions, and encouraged contributions from everyone. I’m amazed by how much <a href="https://cloudfour.com/made/baptist-health/">our web experiences transformed with their guidance</a>.</p>
</blockquote>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Cloud Four not only massively simplified our <a href="https://cloudfour.com/does/ecommerce/">purchasing flow</a> but also prototyped a foundation for our future plans. On top of that, they were also an absolute pleasure to work with. Professional, thoughtful, and most importantly fun.</p>
</blockquote>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><a href="https://cloudfour.com/made/cloudinary-interactive-demo/">The API Explorer demo</a> has been a big help in explaining our APIs to developers. It increased engagement over 400% and improved the quality of our conversions.</p>
</blockquote>



<h2 class="wp-block-heading">How to help</h2>



<p class="wp-block-paragraph"><strong>If you have (or <em>may</em> have) a project</strong>, get in touch via <a href="https://cloudfour.com/and-you/">our contact form, email or phone</a>.</p>



<p class="wp-block-paragraph"><strong>If you have a boss or hiring manager in charge of contracting design resources</strong>, recommend us to them, share this post, or <a href="https://cloudfour.com/and-you/">reach out</a> to make that connection directly.</p>



<p class="wp-block-paragraph"><strong>Share this post</strong> (or <a href="https://cloudfour.com/thinks/">any article</a> you find more relevant) with friends, family, forums, work chats, or social connections who might benefit from (or amplify) our services.</p>



<p class="wp-block-paragraph">It&#8217;s thanks to our amazing clients we&#8217;ve been able to ship so many exceptional experiences over the past 19 years, continually sharing what we learn along the way. I hope you&#8217;ll be part of that journey soon!</p>



<p class="wp-block-paragraph"></p>

<hr>
<h2>We’re Cloud Four</h2>
<p>We solve complex responsive web design and development challenges for ecommerce, healthcare, fashion, B2B, SaaS, and nonprofit organizations.</p>

<p><a href="https://cloudfour.com/made/"><b>See our work</b></a></p>]]></content:encoded>
					
					<wfw:commentRss>https://cloudfour.com/thinks/more-projects-please/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">8529</post-id><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://cloudfour.com/wp-content/uploads/2026/03/cloud-four-and-you-r3.png" width="550" height="309" medium="image" /><enclosure url="https://cloudfour.com/wp-content/uploads/2026/03/cloud-four-and-you-r3.png" length="0" type="image/png" />	</item>
		<item>
		<title>GPC Opt Out: UX Fails or Malicious Compliance?</title>
		<link>https://cloudfour.com/thinks/gpc-opt-out-ux-fails-or-malicious-compliance/</link>
					<comments>https://cloudfour.com/thinks/gpc-opt-out-ux-fails-or-malicious-compliance/#respond</comments>
		
		<dc:creator><![CDATA[Jason Grigsby]]></dc:creator>
		<pubDate>Mon, 23 Mar 2026 17:11:18 +0000</pubDate>
				<category><![CDATA[Essentials]]></category>
		<category><![CDATA[Privacy]]></category>
		<category><![CDATA[UX]]></category>
		<guid isPermaLink="false">https://cloudfour.com/?p=8513</guid>

					<description><![CDATA[As of Jan 1, the CCPA requires websites to confirm they are honoring Global Privacy Control (GPC) opt outs. Why are so many cookie banners complying with the new rule in ways certain to confuse users?]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img width="1600" height="900" src="https://cloudfour.com/wp-content/uploads/2026/03/gpc-opt-out-feature-r1.png" alt="" class="wp-image-8522" srcset="https://cloudfour.com/wp-content/uploads/2026/03/gpc-opt-out-feature-r1.png 1600w, https://cloudfour.com/wp-content/uploads/2026/03/gpc-opt-out-feature-r1-300x169.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/gpc-opt-out-feature-r1-1024x576.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/gpc-opt-out-feature-r1-768x432.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/gpc-opt-out-feature-r1-1536x864.png 1536w" sizes="(max-width: 1600px) 100vw, 1600px" /></figure>



<p class="wp-block-paragraph">Starting on January 1, the California Consumer Privacy Act (CCPA) requires that websites provide confirmation that they have honored a user&#8217;s Global Privacy Control (GPC) opt out. Unfortunately, many cookie consent banners are doing this in the most confusing way possible and making me wonder if they are doing it intentionally or not.</p>



<h2 class="wp-block-heading">What is Global Privacy Control?</h2>



<p class="wp-block-paragraph">Global Privacy Control is a <a href="https://w3c.github.io/gpc/">web standard</a> that allows users to tell websites that they wish to opt out of having their information tracked or sold. In theory, if you have set Global Privacy Control, you shouldn&#8217;t see any cookie consent banners.</p>



<p class="wp-block-paragraph">Global Privacy Control works behind the scenes by setting two values. One is an HTTP Header, <code>Sec-GPC: 1</code>, that is sent by the browser with every request to a server. The second value makes sure GPC is available to JavaScript by setting <code>navigator.globalPrivacyControl</code>&nbsp;property to&nbsp;<code>true</code>. </p>



<p class="wp-block-paragraph">Some browsers—Firefox, DuckDuckGo, and Brave among them—implement GPC support by default. For other browsers, you can install extensions like the Electronic Freedom Foundation&#8217;s <a href="https://privacybadger.org/" data-type="link" data-id="https://privacybadger.org/">Privacy Badger</a>. If you want to test to see if your browser is sending GPC correctly, you can test it on the <a href="https://globalprivacycontrol.org/">Global Privacy Control informational site</a>.</p>



<figure class="wp-block-image size-full"><img width="1400" height="788" src="https://cloudfour.com/wp-content/uploads/2026/03/gpc-website.jpg" alt="" class="wp-image-8514" srcset="https://cloudfour.com/wp-content/uploads/2026/03/gpc-website.jpg 1400w, https://cloudfour.com/wp-content/uploads/2026/03/gpc-website-300x169.jpg 300w, https://cloudfour.com/wp-content/uploads/2026/03/gpc-website-1024x576.jpg 1024w, https://cloudfour.com/wp-content/uploads/2026/03/gpc-website-768x432.jpg 768w" sizes="(max-width: 1400px) 100vw, 1400px" /><figcaption class="wp-element-caption">The Global Privacy Control informational website displays a banner at the top of the page to let you know if your browser sent a GPC signal or not.</figcaption></figure>



<h2 class="wp-block-heading">What happened to Do Not Track?</h2>



<p class="wp-block-paragraph">Some of you may be wondering how Global Privacy Controls differ from an earlier solution called <a href="https://en.wikipedia.org/wiki/Do_Not_Track">Do Not Track</a>. While Do Not Track also used HTTP Headers to opt out of tracking, it wasn&#8217;t an official standard, and never gained traction with website owners. In 2019, the working group behind Do Not Track disbanded, and browsers started removing support for it.</p>



<p class="wp-block-paragraph">The biggest difference between Do Not Track and GPC is that GPC has been codified in law. <a href="https://cookie-script.com/privacy-laws/global-privacy-control-vs-do-not-track" data-type="link" data-id="https://cookie-script.com/privacy-laws/global-privacy-control-vs-do-not-track">Eleven states</a> require businesses to honor GPC opt outs. The EU&#8217;s General Data Protection Regulation (GDPR) was written before GPC was created, but it likely that GPC still applies under GDPR. According to <a href="https://cookie-script.com/privacy-laws/global-privacy-control-vs-do-not-track">CookieScript</a>, &#8220;While not explicitly mentioned in the GDPR regulation, the principles of &#8216;Privacy by Design&#8217; and &#8216;Ease of Withdrawal&#8217; make GPC signal a requirement to honor user opt-out choices.&#8221;</p>



<h2 class="wp-block-heading">UX fails or malicious compliance?</h2>



<p class="wp-block-paragraph">All of this brings me back to California&#8217;s new GPC confirmation rule and the odd way that cookie consent solutions have implemented it. Digital compliance vendor Clym <a href="https://www.clym.io/blog/ccpa-selling-and-sharing-what-counts-as-a-sale-or-share">describes the new rule</a> thusly:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Starting in 2026, it is no longer sufficient to simply process an opt-out silently. If you receive an opt-out signal (like the Global Privacy Control), you must explicitly&nbsp;<strong>display a confirmation</strong>&nbsp;to the user.</p>



<ul class="wp-block-list">
<li><strong>Requirement:</strong>&nbsp;You may need to display a message like &#8220;Opt-Out Request Honored&#8221; or show a toggle in the user’s privacy settings indicating they have opted out.</li>



<li>This allows consumers to know that their automated browser signals are working.</li>
</ul>
</blockquote>



<p class="wp-block-paragraph">Because I have GPC turned on in my browser, I began to see these confirmations. Unfortunately, it is often not clear what I should do with the information. For example, this is what I saw on a recent website using OneTrust for cookie management:</p>



<figure class="wp-block-image size-full is-style-outlined"><img width="912" height="640" src="https://cloudfour.com/wp-content/uploads/2026/03/onetrust-opt-out-honored-2.png" alt="" class="wp-image-8525" srcset="https://cloudfour.com/wp-content/uploads/2026/03/onetrust-opt-out-honored-2.png 912w, https://cloudfour.com/wp-content/uploads/2026/03/onetrust-opt-out-honored-2-300x211.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/onetrust-opt-out-honored-2-768x539.png 768w" sizes="(max-width: 912px) 100vw, 912px" /></figure>



<p class="wp-block-paragraph">It&#8217;s nice to see confirmation that my opt out preference has been honored, but what am I supposed to do now?</p>



<p class="wp-block-paragraph">There is a big button that says, &#8220;Accept All Cookies&#8221; that appears to be my main option. If I click on it, will the site still honor my opt out? Or will clicking on the button override GPC?</p>



<p class="wp-block-paragraph">I decided to give it try, and as expected, clicking the only button available to me overrode my opt out.</p>



<figure class="wp-block-image size-large is-style-outlined"><img width="579" height="1024" src="https://cloudfour.com/wp-content/uploads/2026/03/onetrust-privacy-center-1-579x1024.png" alt="OneTrust's Privacy Preference Center panel. At the top, the same green box from earlier says, &quot;Your Opt out Preference Signal is Honored.&quot; At the bottom, every cookie consent category is turned on." class="wp-image-8518" srcset="https://cloudfour.com/wp-content/uploads/2026/03/onetrust-privacy-center-1-579x1024.png 579w, https://cloudfour.com/wp-content/uploads/2026/03/onetrust-privacy-center-1-170x300.png 170w, https://cloudfour.com/wp-content/uploads/2026/03/onetrust-privacy-center-1-768x1359.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/onetrust-privacy-center-1.png 837w" sizes="(max-width: 579px) 100vw, 579px" /></figure>



<p class="wp-block-paragraph">I find this preferences panel hilarious. It says it has honored my opt out, but every bit of tracking has been turned on. I tested a few other cookie consent options and found similar interfaces where you&#8217;re informed that your opt-out has been honored, but you&#8217;re still forced to make a choice about what cookies you will allow.</p>



<figure class="wp-block-image size-full"><img width="872" height="554" src="https://cloudfour.com/wp-content/uploads/2026/03/osano-banner-2.png" alt="" class="wp-image-8521" srcset="https://cloudfour.com/wp-content/uploads/2026/03/osano-banner-2.png 872w, https://cloudfour.com/wp-content/uploads/2026/03/osano-banner-2-300x191.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/osano-banner-2-768x488.png 768w" sizes="(max-width: 872px) 100vw, 872px" /><figcaption class="wp-element-caption">In this example from Osano, the Opt-Out Signal is Honored, but you still have to choose to between &#8220;Accept,&#8221; &#8220;Deny Non-Essential,&#8221; and &#8220;Manage Preferences&#8221; buttons.</figcaption></figure>



<p class="wp-block-paragraph">I know that for any of these banners, I can click on the cookies settings link to adjust my preferences, but isn&#8217;t the whole point of the GPC opt out to streamline the process so users don&#8217;t have to manually opt out?</p>



<p class="wp-block-paragraph">By contrast, the best implementation I&#8217;ve seen was a small notification that my opt-out had been honored. That&#8217;s it. No further action required. I believe this is what California was hoping for when it added this new requirement.</p>



<p class="wp-block-paragraph">It seems the new rule has surprised cookie consent managers. In my testing, many of them do not yet honor the notification requirement even if they honor GPC behind the scenes. So perhaps these broken and confusing user experiences are because notifications are being quickly grafted onto existing applications.</p>



<p class="wp-block-paragraph">However, when I see that the service is aware that I&#8217;ve opted out, and the only button it provides is one to accept all cookies, I find myself wondering if it is intentional. I know <a href="https://en.wikipedia.org/wiki/Hanlon's_razor">Hanlon&#8217;s Razor</a> says we shouldn&#8217;t immediately ascribe situations like this to malice so I&#8217;m hopeful that over time cookie consent banners will do a better job of honoring GPC opt outs.</p>



<p class="wp-block-paragraph">If you&#8217;re interested in learning more about privacy and cookies, check out my recent two-part series on <a href="https://cloudfour.com/thinks/cookie-consent-management-in-2026-part-1-overview/" data-type="link" data-id="https://cloudfour.com/thinks/cookie-consent-management-in-2026-part-1-overview/">cookie consent management in 2026</a>.</p>

<hr>
<h2>We’re Cloud Four</h2>
<p>We solve complex responsive web design and development challenges for ecommerce, healthcare, fashion, B2B, SaaS, and nonprofit organizations.</p>

<p><a href="https://cloudfour.com/made/"><b>See our work</b></a></p>]]></content:encoded>
					
					<wfw:commentRss>https://cloudfour.com/thinks/gpc-opt-out-ux-fails-or-malicious-compliance/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">8513</post-id><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://cloudfour.com/wp-content/uploads/2026/03/gpc-opt-out-feature-r1.png" width="550" height="309" medium="image" /><enclosure url="https://cloudfour.com/wp-content/uploads/2026/03/gpc-opt-out-feature-r1.png" length="0" type="image/png" />	</item>
		<item>
		<title>Cookie Consent Management in 2026, Part 2: Technical Tips</title>
		<link>https://cloudfour.com/thinks/cookie-consent-management-in-2026-part-2-technical-tips/</link>
					<comments>https://cloudfour.com/thinks/cookie-consent-management-in-2026-part-2-technical-tips/#respond</comments>
		
		<dc:creator><![CDATA[Jason Grigsby]]></dc:creator>
		<pubDate>Thu, 19 Mar 2026 16:35:34 +0000</pubDate>
				<category><![CDATA[Essentials]]></category>
		<category><![CDATA[Privacy]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://cloudfour.com/?p=8509</guid>

					<description><![CDATA[Testing cookies consent compliance proved more difficult than I expected. Here are some tips and tricks I learned while conducting a cookie compliance audit.]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img width="1600" height="900" src="https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-2.png" alt="" class="wp-image-8511" srcset="https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-2.png 1600w, https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-2-300x169.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-2-1024x576.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-2-768x432.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-2-1536x864.png 1536w" sizes="(max-width: 1600px) 100vw, 1600px" /></figure>



<p class="wp-block-paragraph">In <a href="https://cloudfour.com/thinks/cookie-consent-management-in-2026-part-1-overview/">part one</a> of this series, I shared some high-level thoughts on why organizations are increasingly focused on cookie consent and some things I&#8217;ve learned about how to pick a good solution and roll it out in your organization.</p>



<p class="wp-block-paragraph">In this article, I want to focus on the more technical aspects of identifying what source is setting a cookie so that you can ensure that your cookie consent solution is handling it properly.</p>



<h2 class="wp-block-heading">Turn off content blockers</h2>



<p class="wp-block-paragraph">In order to test what cookies <em>could</em> be set, you have to turn off any features that may block cookies. For me, that meant turning down browser privacy setting and turning off extensions like Privacy Badger and uBlock Origin. My home network runs on Eero Plus which also features ad blocking. Everything had to be turned off.</p>



<h2 class="wp-block-heading">Don&#8217;t use default Incognito mode</h2>



<p class="wp-block-paragraph">Chrome in Incognito mode is my default testing environment. Incognito mode provides a clean slate when I&#8217;m troubleshooting performance issues.</p>



<p class="wp-block-paragraph">However, I wasn&#8217;t seeing some of the cookies I expected in my tests. Turns out that when Chrome is in Incognito mode, it blocks third-party cookies by default. You can bypass this behavior by clicking on the eye icon in the toolbar.</p>



<p class="wp-block-paragraph">I used Incognito almost exclusively for my testing which means I&#8217;ve have been doing this wrong for years. </p>



<h2 class="wp-block-heading">Lazy-loading and dynamic cookies</h2>



<p class="wp-block-paragraph">As I ran my tests, I started to see cookies that only showed up occasionally. I finally figured out that these cookies were set by scripts that were lower on the page and were only loaded when someone scrolled down.</p>



<p class="wp-block-paragraph">In addition, ad networks can include different scripts which in turn set different cookies based on a user&#8217;s geography, etc. These dynamic insertions are hard to predict. Thankfully, these changing cookies seem primarily limited to ad networks so if you categorize the parent script correctly, then any additional cookies added later will also be categorized correctly.</p>



<h2 class="wp-block-heading">Finding the cookie culprit</h2>



<p class="wp-block-paragraph">Figuring out what asset set a cookie can be challenging. When you look at the list of cookies in Dev Tools, you can get some hints about what might be setting the cookie from the cookie&#8217;s name and domain. If you&#8217;re lucky, there is only one asset coming from the domain, and you&#8217;ve found your culprit. Most of the time, you won&#8217;t be that lucky.</p>



<p class="wp-block-paragraph">Unfortunately, the cookie panel doesn&#8217;t contain the equivalent of the <a href="https://www.debugbear.com/docs/request-initiator-chain" data-type="link" data-id="https://www.debugbear.com/docs/request-initiator-chain">initiator column</a> in Chrome&#8217;s network panel. When I&#8217;m conducting performance audits, I rely on the initiator section to help me track down the chain of requests that led to an asset getting downloaded. I&#8217;d love to have something similar for cookies.</p>



<p class="wp-block-paragraph">Instead, you either need to make some intelligent guesses or create some tooling. Absent tooling, my investigation steps look something like this.</p>



<p class="wp-block-paragraph">First, I look at the domain name and tracker name to try to determine what service I think might be setting a cookie. For example, a cookie with the domain set to <code>.linkedin.com</code> with the name <code>__cf_bm</code> likely was set by a LinkedIn script and the <code>cf</code> name suggests that the cookie is related to Cloudflare.</p>



<figure class="wp-block-image size-full"><img width="2154" height="1140" src="https://cloudfour.com/wp-content/uploads/2026/03/linkedin-cloudflare.png" alt="Screenshot of the cookies tab in Chrome Dev Tools. A cookie named __cf_bm with the domain .linkedin.com is highlighted." class="wp-image-8502" srcset="https://cloudfour.com/wp-content/uploads/2026/03/linkedin-cloudflare.png 2154w, https://cloudfour.com/wp-content/uploads/2026/03/linkedin-cloudflare-300x159.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/linkedin-cloudflare-1024x542.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/linkedin-cloudflare-768x406.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/linkedin-cloudflare-1536x813.png 1536w, https://cloudfour.com/wp-content/uploads/2026/03/linkedin-cloudflare-2048x1084.png 2048w" sizes="(max-width: 2154px) 100vw, 2154px" /></figure>



<p class="wp-block-paragraph">I&#8217;ll then look up the cookie using a service like <a href="https://cookiesearch.org/">Cookiesearch.org</a>. In this example, the search will tell me that <a href="https://cookiesearch.org/cookies/?search-term=__cf_bm&amp;filter-type=cookie-name&amp;sort=asc&amp;cookie-id=__cf_bm"><code>__cf_bm</code> is set by Cloudflare</a> and &#8220;is used to support Cloudflare Bot Management.&#8221;</p>



<p class="wp-block-paragraph">Once I have a domain for the cookie, I turn to the network panel to see if I can find the culprit. I&#8217;ll filter the network panel to only show assets coming from suspect domain.</p>



<figure class="wp-block-image size-full"><img width="2542" height="1192" src="https://cloudfour.com/wp-content/uploads/2026/03/filtering-network-panel.png" alt="Network panel in Dev Tools filtered to only show assets coming from Linkedin." class="wp-image-8503" srcset="https://cloudfour.com/wp-content/uploads/2026/03/filtering-network-panel.png 2542w, https://cloudfour.com/wp-content/uploads/2026/03/filtering-network-panel-300x141.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/filtering-network-panel-1024x480.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/filtering-network-panel-768x360.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/filtering-network-panel-1536x720.png 1536w, https://cloudfour.com/wp-content/uploads/2026/03/filtering-network-panel-2048x960.png 2048w" sizes="(max-width: 2542px) 100vw, 2542px" /></figure>



<p class="wp-block-paragraph">Cookies can be set by HTTP Headers or JavaScript. HTTP Headers are easier to look for, so I always start there. In the network panel, I look at the response headers for each asset that comes from the suspect domain. The response headers are the headers sent by back the server when the browser requested the asset. The server can ask the browser to create cookies using <code>Set-Cookie</code> headers. There can be more than one <code>Set-Cookie</code> header for a given asset. </p>



<figure class="wp-block-image size-full"><img width="2538" height="1182" src="https://cloudfour.com/wp-content/uploads/2026/03/response-header-setting-cookie.png" alt="" class="wp-image-8504" srcset="https://cloudfour.com/wp-content/uploads/2026/03/response-header-setting-cookie.png 2538w, https://cloudfour.com/wp-content/uploads/2026/03/response-header-setting-cookie-300x140.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/response-header-setting-cookie-1024x477.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/response-header-setting-cookie-768x358.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/response-header-setting-cookie-1536x715.png 1536w, https://cloudfour.com/wp-content/uploads/2026/03/response-header-setting-cookie-2048x954.png 2048w" sizes="(max-width: 2538px) 100vw, 2538px" /></figure>



<p class="wp-block-paragraph">If the cookie isn&#8217;t set using HTTP Headers, it can be more difficult to isolate which bit of JavaScript is setting the cookie. I often use <a href="https://developer.chrome.com/docs/devtools/request-conditions">request blocking</a> in the network panel as a blunt tool to isolate which script sets the cookies.</p>



<figure class="wp-block-image size-full"><img width="2546" height="1536" src="https://cloudfour.com/wp-content/uploads/2026/03/blocking-a-request.png" alt="" class="wp-image-8505" srcset="https://cloudfour.com/wp-content/uploads/2026/03/blocking-a-request.png 2546w, https://cloudfour.com/wp-content/uploads/2026/03/blocking-a-request-300x181.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/blocking-a-request-1024x618.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/blocking-a-request-768x463.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/blocking-a-request-1536x927.png 1536w, https://cloudfour.com/wp-content/uploads/2026/03/blocking-a-request-2048x1236.png 2048w" sizes="(max-width: 2546px) 100vw, 2546px" /><figcaption class="wp-element-caption">Right-clicking on an asset in the network panel will provide an option to Block Requests. You can block them by URL or by domain.</figcaption></figure>



<figure class="wp-block-image size-full"><img width="2560" height="1517" src="https://cloudfour.com/wp-content/uploads/2026/03/blocking-and-throttling-panel-scaled.png" alt="" class="wp-image-8507" srcset="https://cloudfour.com/wp-content/uploads/2026/03/blocking-and-throttling-panel-scaled.png 2560w, https://cloudfour.com/wp-content/uploads/2026/03/blocking-and-throttling-panel-300x178.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/blocking-and-throttling-panel-1024x607.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/blocking-and-throttling-panel-768x455.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/blocking-and-throttling-panel-1536x910.png 1536w, https://cloudfour.com/wp-content/uploads/2026/03/blocking-and-throttling-panel-2048x1214.png 2048w" sizes="(max-width: 2560px) 100vw, 2560px" /><figcaption class="wp-element-caption">After you choose to block a request, the Request Conditions drawer will open. This is where you can turn on and off request blocking and throttling. You can also edit the regular expressions and fine-tune what assets are blocked.</figcaption></figure>



<p class="wp-block-paragraph">First, I&#8217;ll block the entire request domain, clear all cookies, and then check to see if the cookie is still getting set. If it is, I&#8217;m looking at the wrong source. If the cookie is no longer being set, I now know that one of the assets I blocked is responsible.</p>



<p class="wp-block-paragraph">Often I&#8217;m able to make an educated guess about which asset is likely to set the cookie based on the description of the cookie and the asset names. If I have a hunch, I&#8217;ll try blocking that asset alone and see if the cookie is still set.</p>



<p class="wp-block-paragraph">If I don&#8217;t have a guess or I guessed wrong, I&#8217;ll narrow it down by blocking half the requests from the suspect domain to see if that blocks the cookie. If it does, I know where to continue looking. If not, the cookie must be set in the other half. Repeat this a few more times and you can quickly winnow down even a long list of assets.</p>



<h2 class="wp-block-heading">Cookies blocked by the browser</h2>



<p class="wp-block-paragraph">Cookies that were blocked by the browser may still show up in cookie list to help with troubleshooting. Their row will be distinguished in a different color and if you hover over the associated request, you will see information about why the cookie was rejected.</p>



<figure class="wp-block-image size-full"><img width="2424" height="548" src="https://cloudfour.com/wp-content/uploads/2026/03/twitter-blocked-cookie.png" alt="" class="wp-image-8508" srcset="https://cloudfour.com/wp-content/uploads/2026/03/twitter-blocked-cookie.png 2424w, https://cloudfour.com/wp-content/uploads/2026/03/twitter-blocked-cookie-300x68.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/twitter-blocked-cookie-1024x231.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/twitter-blocked-cookie-768x174.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/twitter-blocked-cookie-1536x347.png 1536w, https://cloudfour.com/wp-content/uploads/2026/03/twitter-blocked-cookie-2048x463.png 2048w" sizes="(max-width: 2424px) 100vw, 2424px" /><figcaption class="wp-element-caption">In this screenshot, there are three cookies highlighted with a slightly different shade of brown. If you hover over the information icons in each row, you&#8217;ll see why the cookie was blocked. In this case, the twitter.com cookie was blocked because it didn&#8217;t specify a SameSite attribute which is required for a cross-origin cookie.</figcaption></figure>



<h2 class="wp-block-heading">Testing using a headless browser</h2>



<p class="wp-block-paragraph">Manual testing can only get you so far. I had to audit hundreds of cookies for a client, so I looked for ways to automate the process. I couldn&#8217;t find anything that did exactly what I needed so with Claude Code&#8217;s help, I wrote a command line tool that used <a href="https://pptr.dev/">Puppeteer</a> to see which cookies were set before and after consent was granted.</p>



<p class="wp-block-paragraph">Puppeteer helped me find cookies that my manual testing had missed. Every time Puppeteer launches, it has a clean slate. Therefore, any cookies that my script finds must have been set by the test page. This helped capture third-party cookies that were only showing up on the first page load. </p>



<p class="wp-block-paragraph">I also added logic to intercept cookies being set to create my own version of the the initiator chain. Eventually, I expanded the tests to look for local storage, session storage, and IndexDB. Puppeteer also scrolls the page to make sure it captures any lazy loading cookies.</p>



<p class="wp-block-paragraph">If you need to do any significant amount of testing, I recommend using Puppeteer, or its alternative <a href="https://playwright.dev/">Playwright</a>, so you have a clean testing environment and can automate the process.</p>



<h2 class="wp-block-heading">Cookie consent can be fun?</h2>



<p class="wp-block-paragraph">When our clients first asked for help with their cookie consent management, I wasn&#8217;t looking forward to it. I like designing and building solutions for users not dealing with legal requirements. Plus, cookie consent banners are annoying.</p>



<p class="wp-block-paragraph">But by the end of these projects, I found myself enjoying the work. The cookie consent tools do a good job of recognizing most cookies, but there are always a few mysteries in the box. I love a good mystery. And sometimes you find truly surprising things like a site manifest file setting multiple cookies.</p>



<p class="wp-block-paragraph">Plus, there is satisfaction in knowing that people will have their privacy preferences honored. Not to mention the fact that we&#8217;re able to significantly reduce the legal risk for our customers.</p>



<p class="wp-block-paragraph">Cookie consent management can seem daunting at first, but it is important for your organization and its users. And maybe I&#8217;m just a sicko, but I found it to be a lot of fun.</p>

<hr>
<h2>We’re Cloud Four</h2>
<p>We solve complex responsive web design and development challenges for ecommerce, healthcare, fashion, B2B, SaaS, and nonprofit organizations.</p>

<p><a href="https://cloudfour.com/made/"><b>See our work</b></a></p>]]></content:encoded>
					
					<wfw:commentRss>https://cloudfour.com/thinks/cookie-consent-management-in-2026-part-2-technical-tips/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">8509</post-id><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-2.png" width="550" height="309" medium="image" /><enclosure url="https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-2.png" length="0" type="image/png" />	</item>
		<item>
		<title>Cookie Consent Management in 2026, Part 1: Overview</title>
		<link>https://cloudfour.com/thinks/cookie-consent-management-in-2026-part-1-overview/</link>
					<comments>https://cloudfour.com/thinks/cookie-consent-management-in-2026-part-1-overview/#respond</comments>
		
		<dc:creator><![CDATA[Jason Grigsby]]></dc:creator>
		<pubDate>Wed, 18 Mar 2026 18:31:50 +0000</pubDate>
				<category><![CDATA[Essentials]]></category>
		<category><![CDATA[Privacy]]></category>
		<category><![CDATA[featured/articles]]></category>
		<category><![CDATA[featured/home]]></category>
		<guid isPermaLink="false">https://cloudfour.com/?p=8494</guid>

					<description><![CDATA[The threat of lawsuits has companies scrambling to get their cookie compliance house in order. Here are some of the things we've learned as we've helped our clients.]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img width="1600" height="900" src="https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-1.png" alt="" class="wp-image-8510" srcset="https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-1.png 1600w, https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-1-300x169.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-1-1024x576.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-1-768x432.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-1-1536x864.png 1536w" sizes="(max-width: 1600px) 100vw, 1600px" /></figure>



<p class="wp-block-paragraph">I&#8217;ve noticed a trend. Over the last few months, multiple customers have asked us to help with cookie consent compliance. Either it is a mighty coincidence or something has caused companies to start taking privacy compliance more seriously.</p>



<p class="wp-block-paragraph">I think the renewed interest is because ambitious lawyers have started sending <a href="https://www.pierceatwood.com/alerts/pre-suit-privacy-and-consumer-law-demand-letters-surge-2025-how-businesses-can-stay-ahead#:~:text=Plaintiffs'%20firms%20are%20testing%20decades,early%20pre%2Dlitigation%20demand%20stages." data-type="link" data-id="https://www.pierceatwood.com/alerts/pre-suit-privacy-and-consumer-law-demand-letters-surge-2025-how-businesses-can-stay-ahead#:~:text=Plaintiffs'%20firms%20are%20testing%20decades,early%20pre%2Dlitigation%20demand%20stages.">threatening letters</a> to companies that aren&#8217;t in compliance with the California Consumer Privacy Act (CCPA) and the EU&#8217;s General Data Protection Regulation (GDPR) provisions. I know of at least one company with over $100k in related legal fees.</p>



<p class="wp-block-paragraph">Last month, California won a <a href="https://iapp.org/news/a/california-s-attorney-general-issues-largest-ccpa-fine-to-date">$2.75M settlement with Disney </a>over CCPA violations. CCPA fines can add up quickly. They start at $2,663 per incident. The fines increases to $7,988 per incident for willful violations or violations involving people under 16.</p>



<p class="wp-block-paragraph">It&#8217;s not limited to CCPA and GPDR. Enterprising lawyers have dusted off the 1967 California Invasion of Privacy Act (CIPA) and applied it to web technology. The law firm Varnum <a href="https://www.varnumlaw.com/insights/the-rise-of-cipa-website-tracking-claims/">explains</a>:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Plaintiffs’ attorneys are using CIPA to challenge common website technologies, including cookies, analytics tools, session replay software, and chat features. Many companies are caught off guard when they receive a demand letter alleging unlawful website tracking, followed by the threat of litigation.</p>



<p class="wp-block-paragraph">Thousands of CIPA website tracking claims have been asserted, and filings continue to rise.</p>
</blockquote>



<p class="wp-block-paragraph">So it&#8217;s not surprising that companies are trying to get their cookie house in order. I may be a glutton for punishment, but I&#8217;ve enjoyed working on these cookie consent projects, and thought I&#8217;d share some of the things I&#8217;ve learned. In part one, I&#8217;ll share some high-level thoughts. In <a href="https://cloudfour.com/thinks/cookie-consent-management-in-2026-part-2-technical-tips/" data-type="link" data-id="https://cloudfour.com/thinks/cookie-consent-management-in-2026-part-2-technical-tips/">part 2</a>, I&#8217;ll dig into some technical details.</p>



<h2 class="wp-block-heading">Organizational resistance</h2>



<p class="wp-block-paragraph">When an organization implements cookie consent management for the first time, the impact on their analytics and marketing initiatives can be dramatic. If people can opt out of being tracked, a significant percentage will choose to do so. If your marketing relies on tracking, it will suffer.</p>



<p class="wp-block-paragraph">I know of an organization that backtracked on cookie compliance because of the impact on marketing. Doing so creates legal exposure, but it&#8217;s understandable how a company that sees their sales drop might panic.</p>



<p class="wp-block-paragraph">So my first piece of advice is to talk to marketing ahead of time to understand what tools are being used. Determine which are most likely to be impacted by cookie banners, and see what you can do to mitigate them. Sign up now for a GPDR-compliant, cookie-less analytics service like <a href="https://plausible.io/" data-type="link" data-id="https://plausible.io/">Plausible</a> or <a href="https://umami.is/" data-type="link" data-id="https://umami.is/">Umami</a> so you have a baseline of analytics information. You can use these services track trends before and after you implement a consent banner.</p>



<p class="wp-block-paragraph">Unfortunately, in a lot situations, there isn&#8217;t much you can do to alleviate the data loss. If someone doesn&#8217;t want to be tracked and your marketing tools depend on tracking data, then the tools are going to be less effective. But helping your marketing colleagues anticipate where cookie consent will impact them will not only help mitigate data loss, but it will also prepare the team for their new reality.</p>



<h2 class="wp-block-heading">Hire a good lawyer</h2>



<p class="wp-block-paragraph">I&#8217;m not a lawyer. If you&#8217;re reading this, you&#8217;re probably not either. You need knowledgable legal counsel to help you decide how cookies should be categorized. Only a lawyer can help an organization make sure they are in compliance and understand the risks of various choices.</p>



<p class="wp-block-paragraph">Plus, if you&#8217;re the person leading the privacy charge, then the people are going to resist you. Instead, if a lawyer tells your organization what they need to do, then you don&#8217;t have to argue with co-workers about whether their favorite service&#8217;s cookies should be defined as essential or not. You get to be the hero helping the organization while the lawyer plays the bad cop.</p>



<h2 class="wp-block-heading">Find a good cookie consent solution</h2>



<p class="wp-block-paragraph">I find cookie consent banners annoying. As a user, I didn&#8217;t care what solution a website used so long as I could dismiss it quickly.</p>



<p class="wp-block-paragraph">But after working with a few different cookie consent solutions for our clients, I now have a list of features I consider critical:</p>



<ul class="wp-block-list">
<li><strong>GPDR compliant</strong>: You may only care about CCPA right now, but CCPA is evolving towards GPDR. In fact, even though one of our clients is based in California and doesn&#8217;t sell in Europe, their lawyers advised them to use a GPDR-style cookie consent banner where you can select specific categories of cookies instead of a CCPA-compliant one where you either accept or reject cookies.</li>



<li><strong>Regular scanning of your site: </strong>What cookies are being used on your site may change over time without you knowing about it either because a new third-party service is added to the site or an existing one adds a new cookie. You need regular scans to tell you if a cookie has been discovered so you can categorize it.</li>



<li><strong>Identifies local storage, session storage, and IndexDB in addition to cookies</strong>: Even though everyone talks about cookies, the privacy laws don&#8217;t care what technical mechanism is used to track people. You need a tool that looks at all of the ways people can be tracked.</li>



<li><strong>Intuitive web-based reports</strong>: We&#8217;ve worked with one cookie consent manager where account managers send periodic spreadsheets that appear to be manually generated. By contrast, my favorite provider has an easy-to-use web report that shows what cookies their scans have discovered and how to take action on them.</li>



<li><strong>A solution that is lightweight and fast</strong>:&nbsp;Cookie consent banners have to load early on the page and block other scripts. Therefore, any performance issues they have are magnified.</li>
</ul>



<p class="wp-block-paragraph">On that last point, I asked the web performance Slack community if anyone had recommendations for a performant cookie solution. The kind folks at <a href="https://www.rumvision.com/">RUMVision</a> shared data from across their customer base:</p>



<figure class="wp-block-image size-full"><a href="https://cloudfour.com/wp-content/uploads/2026/03/cookie-consent-js-execution.png"><img width="2241" height="751" src="https://cloudfour.com/wp-content/uploads/2026/03/cookie-consent-js-execution.png" alt="Low impact cookie consent managers include: CookieLaw.org, CookieYes.com, OneTrust.com, Cookiecode.nl, Usercentrics.eu, and PrivacyManager.io." class="wp-image-8495" srcset="https://cloudfour.com/wp-content/uploads/2026/03/cookie-consent-js-execution.png 2241w, https://cloudfour.com/wp-content/uploads/2026/03/cookie-consent-js-execution-300x101.png 300w, https://cloudfour.com/wp-content/uploads/2026/03/cookie-consent-js-execution-1024x343.png 1024w, https://cloudfour.com/wp-content/uploads/2026/03/cookie-consent-js-execution-768x257.png 768w, https://cloudfour.com/wp-content/uploads/2026/03/cookie-consent-js-execution-1536x515.png 1536w, https://cloudfour.com/wp-content/uploads/2026/03/cookie-consent-js-execution-2048x686.png 2048w" sizes="(max-width: 2241px) 100vw, 2241px" /></a></figure>



<p class="wp-block-paragraph">Because I have a performance hammer and everything is a nail, I started my explorations with <a href="https://www.cookieyes.com/partner-offer/?ref=yzqynjn">CookieYes</a> (That&#8217;s an affiliate link. If you sign up, we get a <em>tiny</em> kickback.) It is almost twice as fast as the nearest competitor in the RumVision data.</p>



<p class="wp-block-paragraph">I&#8217;ve been quite happy with CookieYes. It is reasonably priced. The administrative dashboard is easy to work with. The scans surface cookies we need to address. Most importantly, their support has been fast and knowledgeable.</p>



<h2 class="wp-block-heading">Monitor your compliance</h2>



<p class="wp-block-paragraph">Complying with privacy laws requires some form of ongoing vigilance. Unless you are not using any third-party services, the cookies being used on your site may change without your knowledge. Therefore, you need regular scans and people who are responsible for addressing any new issues that arise.</p>



<p class="wp-block-paragraph">In larger organizations, you have to keep an eye out for other teams creating new websites. These websites need to be integrated with your main cookie consent solution. If someone opts out on one of your websites, their decision should carry over to others. This may require all company websites to use subdomains so cookie consent decisions can be more easily shared between them.</p>



<p class="wp-block-paragraph">The privacy laws themselves change. As of January this year, CCPA not only requires websites to honor a user&#8217;s <a href="https://globalprivacycontrol.org/">Global Privacy Control (GPC) setting</a>, but also <a href="https://www.clym.io/blog/ccpa-selling-and-sharing-what-counts-as-a-sale-or-share">explicitly notify them</a> that it has been honored.</p>



<p class="wp-block-paragraph">The good news is that while you do need to monitor cookies and privacy laws to make sure you remain in compliance, the ongoing work is minimal once you tackle the initial audit, categorization, and implementation of a cookie consent banner.</p>



<p class="wp-block-paragraph">In <a href="https://cloudfour.com/thinks/cookie-consent-management-in-2026-part-2-technical-tips/">part 2</a> of this series, I&#8217;ll share some technical tips and tricks I learned for identifying the source of cookies.</p>

<hr>
<h2>We’re Cloud Four</h2>
<p>We solve complex responsive web design and development challenges for ecommerce, healthcare, fashion, B2B, SaaS, and nonprofit organizations.</p>

<p><a href="https://cloudfour.com/made/"><b>See our work</b></a></p>]]></content:encoded>
					
					<wfw:commentRss>https://cloudfour.com/thinks/cookie-consent-management-in-2026-part-1-overview/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">8494</post-id><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-1.png" width="550" height="309" medium="image" /><enclosure url="https://cloudfour.com/wp-content/uploads/2026/03/cookie-2026-feature-part-1.png" length="0" type="image/png" />	</item>
		<item>
		<title>Little Dummies: Simple FPO Content Helpers</title>
		<link>https://cloudfour.com/thinks/little-dummies-simple-fpo-content-helpers/</link>
					<comments>https://cloudfour.com/thinks/little-dummies-simple-fpo-content-helpers/#respond</comments>
		
		<dc:creator><![CDATA[Tyler Sticka]]></dc:creator>
		<pubDate>Thu, 12 Mar 2026 21:26:26 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Process]]></category>
		<category><![CDATA[Responsive Web Design]]></category>
		<category><![CDATA[SVG]]></category>
		<category><![CDATA[Tools]]></category>
		<guid isPermaLink="false">https://cloudfour.com/?p=8497</guid>

					<description><![CDATA[Video, links and code samples from my rapid prototyping talk for the final Eleventy Meetup.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I was delighted to present this talk at the final (for now) episode of <a href="https://11tymeetup.dev">The Eleventy Meetup</a>:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><s>Eleventy</s> <a href="https://www.11ty.dev/blog/build-awesome/">Build Awesome</a> is great for rapid prototyping! Tyler shows off a few of his favorite shortcodes, filters and other techniques to quickly populate interactive mockups and wireframes with “dummy” or FPO (for placement only) content.</p>
</blockquote>



<p class="wp-block-paragraph">You can watch the presentation here:</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Little Dummies: Simple FPO Content Helpers with Tyler Sticka | 11ty Meetup" width="500" height="281" src="https://www.youtube.com/embed/NHgiKb8XfU0?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<h2 class="wp-block-heading">Example Helpers</h2>



<p class="wp-block-paragraph">These are the main code samples from my slides, consolidated below for easy reference.</p>



<p class="wp-block-paragraph">Each helper is written in ESM syntax (but should work in CommonJS with <a href="https://www.11ty.dev/docs/cjs-esm/#common-js-configuration">a few small changes</a>), and each assumes it lives in its own file (imported by <a href="https://www.11ty.dev/docs/config/">the config</a>).</p>



<h3 class="wp-block-heading">Text, Numbers, etc.</h3>



<p class="wp-block-paragraph">With the <a href="https://chancejs.com/">Chance</a> dependency:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">import</span> Chance <span class="hljs-keyword">from</span> <span class="hljs-string">"chance"</span>;
<span class="hljs-keyword">let</span> chance;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">method, ...args</span>) </span>{
  <span class="hljs-comment">// Support JSON string for first argument</span>
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> args&#91;<span class="hljs-number">0</span>] === <span class="hljs-string">"string"</span>) {
    args&#91;<span class="hljs-number">0</span>] = <span class="hljs-built_in">JSON</span>.parse(args&#91;<span class="hljs-number">0</span>]);
  }

  <span class="hljs-comment">// Instantiate Chance the first time</span>
  <span class="hljs-keyword">if</span> (!chance) {
    chance = <span class="hljs-keyword">new</span> Chance();
  }

  <span class="hljs-comment">// If the method exists, return its output</span>
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> chance&#91;method] === <span class="hljs-string">"function"</span>) {
    <span class="hljs-keyword">return</span> chance&#91;method](...args);
  }

  <span class="hljs-comment">// Otherwise, log an error but proceed</span>
  <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`&#91;chance] No method named <span class="hljs-subst">${methodName}</span>`</span>);
  <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>;
}</code></span></pre>


<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>Eleventy Config Example</summary><pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">import</span> chanceHelper <span class="hljs-keyword">from</span> <span class="hljs-string">"./helpers/chance.js"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">eleventyConfig</span>) </span>{
  eleventyConfig.addShortcode(<span class="hljs-string">"chance"</span>, chanceHelper);
  eleventyConfig.addFilter(<span class="hljs-string">"chance"</span>, chanceHelper);
}</code></span></pre></details>



<h3 class="wp-block-heading">Images</h3>



<p class="wp-block-paragraph">With our <a href="https://cloudfour.com/thinks/simple-svg-placeholder/">Simple SVG Placeholder</a> dependency:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">import</span> simpleSvgPlaceholder <span class="hljs-keyword">from</span> <span class="hljs-string">"@cloudfour/simple-svg-placeholder"</span>;

<span class="hljs-comment">/**
 * Modify these to suit the project!
 * @see https://github.com/cloudfour/simple-svg-placeholder#option-reference
 */</span>
<span class="hljs-keyword">const</span> defaults = {
  <span class="hljs-attr">bgColor</span>: <span class="hljs-string">"rgb(0 0 0 / 0.8)"</span>,
  <span class="hljs-attr">textColor</span>: <span class="hljs-string">"white"</span>,
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">width, height, options = {}</span>) </span>{
  <span class="hljs-comment">// Support JSON string for argument</span>
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> options === <span class="hljs-string">"string"</span>) {
    options = <span class="hljs-built_in">JSON</span>.parse(options);
  }

  <span class="hljs-keyword">return</span> simpleSvgPlaceholder({...defaults, width, height, ...options});
}</code></span></pre>


<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>Eleventy Config Example</summary><pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">import</span> fpoImageHelper <span class="hljs-keyword">from</span> <span class="hljs-string">"./helpers/fpo-image.js"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">eleventyConfig</span>) </span>{
  eleventyConfig.addShortcode(<span class="hljs-string">"fpoImage"</span>, fpoImageHelper);
}</code></span></pre></details>



<h3 class="wp-block-heading">Icons</h3>



<p class="wp-block-paragraph">This example uses <a href="https://iconify.design/docs/api/">the Iconify API</a> via <a href="https://www.11ty.dev/docs/plugins/fetch/">Eleventy Fetch</a>.</p>



<p class="wp-block-paragraph">I&#8217;ve made a small enhancement since the presentation, adding <a href="https://github.com/fb55/entities">the entities package</a> to escape attribute values on the inline SVG based on a recommendation from Zach Leatherman:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">import</span> EleventyFetch <span class="hljs-keyword">from</span> <span class="hljs-string">"@11ty/eleventy-fetch"</span>;
<span class="hljs-keyword">import</span> { escapeAttribute } <span class="hljs-keyword">from</span> <span class="hljs-string">"entities/escape"</span>;

<span class="hljs-keyword">const</span> apiUrl = <span class="hljs-string">"https://api.iconify.design"</span>;

<span class="hljs-keyword">const</span> fetchOptions = {
  <span class="hljs-attr">duration</span>: <span class="hljs-string">"1y"</span>,
  <span class="hljs-attr">type</span>: <span class="hljs-string">"json"</span>,
};

<span class="hljs-keyword">const</span> defaultAttr = {
  <span class="hljs-attr">xmlns</span>: <span class="hljs-string">"http://www.w3.org/2000/svg"</span>,
  <span class="hljs-attr">class</span>: <span class="hljs-string">"icon"</span>,
};

<span class="hljs-comment">// Get a specific set:name icon string</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getSpecificIcon</span>(<span class="hljs-params">icon</span>) </span>{
  <span class="hljs-comment">// If already specific, do nothing</span>
  <span class="hljs-keyword">if</span> (icon.includes(<span class="hljs-string">":"</span>)) {
    <span class="hljs-keyword">return</span> icon;
  }

  <span class="hljs-keyword">const</span> searchUrl = <span class="hljs-string">`<span class="hljs-subst">${apiUrl}</span>/search?query=<span class="hljs-subst">${icon}</span>&amp;limit=1`</span>;
  <span class="hljs-keyword">const</span> searchData = <span class="hljs-keyword">await</span> EleventyFetch(searchUrl, fetchOptions);
  <span class="hljs-keyword">const</span> results = searchData.icons || &#91;];

  <span class="hljs-keyword">if</span> (results.length === <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`No icon found for <span class="hljs-subst">${icon}</span>`</span>);
  }

  <span class="hljs-keyword">return</span> results&#91;<span class="hljs-number">0</span>];
}

<span class="hljs-comment">// { class: "icon", width: 120 }</span>
<span class="hljs-comment">// =&gt; 'class="icon" width="120"'</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">objectToAttributeString</span>(<span class="hljs-params">obj</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.entries(obj)
    .map(<span class="hljs-function">(<span class="hljs-params">&#91;key, value]</span>) =&gt;</span> {
      value = escapeAttribute(<span class="hljs-string">`<span class="hljs-subst">${value}</span>`</span>);
      <span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="hljs-subst">${key}</span>="<span class="hljs-subst">${value}</span>"`</span>;
    })
    .join(<span class="hljs-string">" "</span>);
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">icon, attr = {}</span>) </span>{
  <span class="hljs-comment">// Support JSON strings for attributes</span>
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> attr === <span class="hljs-string">"string"</span>) {
    attr = <span class="hljs-built_in">JSON</span>.parse(attr);
  }

  <span class="hljs-keyword">try</span> {
    icon = <span class="hljs-keyword">await</span> getSpecificIcon(icon);
    <span class="hljs-keyword">const</span> &#91;setName, iconName] = icon.split(<span class="hljs-string">":"</span>);
    <span class="hljs-keyword">const</span> iconDataUrl = <span class="hljs-string">`<span class="hljs-subst">${apiUrl}</span>/<span class="hljs-subst">${setName}</span>.json?icons=<span class="hljs-subst">${iconName}</span>`</span>;
    <span class="hljs-keyword">const</span> iconData = <span class="hljs-keyword">await</span> EleventyFetch(iconDataUrl, fetchOptions);

    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> iconData !== <span class="hljs-string">"object"</span>) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`Request for <span class="hljs-subst">${icon}</span> returned <span class="hljs-subst">${iconData}</span>`</span>);
    }

    <span class="hljs-keyword">const</span> { width, height } = iconData;
    <span class="hljs-keyword">const</span> { body } = iconData.icons&#91;iconName];
    <span class="hljs-keyword">const</span> attrString = objectToAttributeString({
      ...defaultAttr,
      <span class="hljs-string">"data-icon"</span>: icon,
      <span class="hljs-attr">viewBox</span>: <span class="hljs-string">`0 0 <span class="hljs-subst">${width}</span> <span class="hljs-subst">${height}</span>`</span>,
      width,
      height,
      ...attr
    });

    <span class="hljs-keyword">return</span> <span class="hljs-string">`&lt;svg <span class="hljs-subst">${attrString}</span>&gt;<span class="hljs-subst">${body}</span>&lt;/svg&gt;`</span>;
  } <span class="hljs-keyword">catch</span>(err) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`&#91;iconify] <span class="hljs-subst">${err.message}</span>`</span>);
    <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>;
  }
}</code></span></pre>


<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>Eleventy Config Example</summary><pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">import</span> iconifyHelper <span class="hljs-keyword">from</span> <span class="hljs-string">"./helpers/iconify.js"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">eleventyConfig</span>) </span>{
  eleventyConfig.addShortcode(<span class="hljs-string">"iconify"</span>, iconifyHelper);
}</code></span></pre></details>



<h2 class="wp-block-heading">Resources</h2>



<p class="wp-block-paragraph">More references from the talk (other than dependencies in the previous section):</p>



<ul class="wp-block-list">
<li>For more about Cloud Four&#8217;s process, check out <a href="https://cloudfour.com/thinks/responsive-design-process-that-works/">Responsive Design Process That Works</a> and <a href="https://cloudfour.com/made/imagequix/">one of our case studies</a></li>



<li><a href="https://cloudfour.com/thinks/why-i-like-designing-in-the-browser/">Why I Like Designing in the Browser</a> and <a href="https://cloudfour.com/thinks/designing-in-the-browser-five-tips-for-beginners/">five tips for beginners</a></li>



<li>Build Awesome provides helpful docs for <a href="https://www.11ty.dev/docs/shortcodes/">Shortcodes</a> and <a href="https://www.11ty.dev/docs/filters/">Filters</a></li>



<li>If you already have an icon library, check out <a href="https://github.com/uncenter/eleventy-plugin-icons">uncenter&#8217;s awesome plugin</a></li>



<li><a href="https://danross.co/flow/">Flow</a> and <a href="https://github.com/christiannaths/redacted-font">Redacted</a> are fonts intended for stubbing out text sections in wireframes</li>



<li>Performance chart from <a href="https://almanac.httparchive.org/en/2025/page-weight">the Page Weight section of the 2025 Web Almanac</a></li>



<li>Accessibility chart from <a href="https://webaim.org/projects/million/#wcag">The WebAIM Million&#8217;s WCAG Conformance section</a></li>



<li><a href="https://xkcd.com/3175/">XKCD&#8217;s Website Task Flowchart cartoon</a></li>
</ul>



<h2 class="wp-block-heading">Some Questions Answered</h2>



<p class="wp-block-paragraph">Two questions stood out to me during a live Q&amp;A following my presentation:</p>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>Do you only prototype in Eleventy / Build Awesome?</summary>
<p class="wp-block-paragraph">No! Sometimes the teams we work with already have an environment with <a href="https://cloudfour.com/thinks/encouraging-play-in-design-systems/">a suitable playground</a>, or a different stack they&#8217;re more familiar with. But Build Awesome is a great fallback due to its stability, performance, flexibility and <a href="https://cloudfour.com/thinks/tiny-web-stacks/">small footprint</a>.</p>
</details>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>Do you share these sorts of helpers between projects? </summary>
<p class="wp-block-paragraph">We start from a private, opinionated <a href="https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository">template repository</a>, which we tailor to the project&#8217;s needs. After a major milestone, we&#8217;ll see if anything we diverged on deserves to be added back to the template repo to benefit future projects. This allows us to easily adapt the helpers to the needs of the project without sweating breaking changes.</p>
</details>



<h2 class="wp-block-heading">Acknowledgements</h2>



<p class="wp-block-paragraph">Big thanks to <a href="https://sia.codes">Sia Karamalegos</a> for having me, <a href="https://www.zachleat.com">Zach Leatherman</a> for creating Build Awesome (<a href="https://www.kickstarter.com/projects/fontawesome/build-awesome-pro">new Kickstarter launching soon</a>) and encouraging my unique possum interpretations, and especially everyone who attended the meetup!</p>



<p class="wp-block-paragraph">If you want to see Cloud Four&#8217;s process in action, <a href="https://cloudfour.com/and-you/">get in touch</a>! We&#8217;re always looking for our next web app design challenge.</p>

<hr>
<h2>We’re Cloud Four</h2>
<p>We solve complex responsive web design and development challenges for ecommerce, healthcare, fashion, B2B, SaaS, and nonprofit organizations.</p>

<p><a href="https://cloudfour.com/made/"><b>See our work</b></a></p>]]></content:encoded>
					
					<wfw:commentRss>https://cloudfour.com/thinks/little-dummies-simple-fpo-content-helpers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">8497</post-id><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://cloudfour.com/wp-content/uploads/2026/03/11ty-dummies-post-feature-r1.jpg" width="550" height="309" medium="image" /><enclosure url="https://cloudfour.com/wp-content/uploads/2026/03/11ty-dummies-post-feature-r1.jpg" length="0" type="image/jpg" />	</item>
	</channel>
</rss>
