<rss>
  <channel>
    <title>Deane Barker's Technical Blog</title>
    <description>A blog about technical issues maintained from 2005-2019. Formerly called "Gadgetopia."</description>
    <link>https://live.deanebarker.net/tech/blog/</link>
    <item>
      <title>AI and the Forced Platform-ization of Enterprise Software</title>
      <link>https://live.deanebarker.net/tech/blog/platformization/</link>
      <description>&lt;p&gt;I&amp;rsquo;ve become interested in the last few years in the &amp;ldquo;layers&amp;rdquo; in which we build, customize, and integrate software. More pointedly, I&amp;rsquo;m fascinated at how the era AI and &amp;ldquo;vibe-coding&amp;rdquo; is going to completely upend them over the next decade. The current &amp;ldquo;us vs. them&amp;rdquo; perspective of software development is never going to be the same.&lt;/p&gt;
&lt;p&gt;Back to layers &amp;ndash; at the bare minimum, there are two:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Vendor:&lt;/strong&gt; the organization that produces the software&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User:&lt;/strong&gt; the organization that uses the software&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The vendor clearly builds the software and makes all sorts of choices. But the user makes choices too, in how they&amp;rsquo;ll configure it, what settings they will use, and the common knowledge they&amp;rsquo;ll share about how that software works at their organizations.&lt;/p&gt;
&lt;p&gt;Customers &amp;ldquo;adapt&amp;rdquo; software (or &amp;ldquo;re-invent&amp;rdquo; it, according to &lt;em&gt;&lt;a href="/library/titles/diffusion-innovations/" data-no-index&gt;Diffusion of Innovations&lt;/a&gt;&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Many times, with enterprise software especially, there&amp;rsquo;s a middle level:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Vendor&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integrator/Partner:&lt;/strong&gt; the organization that oversees the installation, activation, and configuration of the software&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The integrator has special knowledge of the software. They can use some special tools or skills &amp;ndash; like the ability to write code against the vendor&amp;rsquo;s APIs &amp;ndash; to make the software do special things for the user.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;See an article I wrote for Staffbase: &lt;a href="https://staffbase.com/blog/integration-patterns"&gt;Integration patterns: How we connect software&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Most software actually consists of at least four layers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &amp;ldquo;core&amp;rdquo; that the vendor builds and that no one can touch&lt;/li&gt;
&lt;li&gt;Some special tools and APIs which can be used to make the software work differently&lt;/li&gt;
&lt;li&gt;Settings and configuration on a per-instance basis &amp;ndash; so, things global to an organization&lt;/li&gt;
&lt;li&gt;Settings and configuration on a per-user basis &amp;ndash; so, things specific to a human&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And we could go on and on. There are so many different ways to peel this onion.&lt;/p&gt;
&lt;p&gt;At &lt;a href="https://optimizely.com/"&gt;Episerver/Optimizely&lt;/a&gt;, I came up with this graphic. This was internal (and it&amp;rsquo;s about five-years-old now), but I&amp;rsquo;ve shown it to so many people by this point that I&amp;rsquo;ll just publish it here:&lt;/p&gt;








&lt;img src="/tech/blog/images/platformization/bullseye.jpg" loading="lazy" class="center allow-magnify" data-part="image" data-value="/tech/blog/images/platformization/bullseye.jpg" /&gt;



&lt;p&gt;The point I was trying to make was that code and functionality &amp;ldquo;leaks&amp;rdquo; out of a software vendor at so many different levels. The actual resulting software that&amp;rsquo;s perceived by any given user is a roll-up of everything in that list. They may think that the core software (#1) does all the things they experience, without knowing that their accumulated experience is an aggregation of 11 different layers, all homogenized (with varying degrees of success) to look like a single thing.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;From 17 years ago: &lt;a href="/tech/blog/platforms-implementation-confusion/" data-no-index&gt;How Sales Prospects View CMS Platforms vs CMS Implementations&lt;/a&gt;. I had discussed four levels back then.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;This is sort of a re-hash of the &amp;ldquo;product vs. platform&amp;rdquo; debate.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;product&lt;/strong&gt; is a thing designed to be used one way. It promises very fast implementation and low cognitive overhead, but isn&amp;rsquo;t very flexible and is not designed to be.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;platform&lt;/strong&gt; is a thing designed to be adapted and built upon. It&amp;rsquo;s flexible and powerful, but often needs to be implemented carefully and requires considerable thought about all the things you can do with it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I maintain that one of the key decisions of every product company is: are you a product or a platform? Where along that spectrum do you lie? And if you don&amp;rsquo;t do something exactly how a customer or prospect wants, do you just admit that, or do you provide some tools or options to change it?&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;From 14 years ago: &lt;a href="/tech/blog/checking-the-box/" data-no-index&gt;Checking the Box: How CMS Feature Support Is Not a Binary Question&lt;/a&gt;. I provided eight gradients there.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;So, what does this have to do with AI? People have been modifying software for years &amp;ndash; hell, I made a living doing it for a long time.&lt;/p&gt;
&lt;p&gt;…but it&amp;rsquo;s different this time.&lt;/p&gt;
&lt;p&gt;The fundamental relationship between user and vendor is about to change. Those two layers we talked about in the start? They&amp;rsquo;re about to get something really… weird, in between them. And this is a fundamental shift that we just haven&amp;rsquo;t seen before.&lt;/p&gt;
&lt;p&gt;Lately, I&amp;rsquo;ve been following &lt;a href="https://www.inkandswitch.com/"&gt;Ink and Switch&lt;/a&gt; and their research around &amp;ldquo;&lt;a href="https://www.inkandswitch.com/essay/malleable-software/"&gt;malleable software&lt;/a&gt;,&amp;rdquo; which is software the user can change. They have &lt;a href="https://www.youtube.com/watch?v=c1Kaip0fezI"&gt;some great videos&lt;/a&gt; on this.&lt;/p&gt;
&lt;p&gt;(The subtitle for that linked article is telling: &amp;ldquo;Restoring user agency in a world of locked-down apps.&amp;rdquo;)&lt;/p&gt;
&lt;p&gt;In the age of AI, we&amp;rsquo;re going to encounter this more and more. AI has given us the option to change anything we like, and that option is slowly going to become an expectation. Consequently, we&amp;rsquo;re drifting into the &amp;ldquo;platform-ization&amp;rdquo; of everything. How &amp;ldquo;malleable&amp;rdquo; your software is will become a key point of evaluation, no matter how much you try to tell people you&amp;rsquo;re selling a product, not a platform.&lt;/p&gt;
&lt;p&gt;I did some research last year on using AI to create dynamic/disposable components around a data core &amp;ndash; &lt;/p&gt;
&lt;p&gt;&lt;a href="/tech/blog/cms-vibe-experiment/" data-no-index&gt;How Should a CMS Repository Understand the Content Within It?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I said this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Once I was satisfied that my data was secure (that my repository was &amp;ldquo;well-defended&amp;rdquo;), then I didn&amp;rsquo;t really care what Claude did with it. I don&amp;rsquo;t recommend getting callous with your data, but all of these apps took basically no effort from me, so I would have been happy to create them, use them, throw them away, and create new ones.&lt;/p&gt;
&lt;p&gt;Consider this: could every user roll their own UI? We usually talk about &amp;ldquo;the UI,&amp;rdquo; and maybe we have a default…but what if I don&amp;rsquo;t like it? So long as the repository can defend itself, then could I just have some AI agent write me my own UI that I do like?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the future of enterprise software. More and more, vendors are going to be designing two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The inviolate core of the software (the Queen Bee)&lt;/li&gt;
&lt;li&gt;The API/integration layer where AI and users can mess with stuff (the Worker Bees)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&amp;rsquo;s take it to an extreme: you design some enterprise software to manage some data. &lt;em&gt;You ship it without a UI&lt;/em&gt;, or perhaps just a very shallow UI. It&amp;rsquo;s just a data repository, a very well-realized API, an MCP server, and set of good documentation. You let your customers use AI to roll their own UI.&lt;/p&gt;
&lt;p&gt;If you did that, what problems would you be solving? What problems would you not have to solve anymore? What layers come out of the product?&lt;/p&gt;
&lt;p&gt;What would you stop building &lt;em&gt;in&lt;/em&gt; the product, and let other people build &lt;em&gt;on&lt;/em&gt; the product? What stuff would you yourself start building &lt;em&gt;on&lt;/em&gt; the product, rather than &lt;em&gt;in&lt;/em&gt; the product?&lt;/p&gt;
&lt;p&gt;The next generation of AI-enabled browsers is going to redefine how UIs exist in relation to users. They&amp;rsquo;ll let the user re-arrange software to their own desires. Imagine that every user has an AI agent that effectively writes browser extensions &amp;ldquo;over the top&amp;rdquo; of your software &amp;ndash; automatic &lt;a href="https://www.tampermonkey.net"&gt;TamperMonkey&lt;/a&gt; for the masses. Imagine being surprised every time you see how one of your users&amp;rsquo; UI looks and functions.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;I&amp;rsquo;m experimenting on this site with encouraging this. I&amp;rsquo;m building some HTML and JavaScript extension points that I&amp;rsquo;m testing to see if AI-powered browsers can figure out and use when I tell them I want something.&lt;/p&gt;
&lt;p&gt;For example: &amp;ldquo;Make an &amp;lsquo;Edit this Content&amp;rsquo; button appear on every page that is editable.&amp;rdquo; It&amp;rsquo;s my hope that the UI and client tooling I add will be identifiable and usable by an AI agent to let it enable these things in a consistent and manageable way.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m essentially inviting and encouraging a browser AI agent to hack this site.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;How ready for this are you?&lt;/p&gt;
&lt;p&gt;Technically, how many layers do you have in your software stack? What affordances do you have for functional insertion in each different layer? How close to the &amp;ldquo;base&amp;rdquo; layer can a customer affect? If someone throws away your UI, does the rest of the product still work? Does it still provide value?&lt;/p&gt;
&lt;p&gt;Mentally, emotionally, and philosophically, how ready are you to release your grip on all the layers? How ready are you to concede that AI is going to add layers to your product that you never conceived of? Are you going to embrace this or fight it?&lt;/p&gt;
&lt;p&gt;Progress against this idea will improve software as a whole. In general, vendors are holding on too tightly to their functionality. Too many offerings are &amp;ldquo;all product, no platform,&amp;rdquo; and that inflexibility is not going to play well in the future.&lt;/p&gt;
&lt;p&gt;AI is going to generate some soul searching and hopefully constructive determination over where the actual value-add of an enterprise software vendor lies.&lt;/p&gt;
&lt;p&gt;I suspect that a wholesale re-definition of the relationship between vendor and customer is not far behind.&lt;/p&gt;
&lt;h2&gt;Postscript: Scriptable Software&lt;/h2&gt;
&lt;p&gt;If you like the idea of malleable software and how you might enable it at your organization, maybe watch this talk I gave in Croatia in 2022.&lt;/p&gt;
&lt;p&gt;It sums up a lot of what I&amp;rsquo;m thinking in this space, and it was given before AI really broke open in the last few years, so it&amp;rsquo;s a case for the pure idea, independent of any AI implications.&lt;/p&gt;


&lt;div class="video-container"&gt;
    &lt;iframe src="https://www.youtube.com/embed/S6MTRBOHhvE" title="" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;</description>
      <pubDate>Sat, 3 Jan 2026 00:00:00 -0600</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/platformization/</guid>
    </item>
    <item>
      <title>Low Code: Short Term vs. Long Term Value</title>
      <link>https://live.deanebarker.net/tech/blog/low-code-value/</link>
      <description>&lt;p&gt;I spent some time with a low-code app building platform this week. I built a demo app with it, and I was pretty impressed overall. It wasn&amp;rsquo;t as bad as I had feared.&lt;/p&gt;
&lt;p&gt;I did have two superficial thoughts about it &amp;ndash; &lt;/p&gt;
&lt;h2&gt;Consistency Has Value in the Long Term&lt;/h2&gt;
&lt;p&gt;While working with it, I would get a little frustrated because it would take me longer to do something. But the hidden value I saw is that there&amp;rsquo;s less chance to color outside the lines.&lt;/p&gt;
&lt;p&gt;In this particular platform, there&amp;rsquo;s basically one way to do most things. You can&amp;rsquo;t really get… clever, with your code. The way things are implemented is pretty regimented, and while you can get to the destination you, the route is sometimes a little circuitous.&lt;/p&gt;
&lt;p&gt;In the short term, this can be annoying. But in the longer term &amp;ndash; especially with larger, distributed teams &amp;ndash; this would be a huge value-add. One of the problems with code is understanding it after it&amp;rsquo;s been written. And there&amp;rsquo;s always a tendency to try to demonstrate your skill by optimizing and abstracting and otherwise trying to leave evidence that you&amp;rsquo;re The Smartest Guy in the Room™&lt;/p&gt;
&lt;p&gt;Not being able to deviate from implementation and coding patterns is weirdly freeing. The platform becomes &amp;ldquo;bad cop&amp;rdquo; &amp;ndash; meaning, you can say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I would have used [insert ridiculously theoretical coding methodology here], but I couldn&amp;rsquo;t because the platform wouldn&amp;rsquo;t let me. Bummer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This leaves you with really simple, clear, understandable program flow. People behind you can easily figure out what you were trying to do without you have to explain it.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;And this doesn&amp;rsquo;t even include code syntax issues, which can be a really dumb Holy War in some organizations &amp;ndash; not mention the minds of some developers.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;In some sense, the code becomes self-documenting because it exists in relation to a much smaller set of possibilities and patterns. When someone after you is trying to figure out what you were doing, there&amp;rsquo;s a vastly reduced &amp;ldquo;menu&amp;rdquo; of things you &lt;em&gt;might&lt;/em&gt; have been trying to do, so it becomes easier to make sense of it.&lt;/p&gt;
&lt;h2&gt;A Common Execution Environment Removes a Lot of Uncertainty&lt;/h2&gt;
&lt;p&gt;If you assume someone&amp;rsquo;s codebase, and can figure it out, there&amp;rsquo;s still a lot of uncertainty about how to run it. What language is it written in? What runtime does it need? What dependencies does it have? What weird quirks about the environment do I need to configure?&lt;/p&gt;
&lt;p&gt;I think every developer has some horror story about &amp;ldquo;just trying to get it running.&amp;rdquo; You can spend hours just getting a dev environment running correctly for some code before you even start thinking about fixing or improving it.&lt;/p&gt;
&lt;p&gt;The particular low-code platform I was working with has a built-in runtime. They have cloud and on-prem versions, but either way, you&amp;rsquo;re writing an app to fit into their architecture. To deploy, you click a button and it runs inside their containered environment.&lt;/p&gt;
&lt;p&gt;Like the other point, this is freeing. The urge to do anything interesting or clever in the runtime environment is gone &amp;ndash; you have no choice, because it&amp;rsquo;s only going to run in one environment, one way. You&amp;rsquo;re all working towards the same runtime.&lt;/p&gt;
&lt;p&gt;Again, in the short time, this might feel limiting. But over the long time, I imagine this is hugely valuable. Theoretically, the code will always run. Ten years from now, you can pull it off the shelve, understand it easily, change it, then put it back on the shelf in the same spot.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;I know, I know &amp;ndash; this assumes you still have access to the platform. There is absolutely the risk of vendor lock-in here, but that&amp;rsquo;s a risk you sort of have to accept to get the other benefits. It&amp;rsquo;s a trade-off.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Both this observations point to a common problem in software development &amp;ndash; &lt;/p&gt;
&lt;p&gt;Software doesn&amp;rsquo;t &amp;ldquo;happen&amp;rdquo; at one time. We often think only about &lt;em&gt;writing&lt;/em&gt; code. We don&amp;rsquo;t think about maintaining it, evolving it, improving it, or sharing it. With few exceptions, code only has real value over time. Unless you&amp;rsquo;re writing something for a one-time project then throwing it away, you are going to have to revisit that code at some time.&lt;/p&gt;
&lt;p&gt;This means you have to understand it, and you have to have a place to run it. When every possibility is open to you, those two things can suck up an absurd amount of time. Reducing options in the short-term can be annoying, but over the long-term, the value should be huge.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;See also: &lt;a href="/tech/blog/your-cms-as-bad-cop/" data-no-index&gt;Your CMS as Bad Cop&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Content management systems thrive on consistency. In a lot of ways, they&amp;rsquo;re kind of like a database table. In a table, you get rows and columns. In a CMS, you get content types and properties, and they fit together the same way whether you have three pages or three million. At least, that&amp;rsquo;s the idea.&lt;/p&gt;
&lt;p&gt;But when you&amp;rsquo;re not using content management, you can do anything you want. You could make every single page just a little bit different, if you wanted. Sometimes, it happens this way accidentally. Often, it happens because a content owner just wants something different.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/aside&gt;
&lt;p&gt;I got my car washed today. I hate it went you have to drive out through the dryers and there&amp;rsquo;s some big timer flashing at you, because you have to time it just right &amp;ndash; you have to drive slow enough to use all the time, but sometimes you go too fast, and then you have to back up. I think about this way too much, and it probably doesn&amp;rsquo;t matter. My Jeep looks about the same no matter what I do.&lt;/p&gt;
&lt;p&gt;But this particular car wash was on a track. I was getting pushed along. I got pushed out through the dryers and spit out the other side and then I drove off. I didn&amp;rsquo;t have to think about it. And again, my Jeep pretty much looked the same as it always does.&lt;/p&gt;
&lt;p&gt;Sometimes it&amp;rsquo;s nice not waste effort on things that don&amp;rsquo;t matter much.&lt;/p&gt;</description>
      <pubDate>Sat, 4 Oct 2025 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/low-code-value/</guid>
    </item>
    <item>
      <title>Lessons Learned from Vibe-Coding a Configuration Parser</title>
      <link>https://live.deanebarker.net/tech/blog/vibe-lessons/</link>
      <description>&lt;p&gt;I vibe-coded something the other day. And not something temporary &amp;ndash; this is a library I want to use in production environments. The process got me thinking about where the real value &amp;ndash; and the real work &amp;ndash; of functional code lies.&lt;/p&gt;
&lt;p&gt;Years ago, I came up with a syntax for configuring a &amp;ldquo;pipelined&amp;rdquo; software process. It was a way to specify &amp;ldquo;commands&amp;rdquo; and pass &amp;ldquo;arguments&amp;rdquo; to them in plain text.&lt;/p&gt;
&lt;p&gt;It looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;doThisThing  -argument:value
thenDoThis
andThenThis  -argument1:value -argument2:value
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I know, I know &amp;ndash; this is not at all original. It looks a lot like any shell, and that&amp;rsquo;s clearly what I emulated. (I was doing a fair amount of Powershell at the time, I remember.)&lt;/p&gt;
&lt;p&gt;Back then, I wrote a parser for this in C#, for the &lt;a href="https://denina.org/"&gt;Denina&lt;/a&gt; project. It would take in the text above, and return a configuration object with a clean set of objects to represent the commands and arguments. I could then use that in whatever software process I was managing.&lt;/p&gt;
&lt;p&gt;Recently, I had been thinking about a new application for it. I wanted a version of it in JavaScript, along with some enhancements.&lt;/p&gt;
&lt;p&gt;…but I just did &lt;em&gt;not&lt;/em&gt; want to write this. Parsers are notoriously tedious to write, and it usually devolves to a lot of debugging. Consequently, I was procrastinating.&lt;/p&gt;
&lt;p&gt;(You might be looking at the above example and thinking, &amp;ldquo;But that looks so simple…&amp;rdquo; Well, read the spec linked below. There&amp;rsquo;s a lot going on there you can&amp;rsquo;t see.)&lt;/p&gt;
&lt;p&gt;So, I figured this was a good scenario for vibe-coding. This is a pure code problem &amp;ndash; there&amp;rsquo;s no UI in this case. Additionally, this is easily testable &amp;ndash; the text turns into an object, and it&amp;rsquo;s pretty clear if that object is configured the way it&amp;rsquo;s supposed to be.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve &lt;a href="/tech/blog/cms-vibe-experiment/"&gt;vibe-coded some stuff before&lt;/a&gt;, but this was a little different because it wasn&amp;rsquo;t meant to be disposable, throwaway code. I wanted to keep this for use in production environments.&lt;/p&gt;
&lt;p&gt;I decided that I just need to specify &lt;em&gt;very precisely&lt;/em&gt; how this was supposed to work, and make sure there was as little room for interpretation as possible.&lt;/p&gt;
&lt;p&gt;I decided to write a &amp;ldquo;spec&amp;rdquo; for the language. I figured this would be the safest way to explain to AI how it works. This wasn&amp;rsquo;t meant to be a formal spec (a la &lt;a href="https://pegn.dev/"&gt;PEGN&lt;/a&gt;, or whatever), but just a very descriptive explanation of how it works that could double as documentation.&lt;/p&gt;
&lt;p&gt;And here it is &amp;ndash; &lt;/p&gt;
&lt;p&gt;&lt;a href="/tech/code/config-lang/spec/" data-no-index&gt;Configuration Language: Specification&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s 2,000 words and dozens of examples. It took about 90 minutes to write the first draft.&lt;/p&gt;
&lt;p&gt;I figured it was in great shape, but just to be sure, I uploaded it to ChatGPT with this prompt:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Read this and let me know if anything is vague, contradictory, or otherwise doesn&amp;rsquo;t make sense.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It came back with 27 problems.&lt;/p&gt;
&lt;p&gt;Some of them were nitpicky, which annoyed me… but that doesn&amp;rsquo;t matter. If I was asking to AI to write this, then it only mattered that AI understood it. In this case, lack of context was a benefit &amp;ndash; AI was coming at it with no prior knowledge, while this idea had been kicking around in my human brain for a decade.&lt;/p&gt;
&lt;p&gt;Besides the nitpicking, some other issues were quite valid. Some changes were clarifications to the doc to better explain what was in my head, but others were actual, meaningful decisions I hadn&amp;rsquo;t thought of, but had to come to a decision on.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;someCommand -argument
someCommand -argument:
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Does the trailing colon on an argument matter? I had initially stated in the spec that an argument without a value got a default of &amp;ldquo;true&amp;rdquo; (as if to say, &amp;ldquo;this argument exists&amp;rdquo;). However, if I end an argument name with a colon as if I&amp;rsquo;m going to supply a value, but then I don&amp;rsquo;t… is that the same thing?&lt;/p&gt;
&lt;p&gt;No, I decided. If you end with a colon, then that&amp;rsquo;s an empty string value. I would have never thought to specify this, and having AI bring it up evolved the language and covered an edge case.&lt;/p&gt;
&lt;p&gt;I went through this same process &lt;em&gt;dozens&lt;/em&gt; of times for other edge cases I hadn&amp;rsquo;t thought of.&lt;/p&gt;
&lt;p&gt;Once I had finished editing that first round of complaints, I told ChatGPT to forget the prior conversation and sent it the text again with the same prompt. I don&amp;rsquo;t remember what it came back with, but it was &lt;em&gt;damn-near the same number of problems&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I spent an entire morning like this &amp;ndash; working on this specification document &amp;ldquo;alongside&amp;rdquo; AI. I would edit, it would nit-pick some more, and so on and so on.&lt;/p&gt;
&lt;p&gt;I finally got it down to complaining about a single-digit number of really weird problems, and decided an AI could finally take a run at writing it.&lt;/p&gt;
&lt;p&gt;I used Claude in Visual Studio Code in agent mode. I told it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Read this document and create that functionality in a single-file JavaScript module with no external dependencies. Export all classes. Write unit tests to ensure proper implementation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It took 14 minutes, and I&amp;rsquo;m happy to report that the results are &lt;em&gt;stellar&lt;/em&gt;. It wrote 45 unit tests (all of which passed, after a couple attempts and edits). Performance is exceptional: a fairly complicated chuck of CL parses into an object in about half a millisecond.&lt;/p&gt;
&lt;p&gt;I looked through the code a bit. From what I can see, it&amp;rsquo;s not particularly clever &amp;ndash; it&amp;rsquo;s what you would call a &amp;ldquo;brute force&amp;rdquo; parser. It goes line by line and does string spitting to divide everything up. Lots of conditionals and loops. At the risk of sounding defensive, I easily could have written this myself.&lt;/p&gt;
&lt;p&gt;I asked for a couple changes &amp;ndash; nothing that would affect the spec or the underlying language, but rather just some preferences for the JavaScript implementation. And I changed the name of one construct after some second thoughts. (I had to tell it to unit test the changes. I think it&amp;rsquo;s up to 49 tests now.)&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been using the resulting code for a week and it&amp;rsquo;s faded into the background in the sense that it &amp;ldquo;just works.&amp;rdquo; Performance is great, and it&amp;rsquo;s never made a mistake that I&amp;rsquo;ve detected, so it&amp;rsquo;s become a lovely black box that I don&amp;rsquo;t have to care about.&lt;/p&gt;
&lt;p&gt;So, what did I learn from this, and what existing notions did it reinforce?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Vibe-coding is really good when you have a tightly defined use case with objective results that are easily unit-tested.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It&amp;rsquo;s helpful to write documentation in advance and use it for context. I basically documented non-existent software, then just told AI to write some actual software to match what I wrote.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It helps to have very clear demarcation lines around the code. What AI wrote was really modular (I literally told it to write a module). Nothing in here will &amp;ldquo;leak&amp;rdquo; into other code. This matches how I use AI to assist when coding: I always ask it for &amp;ldquo;a pure function with no side-effects or dependencies to do …X.&amp;rdquo; That keeps AI-generated code tightly confined.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Did vibe-coding this save me time? …I don&amp;rsquo;t know. I probably had 4-5 hours total into this. Could I have written the parser in that amount of time with the same performance and quality? …maybe?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;aside&gt;&lt;p&gt;This reminds me of a guy that &lt;a href="/other/mlm/"&gt;pitched me Amway once&lt;/a&gt;. He told me, &amp;ldquo;I don&amp;rsquo;t have to work anymore! I don&amp;rsquo;t have a job!&amp;rdquo; But there he was, spending an hour trying to convince me to join, which he told me he did with a multiple people every day.&lt;/p&gt;
&lt;p&gt;So, he &lt;em&gt;did&lt;/em&gt; have a job, it was just different than whatever he did at his last job.&lt;/p&gt;
&lt;p&gt;Vibe-coding is still work. It&amp;rsquo;s just different work.&lt;/p&gt;
&lt;/aside&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Get second opinions &amp;ndash; AI and otherwise. Fight battles with the idea before code gets written. If you assume the code will be fine, what are the other questions that need to be answered?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It helps to have a clear plan. I&amp;rsquo;ve spent a decade &amp;ldquo;with&amp;rdquo; this language in another project. I knew it worked, so I had an evolved (or so I thought) mental model of what I wanted.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And this last point perhaps gets a little philosophical.&lt;/p&gt;
&lt;p&gt;What was the main thread of work in writing a JavaScript parser for my configuration language? Was it writing the actual code? Or was it deciding what problem I was trying to solve, how I wanted it solved, and all the different ways it might go wrong?&lt;/p&gt;
&lt;p&gt;Ankur Goyal has &lt;a href="https://www.braintrust.dev/blog/async-programming"&gt;borrowed the term &amp;ldquo;async programming&amp;rdquo; to describe this&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The shift is subtle but powerful: instead of writing code line by line, we&amp;rsquo;re learning to describe problems clearly and let tools solve them in the background.&lt;/p&gt;
&lt;p&gt;[…] AI isn&amp;rsquo;t replacing programming, but the most valuable parts of programming are becoming more prominent while routine tasks move to the background.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(And I did, in fact, let AI solve my problem &amp;ldquo;in the background.&amp;rdquo; Once Claude started running, I think I set my laptop down and went to get breakfast.)&lt;/p&gt;
&lt;p&gt;Honestly, writing the actual code of this parser just wasn&amp;rsquo;t &lt;em&gt;that&lt;/em&gt; important. It really didn&amp;rsquo;t involve a lot decisions &amp;ndash; I even told Claude not to use any dependencies, so there weren&amp;rsquo;t many questions about architecture (it&amp;rsquo;s not going to write a &lt;a href="/tech/parlot/parser-combinators/"&gt;parser combinator library&lt;/a&gt; from scratch, so brute-force was the only real option).&lt;/p&gt;
&lt;p&gt;This reminds me of the book &lt;em&gt;&lt;a href="/library/titles/how-big-things-get-done/" data-no-index&gt;How Big Things Get Done: The Surprising Factors That Determine the Fate of Every Project, from Home Renovations to Space Exploration and Everything In Between&lt;/a&gt;&lt;/em&gt;. It&amp;rsquo;s written by a guy who has spent his career studying large-scale construction projects like dams and nuclear power plants.&lt;/p&gt;
&lt;p&gt;One of the core ideas of the book is: think slow, move fast. Few projects ever fail from lack of planning. The book encourages lots planning, edge case speculation, proofs-of-concept, and &amp;ldquo;red team&amp;rdquo; analysis. That&amp;rsquo;s where the problems get identified and the core idea and solution starts to emerge and get refined.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s what we&amp;rsquo;re trying to get to: the core nature of the problem and the solution. We&amp;rsquo;re trying to &lt;em&gt;solve problems&lt;/em&gt;, not write code. The code is just the solution vector. I&amp;rsquo;m not trying to trivialize it by any stretch, but the real obstacle was not what ended up being just 395 lines of JavaScript &amp;ndash; it was the problem definition and the decision of how to solve it.&lt;/p&gt;</description>
      <pubDate>Sun, 28 Sep 2025 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/vibe-lessons/</guid>
    </item>
    <item>
      <title>Two-Stage Content Modeling</title>
      <link>https://live.deanebarker.net/tech/blog/two-stage-modeling/</link>
      <description>&lt;p&gt;I&amp;rsquo;ve been wrestling with a question: how much power should AI have over your CMS repository? In particular, how much access should it have to your content models?&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s an argument that we should let AI do whatever it wants to our models. I&amp;rsquo;ve seen lots of stories about how people are just letting AI engines modify their content models to fit the requirements of whatever output they want.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve argued against this &amp;ndash; &lt;/p&gt;
&lt;p&gt;&lt;a href="/tech/blog/cms-repo-ai/" data-no-index&gt;Queen Bees: The Resurgence of CMS Repositories in the Age of AI&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My concern is that content models are foundational. Lots of things depend on them. If you change a type carelessly, you can easily break some functionality you might not even know existed.&lt;/p&gt;
&lt;p&gt;For example &amp;ndash; &lt;/p&gt;
&lt;p&gt;One day, you decide not to show the &amp;ldquo;Date Published&amp;rdquo; on your blog post pages anymore. So you let AI delete that from the model &amp;ndash; since you don&amp;rsquo;t see it, you don&amp;rsquo;t need it right? It makes it easier for editors, since it simplifies the interface.&lt;/p&gt;
&lt;p&gt;Unfortunately, unbeknownst to you…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;…the &amp;ldquo;Date Published&amp;rdquo; property was used by a syncing process that transmitted new posts to your PR agency&lt;/li&gt;
&lt;li&gt;…the blog post listing page and RSS feed both require the &amp;ldquo;Date Published&amp;rdquo; to show the order of the posts; no date, no listing&lt;/li&gt;
&lt;li&gt;….your regulatory archiving process needed the &amp;ldquo;Date Published&amp;rdquo; to calculate retention times&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But, you claim, the date was a required field for these exact reasons! It was safe!&lt;/p&gt;
&lt;p&gt;…well, it was required and safe when it &lt;em&gt;existed&lt;/em&gt;. No property at all means no validation.&lt;/p&gt;
&lt;p&gt;And this is my biggest concern with not being jealously protective of our content models. It&amp;rsquo;s short-sighted to build them based only on what you can see or what output you want. It&amp;rsquo;s just as short-sighted to modify them based on the same criteria.&lt;/p&gt;
&lt;p&gt;I had a debate about this some years ago with my friend &lt;a href="https://www.codeart.dk/team/allan-thraen/"&gt;Allan Thraen&lt;/a&gt;. I think it was just after I taught a CMS class for &lt;a href="https://www.hackyourfuture.net/"&gt;Hack Your Future&lt;/a&gt; in Copenhagen. In that class, we were letting students add stuff to their models all they liked.&lt;/p&gt;
&lt;p&gt;The students had a great time, and I briefly caught myself thinking that maybe we were too strict over our models? That led to a discussion that resulted in this post:&lt;/p&gt;
&lt;p&gt;&lt;a href="/tech/blog/modeling-on-the-fly/" data-no-index&gt;Repouring the Foundation: The Perils of Content Modeling on the Fly&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And Allan responded with this:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.codeart.dk/blog/2019/4/the-curious-case-of-content-modelling/"&gt;The Curious Case of Content Modelling&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Which brings me back to the core question: &lt;em&gt;should we let AI into our models?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Sure, sure, in a perfect world, the AI engine would have a ton of context. In our example from above, it would know that the &amp;ldquo;Date Published&amp;rdquo; property was being used in all those different ways and would know not to touch it.&lt;/p&gt;
&lt;p&gt;But in my earlier post, I also made this point:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I get a little skeptical when people talk simply of &amp;ldquo;AI&amp;rdquo; as if they can guarantee that all their employees will be using the same engine with the same settings and the same context.&lt;/p&gt;
&lt;p&gt;In reality, I think we need to say &amp;ldquo;an AI&amp;rdquo; to represent that every AI is like a new freelance contractor that shows up to do a job, without knowing any other contractor that has worked in the past or may be working right now.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One solution, of course, is just to deny content model permissions to anyone but a selected few technically-minded people. And this is great… but now we&amp;rsquo;re back to the original state of not allowing AI in either.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Right? The AI was running as an authorized agent of the human user …right?&lt;/p&gt;
&lt;p&gt;This is a key question of AI: agency. Is an AI its own user with its own permissions, or is it always considered an extension of a human user that can only execute in the context of that human?&lt;/p&gt;
&lt;p&gt;If you have a human without permissions to modify the content model, and they can prompt an AI which &lt;em&gt;does&lt;/em&gt; have those permissions… well, that&amp;rsquo;s just not good.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Something else I said in that post:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;AI will simply magnify the volume of activity a single human can initiate&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Put another way: with AI, people can do stupid things &lt;em&gt;at scale&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So, how do CMS and AI get along? How do we empower the amazing things that AI will allow and prevent disasters?&lt;/p&gt;
&lt;p&gt;I got to thinking about this out loud on a &lt;a href="https://info.ingeniux.com/content-matters-podcast"&gt;Content Matters podcast episode&lt;/a&gt; with &lt;a href="https://www.linkedin.com/in/davidjhillis/"&gt;Dave Hillis&lt;/a&gt;, the CMO of Ingeniux. Dave and I go way back, and he thinks pretty deeply about CMS. He had read the blog post from above, and that kind of framed our conversation about how CMS and AI are going to get along in this brave new world.&lt;/p&gt;
&lt;p&gt;An example I always use in modeling is a field for &amp;ldquo;Mood.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say we want to add &amp;ldquo;Mood&amp;rdquo; to our content model, to represent the mood the CEO was in when she wrote whatever she wrote. This is kind of silly, but it represents something that might be added to a model on a whim only to be deleted later. Also, it doesn&amp;rsquo;t affect anything else &amp;ndash; it&amp;rsquo;s harmless, essentially. As a developer, I don&amp;rsquo;t much care if they have this property on their model or not.&lt;/p&gt;
&lt;p&gt;So, how do we enable this level of manipulation? How do we let an editor tell AI to add a &amp;ldquo;Mood&amp;rdquo; property so they can type stuff in a textbox and have it output on the page?&lt;/p&gt;
&lt;p&gt;I think the solution is two-stage modeling. We&amp;rsquo;re going to need to concede that not all parts of our model are equally important &amp;ndash; some parts of it need to be protected and some don&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;We can divide the properties on our types into two &amp;ldquo;stages&amp;rdquo; then (in quotes because I don&amp;rsquo;t know if that&amp;rsquo;s the right nomenclature; I&amp;rsquo;m still thinking about it):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Level 1:&lt;/strong&gt; These are properties created by a developer that have significant impact on the functioning of various digital properties. I put these on &amp;ldquo;Level 1&amp;rdquo; because they&amp;rsquo;re foundational &amp;ndash; everything is built on top of them. If the foundation of a house shifts, you have problems.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Level 2:&lt;/strong&gt; These are whatever the editors want. They can add and remove to their heart&amp;rsquo;s desire, provided they don&amp;rsquo;t duplicate a property name from Level 1. This is where the &amp;ldquo;Mood&amp;rdquo; property can live &amp;ndash; go nuts, fam.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Implicit in this is that AI acting as an agent of the user (…right?!) would have delegated access to Level 2, but no access to Level 1. Level 2 would effectively be a &amp;ldquo;sandbox&amp;rdquo; where nothing structural was attached.&lt;/p&gt;
&lt;p&gt;The key is that the &lt;em&gt;effective&lt;/em&gt; content model is the combination of those two. The actual model of content delivered downstream is both levels together, as one unit. Nothing outside of the modeling system even needs to know they exist at different levels of import.&lt;/p&gt;
&lt;p&gt;For a blog post, what goes in Level 1? I&amp;rsquo;m thinking just Title and Date Published? Those are basically required &amp;ndash; the date for the reasons we mentioned above, and the title just because we have to list content objects somewhere (lots of systems will default to &amp;ldquo;Untitled&amp;rdquo; because without a name, content gets hard to work with).&lt;/p&gt;
&lt;p&gt;What about Body? …meh. Maybe?&lt;/p&gt;
&lt;p&gt;You technically don&amp;rsquo;t need a body for a blog (a tweet might be considered a title with no body?). Additionally, as a developer, I&amp;rsquo;m not sure I care much about the body? It needs to be output in the template, sure, but that might not be my concern. And by putting this on Level 2, editors can change it &amp;ndash; they might want different validation or different rich text options or whatever. If someone else is doing the templating, then a lot of that becomes less crucial to core development.&lt;/p&gt;
&lt;p&gt;Now, to be clear, lots of systems can already do this via various features.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some systems have very granular permissions around every property on a type. I remember that Sitecore allowed detailed permissions down to the field level (everything in Sitecore is a content object &amp;ndash; an &amp;ldquo;item&amp;rdquo; &amp;ndash; so content models are actually defined as collections of content objects).&lt;/li&gt;
&lt;/ul&gt;
&lt;aside&gt;&lt;p&gt;See the section about &amp;ldquo;Recursive Content Models&amp;rdquo; in &lt;a href="/books/real-world-content-modeling/api/#h8"&gt;Real World Content Modeling&lt;/a&gt;. Also, see the first case study here, where I discuss how I once used Sitecore&amp;rsquo;s model recursion: &lt;a href="/tech/blog/case-studies-of-cms-to-sql-decoupled-publishing/" data-no-index&gt;Case Studies of CMS-to-SQL Decoupled Publishing&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;ul&gt;
&lt;li&gt;Some systems use composition or inheritance in their content models, where a content type can be a merging of two other types. This means we could model Level 1 in one type (&amp;ldquo;Blog Post Foundation&amp;rdquo;), Model 2 in another type (&amp;ldquo;Blog Post&amp;rdquo;) which incorporates the Level 1 type, and then just secure permissions so that very few people can modify the Level 1 type.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But, of couse, this all comes down to granular modeling permissions. If you don&amp;rsquo;t have that &amp;ndash; meaning users just have binary, all or nothing access to modify the models &amp;ndash; then I&amp;rsquo;m not sure any of this matters.&lt;/p&gt;
&lt;p&gt;Assuming we have that level of permissions control, these model architectures work well. In addition to being efficient and reducing repetition, they have some neat two-stage implications and allow you to segregate parts of your model into the important stuff… and all the other stuff.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;This all vaguely reminds me of &lt;a href="/tech/blog/multi-stage-transformation/"&gt;an idea I had for headless CMS about a decade ago&lt;/a&gt;. I thought that when a content object was saved, a webhook could call out to a remote service, get a payload of a data, and &amp;ldquo;attach&amp;rdquo; that to the content object as &amp;ldquo;meta.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This extra content would be delivered with the object to downstream services, but it wouldn&amp;rsquo;t be stored alongside it in the repository and it wouldn&amp;rsquo;t get the full benefit of &lt;a href="/books/real-world-content-modeling/content/"&gt;content services&lt;/a&gt; supplied to &amp;ldquo;first-order&amp;rdquo; content.&lt;/p&gt;
&lt;p&gt;This is essentially Level 1 and Level 2 described a different way.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Given that the required permissions and architectures already exist, then what are we talking about here, in terms of CMS evolution?&lt;/p&gt;
&lt;p&gt;Nothing, really. We&amp;rsquo;re just talking about modeling practices, effective permission management, and making sure we treat AIs as extensions of humans &amp;ndash; no AI should have more access than the person who can give it a prompt.&lt;/p&gt;
&lt;p&gt;With this in place, we&amp;rsquo;re a step closer to living in harmony.&lt;/p&gt;</description>
      <pubDate>Sun, 21 Sep 2025 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/two-stage-modeling/</guid>
    </item>
    <item>
      <title>Where's the Line Between the Web and Your CMS?</title>
      <link>https://live.deanebarker.net/tech/blog/web-cms-division/</link>
      <description>&lt;p&gt;A couple weeks ago, &lt;a href="/tech/blog/404-wtf/"&gt;I wrote about a stupid thing I did with redirects&lt;/a&gt; once.&lt;/p&gt;
&lt;p&gt;My friend &lt;a href="https://www.linkedin.com/in/iamandycohen/"&gt;Andy Cohen&lt;/a&gt; reposted it on LinkedIn, and, among other things, &lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:7371364955788554240/"&gt;said this&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Redirects don&amp;rsquo;t belong in the CMS layer&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;rsquo;m inclined to agree. I think a CMS can be a &lt;em&gt;source for redirect data&lt;/em&gt;, but I&amp;rsquo;m coming to believe that any redirection should happen long before anything arrives on your CMS&amp;rsquo;s doorstep. In fact, a &lt;em&gt;lot&lt;/em&gt; of things should happen before anything is serviced by your CMS.&lt;/p&gt;
&lt;p&gt;I self-host this site &amp;ndash; cached and proxied through a Cloudflare tunnel. It&amp;rsquo;s on a bespoke system that has grown organically over seven years. It&amp;rsquo;s basically a templating and organizational layer on top of 6,000-ish Markdown files.&lt;/p&gt;
&lt;p&gt;Last week, for whatever reason, I was running the server in the console, which meant I was watching the requests march down the screen, &lt;a href="https://en.wikipedia.org/wiki/Digital_rain"&gt;Matrix-style&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What I was seeing was mostly redirects.&lt;/p&gt;
&lt;p&gt;I quickly learned that I wasn&amp;rsquo;t sending cache headers with redirect responses. It didn&amp;rsquo;t occur to me that they have &amp;ldquo;cachability&amp;rdquo; like anything else. So I fixed this.&lt;/p&gt;
&lt;p&gt;But there was still a &lt;em&gt;lot&lt;/em&gt; of damn redirects. Remember that this site used to be &lt;a href="https://gadgetopia.com/"&gt;Gadgetopia&lt;/a&gt;, which on the web &lt;a href="/tech/blog/gutenberg-project/"&gt;since 2002&lt;/a&gt;. Given the URL footprint (7,000 or so unique inbound URLs) and the longevity, the site gets a lot of random traffic. It&amp;rsquo;s &lt;a href="/tech/blog/crawlers-are-stupid/"&gt;mostly&lt;/a&gt; &lt;a href="/tech/blog/things-that-web-crawlers-hate/"&gt;bots&lt;/a&gt;, I&amp;rsquo;m sure, but there are still a lot of links out there.&lt;/p&gt;
&lt;p&gt;A few years ago, &lt;a href="/tech/blog/evaluating-gadgetopia-content/"&gt;I salvaged about 350 of those posts&lt;/a&gt;, then pushed the other 7,000+ off to another site I called the &amp;ldquo;archives&amp;rdquo; (&lt;a href="https://archive.gadgetopia.com/post/1576/"&gt;an example&lt;/a&gt;). Getting people there involves some logic, because some posts redirect here, some there, etc.&lt;/p&gt;
&lt;p&gt;I had built that logic into my CMS, but the wastefulness of this suddenly occurred to me. I&amp;rsquo;m no longer adding to Gadgetopia, and that content is not going to change. With Andy&amp;rsquo;s prompting, I decided that this doesn&amp;rsquo;t need to be in my CMS. My CMS can be a source of information for it, but the &lt;em&gt;action&lt;/em&gt; of all these things should be somewhere else.&lt;/p&gt;
&lt;p&gt;I wrote a simple exporter to get the old Gadgetopia URLs out to a Cloudflare redirect CSV, and uploaded that via their Bulk Export. Instantly, that dropped inbound traffic by 80% - 90%. To be fair, the overhead of that traffic was low &amp;ndash; the requests were redirected early, and the responses were all empty bodies with just a &lt;code&gt;Location&lt;/code&gt; header, but still…&lt;/p&gt;
&lt;p&gt;So, that&amp;rsquo;s a CMS being a &lt;em&gt;source&lt;/em&gt; for redirection, but not the actual executor of the logic. Simple enough.&lt;/p&gt;
&lt;p&gt;But, I had a bunch of other logic that just didn&amp;rsquo;t need to be in my CMS.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I have a rule that an inbound URL either has to end with a trailing slash, or have a dot (&amp;ldquo;.&amp;rdquo;) in it (meaning a direct request to a file). If you try to come into a path without a trailing slash, you&amp;rsquo;ll get redirected.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I filter querystring args. I have a list of arguments I use for the site, and the CMS will strip anything not in that list and redirect you back without them. I do this so that the URL you see will be &amp;ldquo;clean,&amp;rdquo; stripped of any marketing cruft, in case you bookmark it or share it out again.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For the same reason, the URL needs to be normalized. Any double slashes, parent pathing, or upper-casing will be corrected and redirected.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I have a &amp;ldquo;kill list&amp;rdquo; of URL patterns that are DOA. These are mostly hack attempts to random WordPress-ish directories or other vulnerabilities (anything containing non-ASCII characters, for example). These are detected and 404ed very early in the request.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST requests are only allowed through a very narrow range of paths.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And there are some more, getting increasingly esoteric. I have these in a class/infrastructure I called a &lt;code&gt;PathFilter&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The goal is that any inbound URL that&amp;rsquo;s actually processed by my CMS should be… perfect. Maybe this is anal-retentiveness, I don&amp;rsquo;t know. But I steadfastly maintain that there&amp;rsquo;s value in being protective of your &amp;ldquo;URL-space.&amp;rdquo; URLs are &amp;ldquo;tickets&amp;rdquo; to content. Keep your tickets in order.&lt;/p&gt;
&lt;p&gt;To handle this logic, I created a &lt;a href="https://workers.cloudflare.com/"&gt;Cloudflare Worker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can route all inbound traffic through a JavaScript function (the &amp;ldquo;Worker&amp;rdquo;). That JavaScript can do whatever it likes, up to and including servicing the entire request via some MVC-ish mechanism.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;If you felt like it, you could easily write some form of a CMS entirely the Cloudflare edge network. I&amp;rsquo;m sure this has been done. I think &lt;a href="https://www.conscia.ai/"&gt;Conscia&lt;/a&gt; did something like it, and I know that &lt;a href="https://www.optimizely.com/insights/blog/content-graph-announcement/"&gt;Optimizely Graph&lt;/a&gt; is handled entirely at the edge.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;My Worker examines the request, does the logic noted above and some other stuff, and either redirects, 404s, or passes the request through. Essentially, you can program against Cloudlfare&amp;rsquo;s CDN logic.&lt;/p&gt;
&lt;p&gt;Cloudflare tracks execution in two ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CPU Time&lt;/strong&gt; is just what it sounds like &amp;ndash; how long a CPU took to process it. This is essentially nothing. Usually 0ms, but occasionally 1ms.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Wall Time&lt;/strong&gt; is how long the request got held up at the Worker, all things considered. This is generally in the 10-20ms range. Sometimes higher, but I&amp;rsquo;m curious how long my bespoke code was taking for the same thing.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Does this bind me to Cloudflare? Yeah, loosely. The logic is contained in JavaScript, which could probably transport to any other proxy that allows it. Or I could write it in my own Node-based proxy.&lt;/p&gt;
&lt;p&gt;Now, none of this is new. Cloudflare Workers &lt;a href="https://blog.cloudflare.com/introducing-cloudflare-workers/"&gt;have been around since 2017&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But the whole thing got me thinking about the division of responsibilities. How much work should your CMS do on the incoming request? Is that the highest and best purpose of your CMS &amp;ndash; just figuring out if it should even service the request? Or should that work be pushed off somewhere else?&lt;/p&gt;
&lt;p&gt;At this moment, my CMS can trust that every single inbound request is one that should be serviced. I pulled hundreds of lines of logic out of the CMS &amp;ndash; deleting an entire subsystem, in fact. For all my CMS knows, the web is a lovely place where all URLs are perfect and no mistakes are ever made.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve started to take this a step further, and I&amp;rsquo;m separating the idea of my CMS from the web server entirely. It&amp;rsquo;s not headless &amp;ndash; the web server will have a native connection to the CMS (via a C# API). So it&amp;rsquo;s not remote, but at the same time, I&amp;rsquo;m divorcing the concept of my CMS and my web server.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;&lt;em&gt;Please&lt;/em&gt; don&amp;rsquo;t come at me about &amp;ldquo;the web site and your CMS are not the same thing!&amp;rdquo; At risk of sounding like a douchebag, I might have been &lt;a href="/tech/blog/use-cases-for-headless-cms/"&gt;writing about headless&lt;/a&gt; before you had your first job.&lt;/p&gt;
&lt;p&gt;This is a system that has grown incrementally for seven years. Sometimes things happen and you don&amp;rsquo;t step back and realize it until way down the road.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;So, even if your system is installed on your own metal, there could be an argument to have &lt;em&gt;two&lt;/em&gt; systems: a CMS, and then a &lt;em&gt;web server integration&lt;/em&gt;. Requests hit your web server, are processed by your web server integration code, and then &lt;em&gt;call out&lt;/em&gt; to the CMS code to be resolved against content.&lt;/p&gt;
&lt;p&gt;As a neat side effect of all this, static file generation is a hop, skip, and a jump away. Since my CMS is just producing HTML and providing it to a web server &amp;ndash; with no notion of it being used to satisfy a web request &amp;ndash; then who says we can&amp;rsquo;t just write it to a file instead? My web server is now calling an &lt;code&gt;HtmlOutputFactory&lt;/code&gt; in a DLL that I can also invoke from the command line and get the exact same HTML that the web server gets.&lt;/p&gt;
&lt;p&gt;At some point, I&amp;rsquo;d like to see if I can serve the same website from an entirely different web server (not Kestrel, the default web server for ASP.NET). I&amp;rsquo;ve been smitten lately with &lt;a href="https://stratdev3.github.io/SimpleW/"&gt;SimpleW&lt;/a&gt;, and I think under the new architecture, I could serve the exact same site from it in about three lines of code.&lt;/p&gt;
&lt;aside class="update"&gt;&lt;p&gt;About a month after this post was written, I switched to static HTML generation being served from &lt;a href="https://caddyserver.com/"&gt;Caddy&lt;/a&gt; on Ubuntu.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;And consider the inverse: could your static site generator be hooked up to your CMS as a dynamic content generation system? Could it generate a single path at a time, on demand, and return that to your CMS? The lines get really fuzzy here…&lt;/p&gt;
&lt;p&gt;This is probably an example of turning around in a circle to end up right back where you started, but it was a educational experience. …or a &lt;em&gt;re&lt;/em&gt;-educational experience? I think these were all concepts I knew, but had lost track of for some reason.&lt;/p&gt;
&lt;p&gt;Anyway, thanks to Andy for his LinkedIn assertion that flipped some bit in my brain and allowed me to separate the two concerns more clearly.&lt;/p&gt;</description>
      <pubDate>Wed, 17 Sep 2025 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/web-cms-division/</guid>
    </item>
    <item>
      <title>Content Query Languages</title>
      <link>https://live.deanebarker.net/tech/blog/content-querying/</link>
      <description>&lt;p&gt;I have a weird fetish for blurring the lines between code and content in CMS. Traditionally, you have code which is written by developers, and content which is written by editors, and never shall the two meet.&lt;/p&gt;
&lt;p&gt;But what happens when editors need to write some code-ish stuff? What happens when things fall into the middle &amp;ndash; too simple or ephemeral for a full developer, but too complex for an editor using a UI and the patterns established way back during implementation?&lt;/p&gt;
&lt;p&gt;Can we enable editors to …sort-of develop? Can we create a new class of editor called a &amp;ldquo;&lt;a href="https://www.servicenow.com/workflows/creator-workflows/what-is-a-citizen-developer.html"&gt;citizen developer&lt;/a&gt;&amp;rdquo;?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve talked about this a lot. I hinted at it 20 years ago, in the context of templating languages:&lt;/p&gt;
&lt;p&gt;&lt;a href="/tech/blog/smarty-as-sub-language/" data-no-index&gt;Smarty as a “Sub-Language”&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Then I wrote about it explicitly 10 years ago:&lt;/p&gt;
&lt;p&gt;&lt;a href="/tech/blog/editorial-scripting-in-cms/" data-no-index&gt;Editorial Scripting in CMS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That post eventually became a full-blown scripting library called &lt;a href="https://denina.org"&gt;Denina&lt;/a&gt;. Here&amp;rsquo;s me talking about that &lt;a href="https://www.youtube.com/watch?v=a_xmvt1w6Ww"&gt;at the Umbraco Codegarden event in Denmark&lt;/a&gt;.&lt;/p&gt;


&lt;div class="video-container"&gt;
    &lt;iframe src="https://www.youtube.com/embed/a_xmvt1w6Ww" title="" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;a href="https://github.com/deanebarker/Denina-Sharp/wiki/"&gt;wiki for Denina&lt;/a&gt; includes some good content about the philosophy and prior art behind this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/deanebarker/Denina-Sharp/wiki/Why-Do-This"&gt;Why Do This&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/deanebarker/Denina-Sharp/wiki/Use-Cases"&gt;Use Cases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/deanebarker/Denina-Sharp/wiki/Alternatives"&gt;Alternatives&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ve never stopped with this weird obsession. Here&amp;rsquo;s me &lt;a href="https://www.youtube.com/watch?v=S6MTRBOHhvE"&gt;in Croatia in 2023&lt;/a&gt; talking about the entire concept of &amp;ldquo;scriptable software&amp;rdquo; (clearly, I was stuck on the &amp;ldquo;promise and peril&amp;rdquo; title motif).&lt;/p&gt;


&lt;div class="video-container"&gt;
    &lt;iframe src="https://www.youtube.com/embed/S6MTRBOHhvE" title="" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;I spent five years at Episerver/Optimizely, and I &lt;del&gt;think&lt;/del&gt; know I drove people nuts there with my attempts to bring scripting into that platform.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;I remember standing in the kitchen in the Stockholm office and over-hearing the CTO doing an AMA with the Swedish engineers in the lunch room. At one point he said: &amp;ldquo;Deane Barker clearly isn&amp;rsquo;t going to be happy until we&amp;rsquo;re writing assembly in the browser.&amp;rdquo; I don&amp;rsquo;t think he knew I was getting coffee.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Lately, I&amp;rsquo;m focusing this obsession to content querying and aggregation: how can we use code concepts to find content and bring it together into the groupings that we need?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve often said that the way a CMS aggregates content is really the soul of the CMS. And learning all the tools to query and bring content together is often the most challenging part of understanding a CMS. It usually represents a level of &amp;ldquo;mastery&amp;rdquo; of that CMS.&lt;/p&gt;
&lt;p&gt;Most CMSs try to implement aggregation tools visually in some kind of UI. The zenith of this approach might have been &lt;a href="/tech/cmsui/drupal-query-builder-2011/"&gt;Drupal&amp;rsquo;s various query builders&lt;/a&gt;, as part of the &lt;a href="https://www.drupal.org/docs/8/core/modules/views"&gt;Drupal Views&lt;/a&gt; module (which I think is in the core now). In my (ahem) view, this was the outer fringe of where you could go with a UI. Drupal Views almost constituted its own software.&lt;/p&gt;
&lt;p&gt;Admittedly, Views included a templating layer, which added complexity, but it&amp;rsquo;s still trying to encapsulate a very complicated layer of query logic into a clickable UI.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;I&amp;rsquo;ll be forever grateful to Lucas de Costa for introducing me to the phrase &amp;ldquo;SQL by Mouse&amp;rdquo; in &lt;a href="https://briefer.cloud/blog/posts/self-serve-bi-myth/"&gt;this article&lt;/a&gt; about writing query code in their dashboard product: &lt;a href="https://briefer.cloud/"&gt;Briefer&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;…some non-technical people are just scared of any monospaced writing with syntax highlight, so [a UI] might be a good first step.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I first referenced that post in &lt;a href="https://www.linkedin.com/posts/deane_last-week-i-made-a-post-about-how-im-contemplating-activity-7208915589346574336-wraJ/"&gt;a video showing a very weird text adventure system&lt;/a&gt; I wrote in Optimizely which also includes some dynamic &amp;ldquo;code as content&amp;rdquo; functionality.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;I&amp;rsquo;ve had a running love affair with query languages, especially when it comes to CMS. I&amp;rsquo;ve always been curious if it might be easier to simply train editors on how to write some light &amp;ldquo;code&amp;rdquo; rather than fiddling with a complicated UI.&lt;/p&gt;
&lt;p&gt;To this end, I&amp;rsquo;ve tried several times to implement content query languages in text. I like text queries because they&amp;rsquo;re precise and they can be easily stored as content (indeed, they&amp;rsquo;re serialized by definition).&lt;/p&gt;
&lt;p&gt;A query is, in some ways, a content object. It should probably be versioned and have permissions and such. And if you put it in a reusable component, then you have this thing you can move around that will magically produce other content.&lt;/p&gt;
&lt;p&gt;(OMG… it&amp;rsquo;s like a… &lt;em&gt;prompt&lt;/em&gt;… but more on that below…)&lt;/p&gt;
&lt;p&gt;My first attempt was in Episerver, about a decade ago. I did this brutally simply: on save, I picked a set of key properties to flatten into a simple database table. Then I let my customer embed a component that contained a query against that table. It got the matching content IDs from my supplemental SQL table, then looked them up through the traditional API in the context of the visitor (thereby complying with permissions and personalization and languages and all that).&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;17 years ago, I also danced around the idea of using the CMS API to &amp;ldquo;filter&amp;rdquo; a list of content obtained elsewhere: &lt;a href="/tech/blog/give-me-api-for-filtering-content/" data-no-index&gt;Give Me an API for Filtering Content&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;My customer could embed components in rich text. The component had a field for &amp;ldquo;query&amp;rdquo; that would look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type = 'article' AND category = 'agriculture'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;rsquo;s literally just the WHERE clause of a SQL statement that ran against a simple, flat table that was indexed well. Simple tables make sense to users because they&amp;rsquo;re all familiar with Excel &amp;ndash; rows and columns are clear and ambiguous.&lt;/p&gt;
&lt;p&gt;I wrote about that project a bit here:&lt;/p&gt;



  

&lt;div class="hero no-words"&gt;
    &lt;div class="info"&gt;
        &lt;p class="title"&gt;&lt;a href="/tech/blog/supplemental-indexing-in-content-management/"&gt;Supplemental Indexing in Content Management&lt;/a&gt;&lt;/p&gt;
        &lt;p&gt;Having a separate index of CMS content, structured for optimal querying, can help you solve a lot of sticky problems.&lt;/p&gt;
    &lt;/div&gt;
    
    &lt;img src="/hero/83DDCD8DE909242606A6DD4EE9DD42AE/image.jpg"/&gt;
    
&lt;/div&gt;
&lt;!-- 83ddcd8de909242606a6dd4ee9dd42ae --&gt;

&lt;p&gt;More recently, I wrote a variation of SQL that I called &amp;ldquo;TreeQL&amp;rdquo; that was designed for a hierarchical content structure. You could write something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT descendants OF /news/ ORDER BY depth
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;My code (it&amp;rsquo;s &lt;a href="https://github.com/deanebarker/treeql-parser"&gt;on GitHub&lt;/a&gt;) simply parsed that using &lt;a href="https://github.com/sebastienros/parlot/blob/main/README.md"&gt;Parlot&lt;/a&gt; (a really great &lt;a href="/tech/parlot/parser-combinators/"&gt;parser combinator&lt;/a&gt; library) into a C# object, using which you could implement your own search logic. I have &lt;a href="/video/content-cloud-endpoint-demo/"&gt;a video of me using that&lt;/a&gt; in an Episerver add-on here.&lt;/p&gt;
&lt;p&gt;For Episerver, I used the object to convert it to LINQ, which was slow. If I took it further, I would have used Opti Find or Opti Graph or something.&lt;/p&gt;
&lt;p&gt;And lately, I&amp;rsquo;ve been fiddling around with another query paradigm using a &amp;ldquo;filter&amp;rdquo; model. In this model, the editor writes a series of directives that progressively carve a subset out of a larger dataset.&lt;/p&gt;
&lt;p&gt;You start with the entire set of records. You can &lt;code&gt;include&lt;/code&gt; records to establish a subset, then &lt;code&gt;include&lt;/code&gt; records from &lt;em&gt;that&lt;/em&gt; subset, or &lt;code&gt;exclude&lt;/code&gt; records from it (those essentially do the exact same thing, just from opposite directions). Each &lt;code&gt;include&lt;/code&gt; or &lt;code&gt;exclude&lt;/code&gt; directive operates on the result of the prior one.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-plaintext"&gt;include: parent = /news/ or /events/
include: type = article
include: year &amp;gt; 2020

exclude: internal is true

sort: date descending
take: 10
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, if you&amp;rsquo;re a developer, you might be looking at this with some level of condescension. I get that. &lt;em&gt;But this is not for you&lt;/em&gt; &amp;ndash; this is for non-technical editors who know what they want in very basic, logical terms.&lt;/p&gt;
&lt;p&gt;Your could even make it simpler by rolling up some of the different queries into dedicated directives. Like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-plaintext"&gt;path:  /news/ or /events/
type:  article
since: 2020-01-01
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&amp;rsquo;ve found that when designing syntax, you sort of have to work in metaphors. And the metaphor of a &amp;ldquo;pipeline&amp;rdquo; that &amp;ldquo;filters&amp;rdquo; is something that non-technical people seem to understand well.&lt;/p&gt;
&lt;p&gt;These are all examples of what are formally known as &amp;ldquo;domain-specific languages&amp;rdquo; (DSLs), or colloquially as &amp;ldquo;little languages.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Some concepts that are very basic developers to are just too abstract from editors &amp;ndash; branching, variables, looping, etc. Editors like &amp;ldquo;straight line&amp;rdquo; execution, so those are a step too far. But how far is too far?&lt;/p&gt;
&lt;p&gt;Well, that&amp;rsquo;s the trick, really…&lt;/p&gt;
&lt;p&gt;Anyway, my first swing at translating this to code was insanely inefficient, swapping it in and out of memory. But then I realized that you can use &lt;a href="https://learnsql.com/blog/what-is-common-table-expression/"&gt;Common Table Expressions&lt;/a&gt; (in SQLite, specifically, though they exist in most SQL databases) to distill this directly to SQL:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;WITH
all AS (SELECT * FROM articles),
x AS (SELECT * FROM all WHERE (parent = '/news/' OR parent = '/events/') = true),
y AS (SELECT * FROM x WHERE (year &amp;gt; 2020) = true),
z AS (SELECT * FROM y WHERE (internal = 1) = false)
SELECT * FROM z
ORDER BY date DESC
LIMIT 10
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;CTEs are very fast &amp;ndash; with a few thousand records and &lt;em&gt;zero&lt;/em&gt; indexing, that query will run on my laptop in about 10ms. And derived fields will cascade &amp;ldquo;down&amp;rdquo; the list, so if I create some calculated field in the base query (the first one) and name that field, the users can refer to it just like it was in the underlying data, without ever knowing it was invented.&lt;/p&gt;
&lt;p&gt;Of course, the translation to SQL assumes a simple relational table model, but as I mentioned above, I&amp;rsquo;ve used supplemental indexing to effectively &amp;ldquo;fake&amp;rdquo; this on-the-fly, alongside my CMS repository. (SQLite in-memory databases are really handy for this &amp;ndash; copy in all the data on startup in a few seconds, then keep it updated; rebuild on a schedule just to keep it accurate.)&lt;/p&gt;
&lt;p&gt;Again, rows and columns make sense to non-developers, so the mental model is clear. If your data isn&amp;rsquo;t rows and columns, &lt;em&gt;create a representation of it that is&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If you don&amp;rsquo;t have an underlying table, you&amp;rsquo;d just need some other type of translation into whatever API you do have.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;There&amp;rsquo;s also a very advanced implementation of the &amp;ldquo;filter and piping&amp;rdquo; model for SQL called &lt;a href="https://prql-lang.org/"&gt;PRQL&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;As with any language design, the trick here is to assume as much as possible.&lt;/p&gt;
&lt;p&gt;By default, I&amp;rsquo;m assuming the table and the fields. I&amp;rsquo;m removing any concept of joins, and I&amp;rsquo;m replacing the concept of parenthetical WHERE clauses with a modeling of &amp;ldquo;whittling down&amp;rdquo; the entire dataset progressively.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;For more on assumption in language design, see the section on &amp;ldquo;Fun with Language Design&amp;rdquo; (towards the bottom) in this article: &lt;a href="/tech/blog/custom-elements-markdown/" data-no-index&gt;The Joy of Mixing Custom Elements, Web Components, and Markdown&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;The way I have this currently written, the directives are extensible, so you could wrap them around your own content model.&lt;/p&gt;
&lt;p&gt;I work at &lt;a href="https://staffbase.com//"&gt;Staffbase&lt;/a&gt;, and here&amp;rsquo;s what it might look like to aggregate multiple news channels if I wanted to insert a list of news in a page (this would be wrapped in a &amp;ldquo;widget&amp;rdquo; you could drop into text from the UI):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-plaintext"&gt;channel: 'CEO Blog' or 'Marketing Minutes' or 'New HQ'
type: social

filter-out: text contains 'confidential'
filter-out: audiences includes 'External Contractors'

sort: date descending
limit: 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(To be clear, this is a little contrived, because we do have a pre-built widget that does roughly this same thing. But there are always edge cases that any pre-built thing wouldn&amp;rsquo;t cover.)&lt;/p&gt;
&lt;p&gt;The thing I wrote above about assumptions is even more true for specific implementations. Given that I know the underlying model and purpose of the content, I can write &lt;code&gt;channel&lt;/code&gt; and &amp;lsquo;type&amp;rsquo; directives specific to the content. And with any implementation, I can change directive names &amp;ndash; like &lt;code&gt;filter-out&lt;/code&gt; rather than &lt;code&gt;exclude&lt;/code&gt; &amp;ndash; to fit what my editors will understand best.&lt;/p&gt;
&lt;p&gt;Now, by this point, you might be screaming: &lt;em&gt;but this is what we have APIs for!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I get that. But the difference with a &amp;ldquo;query language&amp;rdquo; if that it exists in text. And this matters. Editors can write text in an input box. You can serialize text and store it. You can provide a bunch of content-like services to text, which you really can&amp;rsquo;t do to API code that runs in the native computational process of the system.&lt;/p&gt;
&lt;p&gt;I wish more vendors would implement this.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sanity.io/"&gt;Sanity&lt;/a&gt; has something called &lt;a href="https://www.sanity.io/docs/content-lake/how-queries-work"&gt;Graph‑Relational Object Queries&lt;/a&gt; (with the fantastic acronym of &amp;ldquo;GROQ&amp;rdquo;), which is this exact concept. It looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;*[_type == 'movie' &amp;amp;&amp;amp; releaseYear &amp;gt;= 1979] | order(releaseYear) {
  _id, title, releaseYear
}[0…100]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;rsquo;s a little complex, but I&amp;rsquo;m quite sure it&amp;rsquo;s powerful. And kudos to them for providing the option.&lt;/p&gt;
&lt;p&gt;And then, of course, there&amp;rsquo;s &lt;a href="https://en.wikipedia.org/wiki/GraphQL"&gt;GraphQL&lt;/a&gt;, which is the closest thing we have to a standard in the content space. It looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;query {
  empireHero: hero(episode: EMPIRE) {
    name
  }
  jediHero: hero(episode: JEDI) {
    name
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&amp;rsquo;m happy that there&amp;rsquo;s some kind of standard, but GraphQL is verbose to write (&lt;em&gt;so&lt;/em&gt; many braces…), and it&amp;rsquo;s really designed for two things in particular:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Hiding the underlying implementation and letting you design your own model facade at the query level&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Careful specification of output format, specifically to avoid &amp;ldquo;over-fetching&amp;rdquo; and return only what you need (partially for network efficiency when delivering directly to clients)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Part of what I&amp;rsquo;m trying to find is the happy balance between expressiveness/power and approachability.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been encouraged recently by what the research firm &lt;a href="https://www.inkandswitch.com/"&gt;Ink and Switch&lt;/a&gt; has been calling &amp;ldquo;&lt;a href="https://www.inkandswitch.com/essay/malleable-software/"&gt;malleable software&lt;/a&gt;.&amp;rdquo; This is an emerging term to refer to software that can be modified by the end user. Their definition is more for end user software, rather than CMS software with a group of editors, but I love how the concept of software as an amorphous concept that should wrap around the user&amp;rsquo;s needs is starting to emerge.&lt;/p&gt;
&lt;p&gt;And, of course, what will AI do to all of this? Will AI eliminate the need for explicit query languages entirely?&lt;/p&gt;
&lt;p&gt;…maybe? While we might just store a prompt &amp;ndash; &amp;ldquo;Give me the last 10 articles about the new headquarters project…&amp;rdquo; &amp;ndash; that&amp;rsquo;s still a &amp;ldquo;query&amp;rdquo; at some level. It&amp;rsquo;s still serialized to text and writable by an editor. And you would need some understanding of how it will be interpreted to get what you want out of it &amp;ndash; with experience, you&amp;rsquo;ll come to understand how to get the machine to give you what you want.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;I&amp;rsquo;ve been tracking &lt;a href="/other/fsd-flights/"&gt;the direct flights out of the Sioux Falls airport&lt;/a&gt; for about six weeks now.&lt;/p&gt;
&lt;p&gt;Every query for that report was written by ChatGPT. I uploaded the entire SQLite database and just told it what I wanted to know. It runs in a batch process and writes out static HTML files, so I didn&amp;rsquo;t care much about performance or optimization.&lt;/p&gt;
&lt;p&gt;See &lt;a href="/tech/blog/cms-vibe-experiment/" data-no-index&gt;How Should a CMS Repository Understand the Content Within It?&lt;/a&gt; for a discussion of using a CMS repository as context for AI&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;The problem I see right now with this approach is that AI is non-derivative, and it can give you a lot of different variations of solutions for the same problem &amp;ndash; it&amp;rsquo;s currently the opposite of &amp;ldquo;precise.&amp;rdquo; You would need to turn the &lt;a href="https://learn.microsoft.com/en-us/ai-builder/prompt-modelsettings#temperature"&gt;temperature setting&lt;/a&gt; way down, I think, to ensure some consistency in how it&amp;rsquo;s interpreting queries. When it comes to querying content, the fuzziness of AI is just not appropriate.&lt;/p&gt;
&lt;p&gt;So, there are lots of questions and experimentation here, but few hard-and-fast answers. I&amp;rsquo;ve implemented a few of these for customers, but I&amp;rsquo;m still waiting on the perfect opportunity to take it a step further.&lt;/p&gt;
&lt;p&gt;That opportunity will be a specific combination of content domain, editor experience, CMS capabilities, and situational requirements.&lt;/p&gt;
&lt;h2&gt;Postscript: Samples&lt;/h2&gt;
&lt;p&gt;I started playing around a bit with my query tool that I explained above. Here are some samples. These are being run in real-time against the SQLite database running behind this website (the content is in Markdown, but I have a &lt;a href="/tech/blog/necessity-of-content-index/"&gt;content index&lt;/a&gt; in SQL for navigation and such).&lt;/p&gt;
&lt;p&gt;This site runs on a block-based templating system, so I wrapped this functionality up in a block and embedded three of them below, complete with some debug information.&lt;/p&gt;
&lt;p&gt;As I mentioned above, CTEs are &lt;em&gt;really&lt;/em&gt; fast, and the backing table is pretty well-indexed. At this writing, it has 9,328 rows.&lt;/p&gt;
&lt;p&gt;Here are the last three blog posts &amp;ndash; &lt;/p&gt;
&lt;div class="trevor-output"&gt;&lt;ul class="trevor-results"&gt;&lt;li&gt;&lt;a href="/tech/blog/platformization/" rel="trevor"&gt;AI and the Forced Platform-ization of Enterprise Software&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="/tech/blog/low-code-value/" rel="trevor"&gt;Low Code: Short Term vs. Long Term Value&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="/tech/blog/vibe-lessons/" rel="trevor"&gt;Lessons Learned from Vibe-Coding a Configuration Parser&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;dl class="context"&gt;&lt;dt&gt;Parse&lt;/dt&gt;&lt;dd&gt;0ms&lt;/dd&gt;&lt;dt&gt;Query&lt;/dt&gt;&lt;dd&gt;8ms&lt;/dd&gt;&lt;/dl&gt;&lt;pre class="trevor-debug"&gt;include: path starts /tech/blog/
sort: date desc
take: 3&lt;/pre&gt;&lt;pre class="trevor-debug"&gt;WITH
a AS (SELECT * FROM records),
b AS (SELECT * FROM a WHERE (key LIKE '/tech/blog/%') = true)
SELECT * FROM b
ORDER BY  date desc
LIMIT  3
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;James Bond-related books that I own. This uses a custom SQLite function that I wrote to find an element in a JSON array stored as a field value.&lt;/p&gt;
&lt;div class="trevor-output"&gt;&lt;ul class="trevor-results"&gt;&lt;li&gt;&lt;a href="/library/titles/life-50-years-james-bond/" rel="trevor"&gt;50 Years of James Bond&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="/library/titles/blood-fever/" rel="trevor"&gt;Blood Fever&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="/library/titles/brokenclaw/" rel="trevor"&gt;Brokenclaw&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="/library/titles/by-royal-command/" rel="trevor"&gt;By Royal Command&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="/library/titles/carte-blanche-james-bond/" rel="trevor"&gt;Carte Blanche&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;dl class="context"&gt;&lt;dt&gt;Parse&lt;/dt&gt;&lt;dd&gt;0ms&lt;/dd&gt;&lt;dt&gt;Query&lt;/dt&gt;&lt;dd&gt;17ms&lt;/dd&gt;&lt;/dl&gt;&lt;pre class="trevor-debug"&gt;include: path starts /library/titles/
include: tagged with james-bond
sort: title
take: 5&lt;/pre&gt;&lt;pre class="trevor-debug"&gt;WITH
a AS (SELECT * FROM records),
b AS (SELECT * FROM a WHERE (key LIKE '/library/titles/%') = true),
c AS (SELECT * FROM b WHERE (json_has_element(tags, 'james-bond')) = true)
SELECT * FROM c
ORDER BY  title
LIMIT  5
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Content containing the word &amp;ldquo;gumby.&amp;rdquo; (I don&amp;rsquo;t know why I use this word, but apparently I do.) This uses SQLite&amp;rsquo;s full-text indexing system.&lt;/p&gt;
&lt;p&gt;Just to prove a point, I filtered out this post (the one you&amp;rsquo;re reading right now) using an injected variable. Just before I parse the commands, I run the source through a &lt;a href="/tech/fluid/"&gt;Fluid&lt;/a&gt; execution, replacing the variable &lt;code&gt;{{ doc.path }}&lt;/code&gt; with the path to this document. (It&amp;rsquo;s a full templating engine. You could do lots of stuff here.)&lt;/p&gt;
&lt;p&gt;(Worth saying: that&amp;rsquo;s another reason why text is great &amp;ndash; you can manipulate it easily.)&lt;/p&gt;
&lt;p&gt;This is kind of handy, because you could embed the same script on lots of pages (or in a template), and it would provide varied output because its effective source would be contextual to the data from the page on which it&amp;rsquo;s executing.&lt;/p&gt;
&lt;div class="trevor-output"&gt;&lt;ul class="trevor-results"&gt;&lt;li&gt;&lt;a href="/tech/blog/making-your-fields-do-their-own-dirty-work/" rel="trevor"&gt;Making Your Fields Do Their Own Dirty Work&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="/tech/blog/dqm/" rel="trevor"&gt;Managing Service and Content Quality Over Time&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="/other/mkkbb/spoofs/" rel="trevor"&gt;You Only Laugh Twice: A Concise History of James Bond Spoofs&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;dl class="context"&gt;&lt;dt&gt;Parse&lt;/dt&gt;&lt;dd&gt;0ms&lt;/dd&gt;&lt;dt&gt;Query&lt;/dt&gt;&lt;dd&gt;26ms&lt;/dd&gt;&lt;/dl&gt;&lt;pre class="trevor-debug"&gt;include: text matches gumby
exclude: path is not {{ doc.path }}
sort: title&lt;/pre&gt;&lt;pre class="trevor-debug"&gt;WITH
a AS (SELECT * FROM records),
b AS (SELECT * FROM a WHERE ((key in (SELECT path FROM search WHERE text MATCH 'gumby'))) = true),
c AS (SELECT * FROM b WHERE (key = '/tech/blog/content-querying/') = false)
SELECT * FROM c
ORDER BY  title
&lt;/pre&gt;&lt;/div&gt;

&lt;section class="postscript"&gt;
&lt;hgroup class="ps"&gt;
&lt;h2&gt;Update: GROQ by Sanity&lt;/h2&gt;

&lt;/hgroup&gt;

&lt;p&gt;With some help from &lt;a href="https://www.linkedin.com/in/knutmelvaer/"&gt;Knut Melvær&lt;/a&gt;, I did play around with &lt;a href="https://sanity.io/"&gt;Sanity&amp;rsquo;s&lt;/a&gt; GROQ a bit. It&amp;rsquo;s actually quite expressive and simple to pick up.&lt;/p&gt;
&lt;p&gt;Consider this query:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-plaintext"&gt;*[&amp;quot;timeline-computing-history&amp;quot; in timelines[]._ref] | order(dateRange.startDate)
{
  &amp;quot;id&amp;quot;:_id,
  title,
  &amp;quot;desc&amp;quot;:shortDescription,
  &amp;quot;date&amp;quot;:dateRange.startDate,
  &amp;quot;timelines&amp;quot;:timelines[]-&amp;gt;{&amp;quot;id&amp;quot;:_id,title}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;rsquo;s pulling content from a POC that Knut (graciously) threw together in response to this post: &lt;a href="/tech/blog/timeline-cms/" data-no-index&gt;CMS for Historical Timelines&lt;/a&gt;. I actually didn&amp;rsquo;t need anything but the top line. Everything below it is just a &amp;ldquo;projection&amp;rdquo; to shape the results.&lt;/p&gt;
&lt;p&gt;And kudos to Sanity for some great documentation. &lt;a href="https://www.sanity.io/docs/content-lake/query-cheat-sheet"&gt;This page alone&lt;/a&gt; is worth volumes of traditional documentation.&lt;/p&gt;

&lt;/section&gt;</description>
      <pubDate>Thu, 4 Sep 2025 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/content-querying/</guid>
    </item>
    <item>
      <title>My Own WTF, or How to Not Handle URL Redirects</title>
      <link>https://live.deanebarker.net/tech/blog/404-wtf/</link>
      <description>&lt;p&gt;About 10 years ago, I did a CMS migration for a large health system.&lt;/p&gt;
&lt;p&gt;With the new CMS, they were changing the URLs of about 100,000 pages, so we did a standard redirection strategy. We had the old URL stored with the new content, so on app startup, we iterated all the content and loaded a URL lookup table into memory &amp;ndash; &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Old URL → New URL
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When a 404 comes in, look for the old URL, send a redirect to the new URL. (I wrote quite a bit about that strategy here: &lt;a href="/tech/blog/patterns-in-url-redirection-after-cms-migrations/" data-no-index&gt;Patterns in URL Redirection After CMS Migrations&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;This is all pretty standard. Even 100,000 key/value pairs doesn&amp;rsquo;t take a lot of space in memory, and creating that structure took about 90 seconds on app startup. It was done in the background, asynchronously, so it would become available just over a minute after the site came online. Given that the app restarted pretty rarely (once a month, maybe?), this was fine.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;In hindsight, I should have stored this persistently instead of in memory. The URL lookup data wasn&amp;rsquo;t going to change, so there was no reason to not write this lookup to a file or a SQLite database or something.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;However, I made a critical mistake: I didn&amp;rsquo;t actually start the process on app startup. For whatever reason, I triggered the creation of the lookup table when the first 404 came in.&lt;/p&gt;
&lt;p&gt;The first 404 would look for the data in memory, and if it didn&amp;rsquo;t exist, it would then kick of the 90-second process to create it. I figured this was pretty efficient.&lt;/p&gt;
&lt;p&gt;What I didn&amp;rsquo;t realize is that this site got a &lt;em&gt;lot&lt;/em&gt; of traffic. And in the 90 seconds after that initial 404 started the process, &lt;em&gt;a lot of 404s would come in&lt;/em&gt;. The site was big and had been online for a long time, so it was constantly being pelted with 404s. I&amp;rsquo;m sure most of this traffic was from crawlers trying to access the accumulated history of dozens of URL changes over the course of a couple decades of existence.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Fully 20 years ago: &lt;a href="/tech/blog/crawlers-are-stupid/" data-no-index&gt;Crawlers are Stupid&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;This means that for 90 seconds (theoretically) every single 404 kicked off that same process. Until that first process completed and the lookup table was in memory, all those 404s wouldn&amp;rsquo;t find the data, and they would dutifully set about creating it.&lt;/p&gt;
&lt;p&gt;We launched the new site, and it mysteriously kept failing. Seconds after launch, the web server process would go ballistic until it stopped responding, at which point we&amp;rsquo;d fall back to the old environment. I never checked, but at some point, I&amp;rsquo;m sure we had &lt;em&gt;hundreds&lt;/em&gt; of threads trying to iterate all the content and create the same lookup table in memory.&lt;/p&gt;
&lt;p&gt;This happened on three consecutive days. Each day, I had &amp;ldquo;fixed&amp;rdquo; something which I suspected was the problem. Each day, I was wrong.&lt;/p&gt;
&lt;p&gt;Needless to say, the client was just &lt;em&gt;thrilled&lt;/em&gt; with all of this…&lt;/p&gt;
&lt;p&gt;Confusingly, there was no excess memory usage, because as each process completed, it overwrote the table that was there, so we only ever got the one table in memory &amp;ndash; we just had hundreds of processes overwriting it again and again.&lt;/p&gt;
&lt;p&gt;In theory, it would eventually resolve itself, because when the first process would finally write the data, the process wouldn&amp;rsquo;t be started again (because new 404s would find it in memory), but we never got to the end of that chain of processes, because the server would straight up die before that point. I suppose the server would have chewed through it eventually (90 seconds turning into 90 minutes or whatever), but we could never wait that long.&lt;/p&gt;
&lt;p&gt;Since the problem seemed to be CPU-bound, I started looking for infinite recursion somewhere, and I wasn&amp;rsquo;t finding it.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t remember when I figured out what was going on, but when I did, I felt like the sky fell in on me. Realizing the sheer stupidity of what I did was epic.&lt;/p&gt;
&lt;p&gt;I believe I got very quiet. I think I laid my head on my desk for a long period of time.&lt;/p&gt;
&lt;p&gt;I fixed it by setting an &amp;ldquo;in process&amp;rdquo; flag when the first process started, and just returning an actual 404 and bailing out for every 404 that came in during that 90-second window so that only one background process was ever running at a time. There were undoubtedly better solutions for fixing and improving this, but it needed to be done in a hurry, so that&amp;rsquo;s what I did.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a perfect demonstration that you need to test error conditions like &lt;em&gt;lots&lt;/em&gt; of 404s. Consider that &amp;ndash; &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The average load test would have likely only tested URLs that existed, so it would have never triggered this&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even if my load test included a single 404 (it didn&amp;rsquo;t…), the problem would have never surfaced on a single 404 (indeed, that was the exact situation I had coded it for)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To be fair to me, these two points made it a non-trivial thing to discover. What test would you put in place for this?&lt;/p&gt;
&lt;p&gt;The only thing I can think of is that I could have pulled web logs from the existing site and found some way to &amp;ldquo;replay&amp;rdquo; them on the new site. That would be the best way to simulate real traffic (indeed, it wouldn&amp;rsquo;t even be &amp;ldquo;simulated&amp;rdquo; at that point &amp;ndash; it would be the &lt;em&gt;actual&lt;/em&gt; traffic).&lt;/p&gt;
&lt;p&gt;But, clearly, I made multiple mistakes in how I coded this in the first place. It was not my finest moment.&lt;/p&gt;


&lt;section class="postscript"&gt;
&lt;hgroup class="ps"&gt;
&lt;h2&gt;Update&lt;/h2&gt;

&lt;p class="date"&gt;Added on &lt;time datetime="2025-08-28"&gt;August 28, 2025&lt;/time&gt;&lt;/p&gt;

&lt;/hgroup&gt;

&lt;p&gt;I sent this to the client developer that was on the project all those years ago. He responded:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[pats Deane on back] We&amp;rsquo;ve forgiven you. It&amp;rsquo;s time to forgive yourself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;/section&gt;</description>
      <pubDate>Wed, 27 Aug 2025 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/404-wtf/</guid>
    </item>
    <item>
      <title>CMS for Historical Timelines</title>
      <link>https://live.deanebarker.net/tech/blog/timeline-cms/</link>
      <description>&lt;p&gt;I&amp;rsquo;ve often said that the last thing the world needs is another CMS. Yet, here we go…&lt;/p&gt;
&lt;p&gt;I read a lot of history (literally five minutes ago, I finished &lt;a href="/library/titles/band-played-on/"&gt;&lt;em&gt;And the Band Played On&lt;/em&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;To understand history, nothing beats a timeline.&lt;/p&gt;
&lt;p&gt;They help me put things into context. I like seeing when something began, all the different phases it went through, and what their relative timespan was. This is what it takes for me to sort something out in my head.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve often thought about coming up with a software system to manage timelines &amp;ndash; a &amp;ldquo;CMS for history,&amp;rdquo; if you will. This post is an exploration of that idea, along with a bunch of supporting links and random stuff I&amp;rsquo;ve gathered over the years.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Note that this is not a tool for timeline &lt;em&gt;visualization&lt;/em&gt;. There are lots of tools to &lt;em&gt;display or visualize&lt;/em&gt; timelines &amp;ndash; some really amazing ones, in fact. But I&amp;rsquo;m more interested in a system to manage the data backend of these systems, so that it could slice and dice this data and output it in different ways, likely using some of those same visualizations.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;My goal would be to find some data model that could represent the passage of time, the events that occur within it, the geographies associated with those events, and actors that were involved in them. With a solid model behind this, you could visually represent it in different ways, query it around the involvement of various entities, and even overlay different timelines to see where they intersect.&lt;/p&gt;
&lt;p&gt;Some random use cases:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Learning.&lt;/strong&gt; This is the primary use case &amp;ndash; to be able to more clearly visualize the passage of time and the events that occur within it. In particular, there are some historical threads I&amp;rsquo;ve been studying on and off for years. I&amp;rsquo;d like to start building and maintaining timelines of them all.&lt;/li&gt;
&lt;/ol&gt;
&lt;aside class="in-list"&gt;&lt;p&gt;Example: I have a two-hour presentation on the history of the internet. &lt;a href="https://www.dropbox.com/scl/fi/v4ycs3dlf5oanz5eawc4z/The-Invention-of-the-Internet-v4-Augie-2015.pptx?rlkey=kljdsrcscmnp8xwcurmdq8wca&amp;amp;st=5tisfu53&amp;amp;dl=0"&gt;Here&amp;rsquo;s the deck&lt;/a&gt; (which I haven&amp;rsquo;t touched for 10 years). I&amp;rsquo;d like to turn this into a data-sourced timeline that I could flesh out a little more.&lt;/p&gt;
&lt;/aside&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Event planning and coordination.&lt;/strong&gt; I&amp;rsquo;ve been involved in some conference organization which required planning for specific things to occur, down to the minute in some cases &amp;ndash; &amp;ldquo;At 8:32 a.m., Person X has to be Location Y,&amp;rdquo; etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Event reconstruction.&lt;/strong&gt; This is a derivative of #1, but consider a crime scene or accident investigation that needs to recreate several places, people, and events across time.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;aside class="in-list"&gt;&lt;p&gt;I&amp;rsquo;ve always loved a website called &amp;ldquo;&lt;a href="https://seventeenpeople.com/"&gt;Seventeen People&lt;/a&gt;: A modest tribute to &amp;ndash; and deconstruction of &amp;ndash; my favorite hour of television.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s devoted to a single episode of &lt;em&gt;The West Wing&lt;/em&gt;. It explains and visualizes where every character was at specific times on a 3D map of the titular set.&lt;/p&gt;
&lt;p&gt;I was reminded of this website while watching the recent Netflix show &lt;a href="https://www.netflix.com/title/81005297"&gt;The Residence&lt;/a&gt;, which is a &lt;a href="/huh/rashomonic/" data-no-index&gt;rashomonic&lt;/a&gt; story about one night in the residential wing of the White House. It could use a similar resource.&lt;/p&gt;
&lt;/aside&gt;


&lt;aside class="update"&gt;
  &lt;p&gt;A couple friends read this and gave me some other examples &amp;ndash; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Matt Garrepy showed me &lt;a href="https://www.reddit.com/r/movies/comments/1wxpfc/detailed_explanationtimeline_of_shane_carruths/"&gt;this timeline&lt;/a&gt; from an apparently legendary 2004 movie called &lt;em&gt;Primer&lt;/em&gt;. (There might be &lt;a href="https://www.slashfilm.com/517856/infographic-primer/"&gt;more than one&lt;/a&gt; of these.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark Demeny showed me &lt;a href="https://xkcd.com/657/"&gt;this XKCD cartoon&lt;/a&gt; that maps the timelines of several movies, complete with a joke about &lt;em&gt;Primer&lt;/em&gt;. (Concidentally, I just watched &lt;em&gt;12 Angry Men&lt;/em&gt; last month, and it was fantastic. Ironically, the titular men in that film are trying to reconstruct a… wait for it… &lt;em&gt;timeline&lt;/em&gt;.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;/aside&gt;

&lt;ol start="4"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Research organization.&lt;/strong&gt; Lots of history books, autobiographies, and memoirs involve plotting a lot of observations on a timeline.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Real-life logging.&lt;/strong&gt; Sometimes you need a log of where people are at specific times. Imagine application logging…but for people.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;aside class="in-list"&gt;&lt;p&gt;A friend worked as a security guard when he was younger, and he had to fill out a log which detailed where each person was located at specific times. I remember him using a punch clock thing at various places around the building to verify he had physically been there at that moment.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Last year, in an effort to research this, I made a post to the History Stack Exchange: &lt;a href="https://history.stackexchange.com/questions/68604/is-there-a-formal-ontology-for-documenting-historical-timelines"&gt;Is there a formal ontology for documenting historical timelines?&lt;/a&gt; I wrote, in part:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How do historical researchers organize their notes? If you&amp;rsquo;re researching and documenting the history of…well, anything, are there systems designed to keep track of &amp;ldquo;the timeline&amp;rdquo;?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m reading &amp;ldquo;House of Gucci&amp;rdquo; right now, which is the long, storied history of the Gucci family and company (it was the source material for the 2021 movie starring Lady Gaga). It&amp;rsquo;s incredibly detailed, and I find myself wondering how did the author keep track of it all? It had to be something more elaborate than a bunch of sticky notes on a whiteboard.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The resulting answers were few, but quite good. I learned that techniques used in the study of history are known as &amp;ldquo;historiography&amp;rdquo; (someone edited my post and applied that tag). A few mentioned mentioned some resources (linked below), but honestly, I had trouble conveying the concept of serializing history to a data model. Explaining it to non-CMS people was harder than I thought.&lt;/p&gt;
&lt;p&gt;I ended up adding a music analogy, which I thought worked pretty well:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Musical notation is a codification of a concept (a series of audible sounds). It&amp;rsquo;s a standard protocol, which many people understand, and it&amp;rsquo;s used to serialize music into a recordable form. It&amp;rsquo;s transferable across time and space &amp;ndash; I can write some music down that someone can play later, because we both understand the protocol. Does anything like this exist for historical timelines?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Still, no existing solution jumped out at me.&lt;/p&gt;
&lt;p&gt;Getting down to nuts and bolts, in my head, the data model looks something like this:&lt;/p&gt;



&lt;script src=" https://cdn.jsdelivr.net/npm/mermaid@11.4.1/dist/mermaid.min.js "&gt;&lt;/script&gt;
&lt;script&gt;
mermaid.initialize({
  startOnLoad: true,
  theme: "neutral",
  themeVariables: {
    fontFamily: "Arial, sans-serif",
    fontSize: "1rem",
    fontWeight: "normal"
  }
});
&lt;/script&gt;

&lt;pre class="mermaid"&gt;
erDiagram
    TIMELINE }o--o{ EVENT : "linked to"
    EVENT }o--o{ ACTOR : involves
    LOCATION }o--o{ EVENT : "occurs at"
    EVENT }o--o{ SUBJECT : "affects"
    ACTOR ||..o{ ACTOR : "member of"
    LOCATION ||..o{ LOCATION : "contained within"

    TIMELINE {
        string id
        string name
        int period
        datetime basePeriod
    }
    EVENT {
        string id
        int startPeriod
        int endPeriod
        string status
    }
    SUBJECT {
        string id
        string name
    }
    ACTOR {
        string id
        string parentActorId
        string name
    }
    LOCATION {
        int id
        string parentLocationId
        string name
    }
&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;Timeline&lt;/strong&gt; is the largest object. They&amp;rsquo;re the &amp;ldquo;container&amp;rdquo; through which you view everything.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A Timeline has a &lt;strong&gt;Period&lt;/strong&gt;. This is the minimum period of time the Timeline breaks up into. If you&amp;rsquo;re studying the history of Christianity, it&amp;rsquo;s probably okay to have your period be a full year. If you&amp;rsquo;re reconstructing the meltdown of a nuclear reactor, you might have a period of a second or less.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A Timeline has a &lt;strong&gt;Base Period&lt;/strong&gt;, which is a point in time when the timeline starts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Events&lt;/strong&gt; are assigned to Timelines. An Event could be assigned to more than one Timeline, though maybe that&amp;rsquo;s over-engineering.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Events are placed on a timeline by &lt;strong&gt;Start Period&lt;/strong&gt;, which represents the number of Periods from the Base Period. If your Period is 1 year, your Base Period is 5000 BC, and an event has a Start Period of 6100, then the Event occurred at 1100 AD.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Events can have an &lt;strong&gt;End Period&lt;/strong&gt; as well, for Events that span time. An End Period of NULL meants the event is a point in time, not a span.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Events can be linked to one or more &lt;strong&gt;Actors&lt;/strong&gt;. This is a network of humans that are somehow involved in the Event.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Events can be linked to one or more &lt;strong&gt;Locations&lt;/strong&gt;. This is a network of geospatial locations that are somehow involved in the Event.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Events can be linked to one or more &lt;strong&gt;Subjects&lt;/strong&gt;. This is a network of objects (purposely left vague) that are somehow involved in the Event.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;aside&gt;&lt;p&gt;This seemed very familiar to me when I was writing it down. Sure enough, I basically espoused the exact same model fully 20 years ago in this post: &lt;a href="/tech/blog/functional-design-patterns/" data-no-index&gt;Functional Design Patterns&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have a client right now who needs a Web-based calendar. Now, these things have been done to death. But did anyone… take notes? Did anyone examine how a calendar works from a language-independent standpoint and determine how to model the concept of events occuring across time?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Looking back, that post should probably have been called &amp;ldquo;Content Modeling Design Patterns.&amp;rdquo;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;The concept of putting events on a timeline is neither novel nor complex. However, it gets a little daunting when I bring Actors, Subjects, and Locations into it. In some senses, I am theoretically trying to represent everything on Earth.&lt;/p&gt;
&lt;p&gt;The trick is in the details, of course. How in-depth you decide to go depends very much on what you&amp;rsquo;re trying to model &amp;ndash; what historical concept you want to represent.&lt;/p&gt;
&lt;p&gt;In tossing this idea around, I&amp;rsquo;ve uncovered some interesting things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.historytimeline.com/"&gt;History Timeline&lt;/a&gt; is a software package that purports to do exactly what I&amp;rsquo;m seeking. However, it appears to be client software, optimized for printing, rather than data-driven, server-based software.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Someone on the Stack Exchange question pointed me to &lt;a href="https://linkedevents.org/ontology/"&gt;LODE&lt;/a&gt;, the ontology for Linking Open Descriptions of Events. That comes very close to what I want to do, but it&amp;rsquo;s more a transmission or serialization format. Additionally, it&amp;rsquo;s been around since 2009, and not a lot seems to have happened with it (but maybe that&amp;rsquo;s because it was so good on first draft?). Still, there&amp;rsquo;s a lot to be learned there.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I purchased a &amp;ldquo;World History Timeline&amp;rdquo; from a company called &lt;a href="https://www.worldhistoryandmythology.com/"&gt;World History and Mythology&lt;/a&gt;. I was a little shocked when it was a Microsoft Excel download. Yes, they created a macro-enabled Excel document that they used to plot out the history of the world &amp;ndash; each cell is a period (using my nomenclature from above), and each row is a grouping of some kind. It&amp;rsquo;s a spectacular work, but it was very difficult to browse for me. Honestly, the idea of Excel as a content delivery platform had never occured to me…&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MermaidJS includes a &lt;a href="https://mermaid.js.org/syntax/timeline.html"&gt;timeline option&lt;/a&gt; for a diagram type (clearly, this is simply a visualization format). Here&amp;rsquo;s an example:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;pre class="mermaid"&gt;
timeline
    title Deane's Life
    1971 : Born
    1989 : Graduates High School
    1997 : Graduates College
    1999 : Marries Annie
&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;I even created my own web component to visualize timelines. &lt;a href="/assets/js/timeline.js"&gt;It&amp;rsquo;s here&lt;/a&gt; (css is &lt;a href="/assets/css/timeline.css"&gt;here&lt;/a&gt;) if you want to look at it. It&amp;rsquo;s unfinished, but it looks something like this:&lt;/li&gt;
&lt;/ul&gt;
&lt;time-line style="margin-left: 40px; max-width: calc(100% - 40px);"&gt;
  &lt;time-period start="1962" end="1967"&gt;Period 1&lt;/time-period&gt;
  &lt;time-period start="1967" end="1970"&gt;Period 2&lt;/time-period&gt;
  &lt;time-period start="1970" end="1976"&gt;Period 3&lt;/time-period&gt;
&lt;/time-line&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I found a company called &lt;a href="https://www.historyfactory.com/"&gt;History Factory&lt;/a&gt; that compiles organizational histories for companies. I&amp;rsquo;m not sure if they have any specific or proprietary software that they use for this, but I love the idea that they essentially produce timelines for a living.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There are lots of &amp;ldquo;timeline modules&amp;rdquo; for various CMS platforms. For example, &lt;a href="https://www.commoninja.com/widgets/timeline/craft-cms"&gt;Timeline for Craft CMS&lt;/a&gt; and there are literally &lt;a href="https://wordpress.com/plugins/browse/timeline"&gt;dozens for WordPress&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://timeline.knightlab.com/"&gt;TimelineJS&lt;/a&gt; is a gorgeous open-source visualization tool from the Knight Lab at Northwestern University. It&amp;rsquo;s amazing, but it&amp;rsquo;s a visualization/design tool. It doesn&amp;rsquo;t have a lot of sophistication in the underlying data. (Put another way: the tool I&amp;rsquo;m dreaming of would likely generate data to power TimelineJS installations, among other visualizations.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Here&amp;rsquo;s a spectacular &lt;a href="https://www.oldmapsonline.org/en/history/regions#position=3/42.23/12.81&amp;amp;year=1458"&gt;timeline of world history&lt;/a&gt;. Again, this is a visualization, and I think it&amp;rsquo;s mostly a community project, not a product or platform. But it&amp;rsquo;s beautifully done.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, there&amp;rsquo;s a lot of prior art here. I&amp;rsquo;m trying to thread my desire in between what already exists and figure out where there&amp;rsquo;s overlap.&lt;/p&gt;
&lt;p&gt;Here are some open(-ish) questions I&amp;rsquo;m dealing with &amp;ndash; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Is this a CMS?&lt;/strong&gt; Yes, I think it is. This, of course, is is a bit of a &amp;ldquo;Holy War&amp;rdquo; question, but the Events, Actors, Locations, and Subjects and the relationships between them are unquestionably &amp;ldquo;content.&amp;rdquo; The only novel thing is organizing them in relation to time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Would you build it on top of an existing CMS?&lt;/strong&gt; More than likely, yes. Like I said, the individual entities are content and can benefit from all the services that a CMS already provides.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How is this different than a web calendar?&lt;/strong&gt; A web calendar is always a human-oriented period by default, since it&amp;rsquo;s concerned with scheduling things for humans (consider documenting the Age of Exploration on Google Calendar…). And while they do have some Location, people (Actor), and resource (Subject) functionality, it&amp;rsquo;s only in the context of invitations, so not quite the same thing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What parts of this are…novel?&lt;/strong&gt; Very little, honestly. As I mentioned above, the entities themselves are core content, and the linking from events to Locations, Actors, and Subjects feels like a &lt;a href="https://en.wikipedia.org/wiki/Semantic_triple"&gt;semantic triple&lt;/a&gt; to me. I think I&amp;rsquo;m just needing to add some conceptual &amp;ldquo;overlay&amp;rdquo; for the timeline piece of it. I also like the concept of arbitrary-length Periods that build on the Base Period, but that&amp;rsquo;s just math.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After writing this, I&amp;rsquo;m beginning to think this is just an editorial UI on top of another data management tool… &lt;em&gt;but that&amp;rsquo;s what all CMSs are in the end&lt;/em&gt;, really.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;I remember trying to explain a CMS to a veteran database admin who just wasn&amp;rsquo;t getting it, and I finally resorted to: &amp;ldquo;It&amp;rsquo;s a special database UI that let&amp;rsquo;s you manage words better.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Also, a friend told me once, &amp;ldquo;A CMS is just a relational database management system &lt;em&gt;management system&lt;/em&gt;.&amp;rdquo;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;So, that&amp;rsquo;s it, basically. That&amp;rsquo;s the idea.&lt;/p&gt;
&lt;p&gt;Believe me, the last thing I need to do is create another CMS. But this idea simply will not leave me alone. And &lt;a href="/tech/blog/cms-vibe-experiment/"&gt;some recent research I&amp;rsquo;ve been doing about AI in relation to CMS repositories&lt;/a&gt; makes me think this would be easier to build than I had originally feared.&lt;/p&gt;
&lt;p&gt;Please, someone, talk me out of this.&lt;/p&gt;


&lt;section class="postscript"&gt;
&lt;hgroup class="ps"&gt;
&lt;h2&gt;Update: Timelines for Fiction&lt;/h2&gt;

&lt;p class="date"&gt;Added on &lt;time datetime="2025-08-29"&gt;August 29, 2025&lt;/time&gt;&lt;/p&gt;

&lt;/hgroup&gt;

&lt;p&gt;Earlier in this post I mentioned the book &lt;em&gt;&lt;a href="/library/titles/band-played-on/" data-no-index&gt;And the Band Played on&lt;/a&gt;&lt;/em&gt;, and in the Stack Exchange post, I referred to &lt;em&gt;&lt;a href="/library/titles/house-gucci/" data-no-index&gt;House of Gucci&lt;/a&gt;&lt;/em&gt;. These are both historical re-creations where timelines would be used for accuracy and research.&lt;/p&gt;
&lt;p&gt;However, I just started reading the zombie novel &lt;em&gt;&lt;a href="/library/titles/world-war-z/" data-no-index&gt;World War Z&lt;/a&gt;&lt;/em&gt; (more known for a mostly unrelated movie with Brad Pitt).&lt;/p&gt;
&lt;p&gt;I love the format of this novel. It&amp;rsquo;s a series of &amp;ldquo;interviews&amp;rdquo; with people who survived a zombie war that occurred sometime in the past. It&amp;rsquo;s very &lt;a href="/huh/rashomonic/" data-no-index&gt;rashomonic&lt;/a&gt; in the sense that multiple people talk about the same series of events.&lt;/p&gt;
&lt;p&gt;In just the first 30 pages, for example, I&amp;rsquo;m hearing bits and pieces about the &amp;ldquo;Warmbrunn-Knight Report&amp;rdquo; and &amp;ldquo;Flight 575&amp;rdquo; and some battle in Yonkers. None of this has been fully explained to me yet.&lt;/p&gt;
&lt;p&gt;What this tells me is that &lt;em&gt;there is a timeline to this&lt;/em&gt;. I assume the author wrote a detailed timeline of what actually happened, and then he wrote this novel by figuring out who had access to what information when. So there is a master timeline, and I&amp;rsquo;m just seeing different windows into it.&lt;/p&gt;
&lt;p&gt;I love this use of a timeline. It&amp;rsquo;s something I would have never thought of.&lt;/p&gt;

&lt;/section&gt;</description>
      <pubDate>Tue, 26 Aug 2025 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/timeline-cms/</guid>
    </item>
    <item>
      <title>How Should a CMS Repository Understand the Content Within It?</title>
      <link>https://live.deanebarker.net/tech/blog/cms-vibe-experiment/</link>
      <description>&lt;p&gt;Last week, I wrote about how &lt;a href="/tech/blog/cms-repo-ai/"&gt;CMS repositories would need to adapt to the coming changes around AI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I said this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;My belief is that the CMS of the future will be a set of strict rules around a content model, and that will be &amp;ldquo;beyond the reach&amp;rdquo; of AI. AI engines can do whatever they want with content, so long as they obey the model rules we put in place…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And, more succinctly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A good content repository in the age of AI should be well-defended and well-described.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I decided to play around this with a little bit.&lt;/p&gt;
&lt;p&gt;I wanted to create a &amp;ldquo;CMS repository&amp;rdquo; that was &amp;ldquo;well-defended and well-described.&amp;rdquo; I was wondering if I built out a repository in such a way that it would ensure good data and would be able to describe itself to AI agents, how would that affect my ability to apply AI-generated process agents to it?&lt;/p&gt;
&lt;p&gt;Put another way: if we have a great repository, will we get better results from vibe-coding? Could the repository itself serve as an integral part of the vibe-coding process? Could I be &amp;ldquo;repository-centric,&amp;rdquo; and let AI handle all of the other work?&lt;/p&gt;
&lt;p&gt;So, what repository system did I pick for this experiment?&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/SQLite"&gt;SQLite&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, you can argue that choice, but here was my reasoning:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It&amp;rsquo;s super easy to work with&lt;/li&gt;
&lt;li&gt;SQL databases are, by definition, self-describing; every one of them will serialize the &amp;ldquo;content model&amp;rdquo; to a text file of &lt;a href="https://en.wikipedia.org/wiki/Data_definition_language"&gt;SQL DDL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;There&amp;rsquo;s effectively no &amp;ldquo;space&amp;rdquo; between the data storage and the SQL API, but I&amp;rsquo;ll talk more about this below…&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;My goal was to lock down a database/repository as securely as I could, both to ensure no bad data could get in, but also because a well-defended repository is well-described by definition.&lt;/p&gt;
&lt;p&gt;I came up with idea of a simple &amp;ldquo;Friend CRM&amp;rdquo; &amp;ndash; a database to track my friend&amp;rsquo;s information and allow me to store notes I take about them.&lt;/p&gt;
&lt;p&gt;It was pretty simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A User was a person who could work with the data (more on this below as well…)&lt;/li&gt;
&lt;li&gt;A Person record contained information about a person&lt;/li&gt;
&lt;li&gt;A Note record contained some textual notes about something&lt;/li&gt;
&lt;li&gt;A Note could be associated with one or more Person records&lt;/li&gt;
&lt;li&gt;Both Person and Note records could have Tags&lt;/li&gt;
&lt;li&gt;Every time a Person or Note was inserted, edited, or deleted, a record indicating this would be written to a history table, along with a serialized version of the old data (if applicable)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Very simple. But what I tried to do was codify all the business rules in the database itself, instead of enforcing them at the application or UI layers.&lt;/p&gt;
&lt;p&gt;In general, developers tend to push validation off to the application layer. Our core data storage tends to be &amp;ldquo;loose,&amp;rdquo; and we just filter and strain the data before we try to persist it. Our general practice is we won&amp;rsquo;t attempt a database operation unless we already know the data is good.&lt;/p&gt;
&lt;p&gt;This is fine, but it leaves a &amp;ldquo;gap&amp;rdquo; between the data storage and the content/data model. Our repository will store far bigger data variances than we intend. The theoretical problem is that something could conceivably get &amp;ldquo;under&amp;rdquo; the app layer.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t likely, but imagine if someone got SQL access to your database &amp;ndash; this usually gives developers chills. &amp;ldquo;Use the API!&amp;rdquo; they scream. Anything going directly to the repo is considered potential bad data, because the API is the &amp;ldquo;sheriff.&amp;rdquo;&lt;/p&gt;



&lt;script src=" https://cdn.jsdelivr.net/npm/mermaid@11.4.1/dist/mermaid.min.js "&gt;&lt;/script&gt;
&lt;script&gt;
mermaid.initialize({
  startOnLoad: true,
  theme: "neutral",
  themeVariables: {
    fontFamily: "Arial, sans-serif",
    fontSize: "1rem",
    fontWeight: "normal"
  }
});
&lt;/script&gt;

&lt;pre class="mermaid"&gt;
flowchart LR
    A("Repo")
    B("API &lt;br/&gt; (the only proper gateway)")
    C("Good Incoming Data")
D("Bad Actor&lt;br/&gt;(sneaking in the back door)")
    C--&gt;B--&gt;A
    D--&gt;A
&lt;/pre&gt;

&lt;p&gt;This is pretty normal in modern web apps, but the API becomes effectively where the content model is defined, because that&amp;rsquo;s the finest &amp;ldquo;strainer&amp;rdquo; for the data. If the API is the last word on the type of data than can be persisted, then the core repository system and the API are effectively a bundle that &lt;em&gt;have&lt;/em&gt; to be used together.&lt;/p&gt;
&lt;p&gt;In this case, I was trying to define the database in such an exacting way that it became self-describing and self-defending. The database would both store the data and &lt;em&gt;understand the model intuitively&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;My litmus test was, &amp;ldquo;Could I give someone SQL-level access to this database without fear?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;To this end, I spent a lot of time learning about &lt;a href="https://www.sqlitetutorial.net/sqlite-check-constraint/"&gt;SQLite CHECK constraints&lt;/a&gt;. A simple &amp;ldquo;constraint&amp;rdquo; is a general rule, like &amp;ldquo;NOT NULL.&amp;rdquo; But a CHECK constraint will run defined logic on values and accept or reject them at the database level.&lt;/p&gt;
&lt;p&gt;You can write CHECK constraints to do lots of validation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ensure a number value is above or below a set point or within a range&lt;/li&gt;
&lt;li&gt;Run a REGEX(-ish) pattern on text input to ensure it complies&lt;/li&gt;
&lt;li&gt;Ensure the length of a string is in compliance&lt;/li&gt;
&lt;li&gt;Prevent the deletion of a row until some condition involving another table or value is satisfied&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CHECK(username NOT GLOB '*[^a-z]*')
CHECK(length(password) &amp;gt;= 8)
CHECK(type IN ('user', 'admin'))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When included in a table definition, those CHECK constraints ensure that any value for the username value is comprised only of lower-case letters, the password value is at least eight characters, and the type value is only &amp;ldquo;user&amp;rdquo; or &amp;ldquo;admin&amp;rdquo; and nothing else. If any data comes in that violates those rules, the database will simply refuse to insert or update.&lt;/p&gt;
&lt;p&gt;Additionally, I defined a bunch of triggers. So, for example, when records are deleted from some of the tables, I write the old data it to a &amp;ldquo;history&amp;rdquo; table as a crude form of versioning. Another example: if you try to delete the last record from the junction/interstitial table that links two records, it can cancel that to ensure that no record exists without being linked to something else.&lt;/p&gt;
&lt;p&gt;These are things we normally enforce in the application/API layer, certainly (and sometimes even only in the UI layer, if we&amp;rsquo;re lazy). By moving these &amp;ldquo;back&amp;rdquo; to the data storage, I was hoping that I could &amp;ldquo;collapse&amp;rdquo; the application and data storage layers into one, and therefore make the database self-describing.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Yes, you can absolutely argue with my logic here.&lt;/p&gt;
&lt;p&gt;In some respects, the &amp;ldquo;repo&amp;rdquo; for SQLite are the files on disk and the &amp;ldquo;API&amp;rdquo; is the SQLite runtime and, more specifically, the SQL interpreter executing within it. At some level, every repo eventually just ends up as files on a disk somewhere, and everything in &amp;ldquo;front&amp;rdquo; of that can be considered the API gateway.&lt;/p&gt;
&lt;p&gt;I might have gone too far into the weeds on this. I might be irrational about how much the &amp;ldquo;API&amp;rdquo; and &amp;ldquo;repo&amp;rdquo; should (or already do) constitute the same layer.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;The goal was to be able to serialize this database structure &amp;ndash; which now also happens to be a content model &amp;ndash; to a text file (SQL DDL), and show it to an AI engine and tell it… &amp;ldquo;Build stuff that works with this.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;a href="/tech/blog/images/cms-vibe-experiment/db-creation-script.txt"&gt;Here is the resulting SQL DDL&lt;/a&gt;. It&amp;rsquo;s pretty tight &amp;ndash; even if you have SQL level access, it&amp;rsquo;s hard to get data in there that doesn&amp;rsquo;t work. This is accomplished via a set of CHECK constraints and TRIGGERS working together.&lt;/p&gt;
&lt;p&gt;There were a couple edge cases I couldn&amp;rsquo;t work in. For instance: I wanted to ensure that a Note was assigned to at least one Person. However, there&amp;rsquo;s a problem that you have to insert the Note record before you assigned, so there will be a microsecond when it&amp;rsquo;s not assigned. I consulted ChatGPT and Claude, and they offered some really bizarre ways around this, using the tools SQLite has. (A stored proc would have solved this, but SQLite doesn&amp;rsquo;t have those.)&lt;/p&gt;
&lt;p&gt;But, it&amp;rsquo;s pretty close. It&amp;rsquo;s a very well-defended and consequently well-described repository. By giving an AI engine the SQL DDL, it should understand the data and be able to build stuff with it… hopefully.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;I was texting to my old boss &lt;a href="https://www.linkedin.com/in/kevinsyli/"&gt;Kevin Li&lt;/a&gt; from Optimizely about it, and he made a good observation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The strongest argument is &amp;ldquo;if multiple agents want to create ephemeral content from the same source, one content model makes sure they have some resemblance of a shared consciousness.&amp;rdquo; What you&amp;rsquo;re talking about really is content model as a facet of context engineering. Specifically org wide context engineering, instead of user or task based context engineering&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&amp;rsquo;s a smart way of looking at it: the content model as enduring context.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Now, if I provided this model definition to an AI agent, could it build something good from it?&lt;/p&gt;
&lt;p&gt;This is what me and Claude ended up vibing:&lt;/p&gt;



&lt;pre class="mermaid"&gt;
flowchart TD
    A(Full Web UI)
    B(Web API)
    C(Notifier)
    D(Micro UI)
    E(Static Site Gen)
    G(Batch Process)
    F{{CMS / Repository}}

    F --&gt; A
    F --&gt; B
    F --&gt; G
    B --&gt; C
    B --&gt; D
    F --&gt; E

    style F fill:#FFe5dd,stroke:#DD4085,stroke-width:2px,color:#000,height:3rem;
&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Repo&lt;/strong&gt; is the aforementioned SQLite database&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Full Web UI&lt;/strong&gt; is a Node/Express web app that provides data management functionality&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Web API&lt;/strong&gt; is a REST API that provides remote access with token authentication&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Notifier&lt;/strong&gt; is a Node background process that polls the web API and pops up a Windows notification when a new record is added or changed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Micro UI&lt;/strong&gt; is a small Electron app that provides nothing but the ability to type a note and search for a person to link it to&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Static Site Gen&lt;/strong&gt; is a CLI process that wrote out all the Note records in a journal-like format (one output among many, I would assume)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Batch Process&lt;/strong&gt; is a scheduled process that searches for profanity and replaces it with a sanitized version (&amp;ldquo;f**k&amp;rdquo;, for example)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, I didn&amp;rsquo;t actually need of these &amp;ndash; this was all just a big POC. (I was actually struggling a little to come up with different apps to write.)&lt;/p&gt;
&lt;p&gt;But the point I was trying to prove was that if we have a well-described repository, that will assist AI in creating applications that operate on it. The Queen Bee can craft its own Worker Bees.&lt;/p&gt;
&lt;p&gt;The results were… pretty good. Not perfect, but certainly promising.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;To be clear, the resulting code artifacts are actually a mess &amp;ndash; there are errors all over the place. But I chalk that up to the fact that I&amp;rsquo;m not a very good vibe-coder, and I put very little effort into fine-tuning. It could have been better if I had put more time into it instead of just whipping out a POC.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;However, I did realize pretty quickly that the SQL DDL was just not enough, sadly. The problem is that this described the &lt;em&gt;data&lt;/em&gt; model, but it didn&amp;rsquo;t describe how I wanted to work with it as &lt;em&gt;content&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For example: I gave the SQL database definition to Claude and told it: &amp;ldquo;Make me a Web UI for this.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;And I certainly got a web UI, but it was something like &lt;a href="https://www.phpmyadmin.net/"&gt;phpMyAdmin&lt;/a&gt;. Claude literally gave me a bare-bones UI to manage the tables, columns, and rows. For instance, to link a note to a person, I would need to add the Note, record the resulting ID, find a Person, record their ID, and then manually add the record in the junction/interstitial table. This is not what I wanted.&lt;/p&gt;
&lt;p&gt;But to be fair to Claude, this was a web UI to manage the &lt;em&gt;data&lt;/em&gt; as the database understood it. All the database understands was tables, columns, constraints, and triggers. And Claude did pretty good with this: I was gratified to see that Claude acknowledged all my CHECK constraints &amp;ndash; for example, the apiKey column on the User table can only be (1) NULL, or (2) 32 characters. Claude correctly understood this and  &amp;ldquo;elevated&amp;rdquo; this to the UI level to validate it there.&lt;/p&gt;
&lt;p&gt;However, this clearly still didn&amp;rsquo;t manage the &lt;em&gt;content&lt;/em&gt; in the way a human would want to manage it. And there&amp;rsquo;s no way to do this in the database definition &amp;ndash; tables don&amp;rsquo;t have a place to state what the data &lt;em&gt;means&lt;/em&gt; to a human.&lt;/p&gt;
&lt;p&gt;So I determined that I need to provide that, and I wrote a short narrative explaining how a human would work with the data.&lt;/p&gt;
&lt;p&gt;Here it is, in its entirety:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is a database that is used to track information about people I know, including a running log of notes related to that person.&lt;/p&gt;
&lt;p&gt;There are named users for the database. No one should be able to access the UI for the database until they provide a correct username and password.&lt;/p&gt;
&lt;p&gt;I can enter people&amp;rsquo;s data into the database and tag them (friends, coworkers, relatives, etc.) I can also enter whatever birthday information I have about them: their full birthdate, just the month and year, or just the year.&lt;/p&gt;
&lt;p&gt;I can add free-form notes, and associate the notes with one or more people. I can also tag these notes (phone call, meeting, request, etc). The notes are intended to be Markdown text.&lt;/p&gt;
&lt;p&gt;I can use tags to find all the people or notes that are associated with it.&lt;/p&gt;
&lt;p&gt;Whenever I change or delete a person or a note, the existing information is archived so that I always have a history of what the record was originally.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I tried to stay away from dictating any details of the UI, because this description was about the &lt;em&gt;content model&lt;/em&gt; &amp;ndash; what the data meant, and how I wanted to work with it &amp;ndash; in conceptual terms.&lt;/p&gt;
&lt;p&gt;So my description (my &lt;em&gt;context&lt;/em&gt;) became two-part:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The SQL DDL&lt;/li&gt;
&lt;li&gt;The &amp;ldquo;friendly&amp;rdquo; description of how I wanted to work with the data (as a text file)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Every time I wanted Claude to generate something, I gave it the SQL file, the text file, and then an additional description of what I wanted to build.&lt;/p&gt;
&lt;p&gt;For example, &lt;a href="/tech/blog/images/cms-vibe-experiment/batch-notes.txt"&gt;here&amp;rsquo;s the &amp;ldquo;additional description&amp;rdquo; for the Batch Process&lt;/a&gt;. Using just that and the two other items mentioned above, it seemed Claude could build about anything.&lt;/p&gt;
&lt;p&gt;All builds were done independently of each other. The only thing they had in common were the two files noted above.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;An exception: given the nature of the Micro UI and the Notifer, they actually ran from the Web API, so they both got one more piece of context: &lt;a href="/tech/blog/images/cms-vibe-experiment/web-api-readme.txt"&gt;the README that Claude wrote for the Web API&lt;/a&gt;. Technically, they didn&amp;rsquo;t need the database creation script because they would never see it &amp;ndash; the Web API was their repository, which is the common model for most applications we build.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;In the end, I had a SQLite database file (the &amp;ldquo;Queen Bee&amp;rdquo;), and six folders, each containing an application that operated on the database (the &amp;ldquo;Worker Bees&amp;rdquo;). The worker bees didn&amp;rsquo;t know anything about each other, except for the exception noted.&lt;/p&gt;
&lt;p&gt;Here are some screencaps of what everything looked like (that had a UI or any worth getting an image of):&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;I had Claude generate some random data, and for no particular reason, I said: &amp;ldquo;When generating data, use a spy/espionage theme.&amp;rdquo; The results were fantastic.&lt;/p&gt;
&lt;p&gt;Also, &amp;ldquo;Oikos&amp;rdquo; is a Greek word for &amp;ldquo;relationship&amp;rdquo; or &amp;ldquo;family&amp;rdquo; or something similar. Besides being the name of a brand of yogurt, it&amp;rsquo;s a word my pastor uses often to describe the people around us (&amp;ldquo;our relational world,&amp;rdquo; he says). It&amp;rsquo;s short and easy to remember, so it was a handy name for the project.&lt;/p&gt;
&lt;/aside&gt;





    &lt;div class="image center" style="width:px"&gt;
    &lt;img src="/tech/blog/images/cms-vibe-experiment/dashboard.jpg" loading="lazy" class="allow-magnify" data-part="image" data-value="/tech/blog/images/cms-vibe-experiment/dashboard.jpg" /&gt;
    &lt;p&gt;The Web UI &amp;ldquo;dashboard&amp;rdquo;&lt;/p&gt;

    &lt;/div&gt;





    &lt;div class="image center" style="width:px"&gt;
    &lt;img src="/tech/blog/images/cms-vibe-experiment/person.jpg" loading="lazy" class="allow-magnify" data-part="image" data-value="/tech/blog/images/cms-vibe-experiment/person.jpg" /&gt;
    &lt;p&gt;A person record in the Web UI&lt;/p&gt;

    &lt;/div&gt;





    &lt;div class="image center" style="width:px"&gt;
    &lt;img src="/tech/blog/images/cms-vibe-experiment/web-api.jpg" loading="lazy" class="allow-magnify" data-part="image" data-value="/tech/blog/images/cms-vibe-experiment/web-api.jpg" /&gt;
    &lt;p&gt;The Web/REST API&lt;/p&gt;

    &lt;/div&gt;





    &lt;div class="image center" style="width:px"&gt;
    &lt;img src="/tech/blog/images/cms-vibe-experiment/micro-ui.jpg" loading="lazy" class="allow-magnify" data-part="image" data-value="/tech/blog/images/cms-vibe-experiment/micro-ui.jpg" /&gt;
    &lt;p&gt;The Micro UI as a standalone Electron app&lt;/p&gt;

    &lt;/div&gt;


&lt;p&gt;So, what did I learn from this? Well, it was a little all over the map, but here are some thoughts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Something I already knew: &lt;strong&gt;data and content are not the same thing&lt;/strong&gt;. Databases store &amp;ldquo;data.&amp;rdquo; You need a &amp;ldquo;Contentbase.&amp;rdquo; What the data &lt;em&gt;is&lt;/em&gt; and what the data is &lt;em&gt;intended to be used for&lt;/em&gt; are drastically different concepts, and computers can only reliably assume the former.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I still like the Queen Bee/Worker Bee analogy. Instead of my &amp;ldquo;CMS&amp;rdquo; being one big thing, I have a core repository and an… &lt;strong&gt;ecosystem of applications&lt;/strong&gt; (a constellation? an array?), each doing their own thing, with only the repo in common.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The idea of a &lt;strong&gt;&amp;quot;well-described repository&amp;rdquo; is promising&lt;/strong&gt;. But you&amp;rsquo;ll need to find a way to describe both the mechanics of the data storage and how you want to work with the data. As Kevin mentioned above, this is your context &amp;ndash; your &amp;ldquo;contextual base.&amp;rdquo; You need to be sure that this well-rounded from both a raw data and intentional perspective.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The SQL DDL can be generated real-time, and the same is probably true for other repos as well. It wouldn&amp;rsquo;t be hard to provide a remote &lt;strong&gt;endpoint that would explain all the rules and intentions of the repository&lt;/strong&gt; that your agent could connect to. However, you need to find a way to inject the &amp;ldquo;friendly&amp;rdquo; description of how you want to work with the data. As mentioned in my prior post, there&amp;rsquo;s no standard way to describe this.&lt;/p&gt;
&lt;p&gt;If I was going stick with SQLite (I&amp;rsquo;m not), then I&amp;rsquo;d probably come up with some &amp;ldquo;meta table&amp;rdquo; that would store the friendly descriptions of the other tables, what they meant in terms of domain-level content objects, and how I would want to work with them. I&amp;rsquo;m not sure there would be a way to provided standardized access to this from the SQL level, but from the remote API level (which is where most access would come from), I could have an endpoint that returned a combination of friendly descriptions and SQL DDL.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once I was satisfied that my data was secure (that my repository was &amp;ldquo;well-defended&amp;rdquo;), then &lt;strong&gt;I didn&amp;rsquo;t really care what Claude did with it&lt;/strong&gt;. I don&amp;rsquo;t recommend getting callous with your data, but all of these apps took basically no effort from me, so I would have been happy to create them, use them, throw them away, and create new ones.&lt;/p&gt;
&lt;p&gt;Consider this: could every user roll their own UI?  We usually talk about &amp;ldquo;&lt;em&gt;the UI&lt;/em&gt;,&amp;rdquo; and maybe we have a default…but what if I don&amp;rsquo;t like it? So long as the repository can defend itself, then could I just have some AI agent write me my own UI that I do like?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class="in-list"&gt;&lt;p&gt;JetBrains is apparently &lt;a href="https://www.infoworld.com/article/4029053/jetbrains-working-on-higher-abstraction-programming-language.html"&gt;planning a new programming language… English&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;JetBrains is exploring how to make this new language a derivative from Kotlin, but [the CEO] believes the derivative should be English. &amp;ldquo;So basically, you write the design doc in English, maybe with some semantics, with some abstract paragraph, some other things which might help.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/aside&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pass-through identity will matter more.&lt;/strong&gt; SQLite doesn&amp;rsquo;t have any user permissions (if you have access to the database file, you can do everything). That was a key issue in this case, because all my vibe-coded apps were connecting in &amp;ldquo;God mode.&amp;rdquo; In real-life, I&amp;rsquo;d use a database server that required login, and I would make them connect as actual database users that can be tracked and throttled, rather than funneling everything through the same user (as we tend to do with our applications).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related to that, the idea of lots of independent worker bees doing content operations independently brings up questions around what non-developers might do. A human could always do something dumb, but &lt;strong&gt;AI will enable them to do dumb things at scale&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And where did this all leave me?&lt;/p&gt;
&lt;p&gt;With a pretty big question, it turns out.&lt;/p&gt;
&lt;p&gt;Frankly, I&amp;rsquo;m still a little unsure of where AI leaves the boundaries of CMS. Let&amp;rsquo;s assume I had a more full-featured database server, like SQL Server or Postgres &amp;ndash; one that gave me stored procs, and more ways to make the database &amp;ldquo;well-defended and well-described.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Could I implement an entire CMS purely in a database and call it good?&lt;/p&gt;
&lt;p&gt;This, of course, is nothing new &amp;ndash; this is how we did CMS back in the day. The entire idea of CMS, in fact, was the generalize content storage so we didn&amp;rsquo;t have to custom build databases for everything.&lt;/p&gt;
&lt;p&gt;But with AI, we&amp;rsquo;re removing a lot of the work of custom-building things. If you have an agent to do the work for you, then &lt;em&gt;do you really care if something is custom-built?&lt;/em&gt; Would it be easier to lock a content model down in a SQL database, and then just use AI to generalize everything into whatever output you wanted?&lt;/p&gt;
&lt;p&gt;This comes back to a key point: most current CMS repositories say &lt;em&gt;nothing&lt;/em&gt; about the model. They store it in a way that&amp;rsquo;s optimized for efficiency and adaptability, not intelligence, logic, intention, and discovery.&lt;/p&gt;
&lt;p&gt;We don&amp;rsquo;t store an &amp;ldquo;articles&amp;rdquo; table. Instead we do something like this:&lt;/p&gt;



&lt;pre class="mermaid"&gt;
erDiagram
    TYPE ||--o{ PROPERTY : has
    OBJECT ||--o{ TYPE : "is instance of"
    OBJECT ||--o{ OBJECT_PROPERTY : has
    OBJECT_PROPERTY ||--o{ PROPERTY : "is instance of"
    TYPE {
        int id
        string name
    }
    PROPERTY {
        int id
        int typeId
        string name
    }
    OBJECT {
        int id
        string typeId
    }
    OBJECT_PROPERTY {
        int int
        int objectId
        int propertyId
        string value
    }
&lt;/pre&gt;

&lt;p&gt;This is &lt;em&gt;very&lt;/em&gt; common repository model. (I think we call this an &amp;ldquo;object oriented repository,&amp;rdquo; but I&amp;rsquo;m sure the nomenclature is loose. Also, this assumes you&amp;rsquo;re using a relational database, which might not be true.)&lt;/p&gt;
&lt;p&gt;Content in here doesn&amp;rsquo;t make any immediate logical sense, and it&amp;rsquo;s not intended to.&lt;/p&gt;
&lt;p&gt;So why do we do this?&lt;/p&gt;
&lt;p&gt;We do it to &lt;em&gt;generalize&lt;/em&gt;, so we can adapt our repository to any &amp;ldquo;shape&amp;rdquo; of content &amp;ndash; it doesn&amp;rsquo;t matter what you&amp;rsquo;re actually storing, this model will make it fit. Indeed, a big part of every CMS vendor&amp;rsquo;s business model is built off the idea that they&amp;rsquo;ll provide a general place to put content, adaptable to whatever your actual model is.&lt;/p&gt;



&lt;pre class="mermaid"&gt;
flowchart LR

    a("Repository&lt;br/&gt;(in generalized format)")
    b("API&lt;br/&gt;(interprets the generalized format)")
    c("Editorial UI")
    d("Output")

    a--&gt;b
    b--&gt;c
    b--&gt;d

    style b fill:#cce5ff,stroke:#004085,stroke-width:2px,color:#000;
&lt;/pre&gt;

&lt;p&gt;But are we just kicking the can down the road?&lt;/p&gt;
&lt;p&gt;Since our repository could technically represent &lt;em&gt;anything&lt;/em&gt; now, the customer just has to describe the content model somewhere else. We provide our vague, amorphous repository to the customer, and we have big configuration UIs and API/app layers where they can explain the model. Then we use that to extrude content into our generalized data repository.&lt;/p&gt;
&lt;p&gt;…but what if we just described the content model at the repository? And then we pushed all the generalization off to AI? What if AI removed the labor overhead of making specific, form-fit repository and by doing so, made the repository the most efficient place to describe the model?&lt;/p&gt;



&lt;pre class="mermaid"&gt;
flowchart LR

    a("Repository&lt;br/&gt;(in specific, well-described format)")
    b("Editorial UI via AI&lt;br/&gt;(AI understands the specific format)")
    c("Output via AI&lt;br/&gt;(AI understands the specific format)")

    a--&gt;b
    a--&gt;c

    style b fill:#cce5ff,stroke:#004085,stroke-width:2px,color:#000;
    style c fill:#cce5ff,stroke:#004085,stroke-width:2px,color:#000;
&lt;/pre&gt;

&lt;p&gt;I mean, we have to describe the content model &lt;em&gt;somewhere&lt;/em&gt;, right? Why not describe it in the repository itself? And since our current databases &amp;ndash; as demonstrated above &amp;ndash; can&amp;rsquo;t understand intention, we&amp;rsquo;ll to find a way to let AI make sense of what the data &lt;em&gt;does&lt;/em&gt;, not just what it &lt;em&gt;is&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Are we coming full-circle back to bespoke databases? Has AI removed the comparative advantage to generalizing our repositories? Has AI made us less afraid of potential technical debt related to overly specific content models?&lt;/p&gt;
&lt;p&gt;Will that be the CMS of the future? Just a really good repository that can be &amp;ldquo;well-defended and well-described&amp;rdquo;? And then we let AI handle everything else?&lt;/p&gt;
&lt;p&gt;Well, this brings me back to the same argument I made in the &lt;a href="/tech/blog/cms-repo-ai/"&gt;last post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve just now spent a couple hours messing with databases and slowly wandered in a circle back to the same point.&lt;/p&gt;
&lt;p&gt;I do this frequently.&lt;/p&gt;</description>
      <pubDate>Sat, 23 Aug 2025 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/cms-vibe-experiment/</guid>
    </item>
    <item>
      <title>The Missing Service: Notify One Time</title>
      <link>https://live.deanebarker.net/tech/blog/notify-one-time/</link>
      <description>&lt;p&gt;There are lots of things I see on the web that are &amp;ldquo;upcoming,&amp;rdquo; and I think, &amp;ldquo;How can I find out when this happens?&amp;rdquo; Of course, I just could keep checking back to the URL I&amp;rsquo;m looking at, but I&amp;rsquo;ll no-doubt eventually stop doing that.&lt;/p&gt;
&lt;p&gt;And let&amp;rsquo;s face facts: &lt;em&gt;no one&lt;/em&gt; really wants to give their email to a website. Very few people want to subscribe to all your content, certainly not if they just want to find out about one thing.&lt;/p&gt;
&lt;p&gt;What people &lt;em&gt;might&lt;/em&gt; want is to be notified when a specific thing happened. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When Part 2 of a blog post series publishes&lt;/li&gt;
&lt;li&gt;When a specific software update is released&lt;/li&gt;
&lt;li&gt;When a book is finally released&lt;/li&gt;
&lt;li&gt;When new tour dates are announced&lt;/li&gt;
&lt;li&gt;When early election voting opens&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For these things, I will give you my email address, only if you promise to use it solely for the thing I want. If you promise to email me &lt;em&gt;that one time&lt;/em&gt; about that thing I want to know about &lt;em&gt;and then forget my email&lt;/em&gt;, then I&amp;rsquo;d be willing to give it to you.&lt;/p&gt;
&lt;p&gt;That said, this is what I want to see on a website (obviously, this is just a demo/POC, so don&amp;rsquo;t enter anything here):&lt;/p&gt;
&lt;div id="notify-one-time"&gt;
&lt;div id="not-title"&gt;Notify One Time&lt;/div&gt;
&lt;div id="not-form"&gt;
&lt;input type="text" placeholder="Enter your email"/&gt;&lt;button&gt;Let me know&lt;/button&gt;
&lt;/div&gt;
&lt;div id="not-help"&gt;&lt;p&gt;You are providing your email to the Notify One Time service. This is an independent service on which this site owner has an account.&lt;/p&gt;
&lt;p&gt;You are asking to be notified when [whatever event] occurs.&lt;/p&gt;
&lt;p&gt;When this event occurs, the site owner will provide the announcement text, we will email it to you, and then delete your email forever. The site owner will never see your email address and can never send anything else to it.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Notify One Time (&amp;ldquo;NOT&amp;rdquo;), would be a non-profit service. (Maybe? I&amp;rsquo;m not much of a businessman. I don&amp;rsquo;t know the best way to organize this.)&lt;/p&gt;
&lt;p&gt;As a site owner, I could create an account and register events. For example, when my upcoming book is published. For each event, I would get some script code to embed the above UI on my website.&lt;/p&gt;
&lt;p&gt;If a visitor wants to be notified when that happens, they could enter their email address and it that would get sent to the Notify One Time servers, linked to my event.&lt;/p&gt;
&lt;p&gt;As I site owner, I could never see the emails. I could maybe get an analytic or two &amp;ndash; like the aggregate number of people who had provided their emails, maybe even over some time distribution &amp;ndash; but I could never actually see the data.&lt;/p&gt;
&lt;p&gt;Then, when my book publishes, I would log into my account at Notify One Time, and &amp;ldquo;resolve&amp;rdquo; the event by providing the text of the announcement email (which, presumably, would have an Amazon link or something).&lt;/p&gt;
&lt;p&gt;Notify One Time would then send that announcement email to everyone who subscribed. And then… &lt;em&gt;it would delete every email that was provided, irrevocably and forever&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I could then remove the script code (but it would likely have something in it to check the the event was active, and hide itself if it had already been resolved).&lt;/p&gt;
&lt;p&gt;The key to this is to get people to recognize and trust the system. If NOT became some known-ish brand and people understood the model, then they would see the logo and know that there was no commitment. They were just signing up for &lt;em&gt;one&lt;/em&gt; email, full stop.&lt;/p&gt;
&lt;h2&gt;Postscript: Preventing Abuse&lt;/h2&gt;
&lt;p&gt;I know this will be an immediate question: &amp;ldquo;What&amp;rsquo;s to stop my ex-boyfriend from signing me up for a bunch of notifications?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;A few thoughts here &amp;ndash; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The risk is low. To do this, your ex-boyfriend would have to find a bunch of pages that have Notify One Time forms embedded. Even then, they are, by definition, only signing you up for a single email to be sent, the contents of which they have no control over, sometime in the future.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We &lt;em&gt;could&lt;/em&gt; require email verification &amp;ndash; send an initial email and require confirmation &amp;ndash; but I don&amp;rsquo;t like this as it adds cognitive overhead and could ironically become an abuse vector all by itself.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What we would probably do if have some heuristic to sense abuse. For instance, if the same email gets submitted many times in the same time period, we could flag it and &lt;em&gt;then&lt;/em&gt; require email verification for that particular address.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But, as I noted in the first point, I think the potential for abuse is low, and the threat of material damage is even lower. But I concede that I might just be naive.&lt;/p&gt;</description>
      <pubDate>Wed, 13 Aug 2025 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/notify-one-time/</guid>
    </item>
    <item>
      <title>Queen Bees: The Resurgence of CMS Repositories in the Age of AI</title>
      <link>https://live.deanebarker.net/tech/blog/cms-repo-ai/</link>
      <description>&lt;p&gt;I&amp;rsquo;m wondering if the coming age of AI will force CMSs to retrench back to the repository level.&lt;/p&gt;
&lt;p&gt;Since the birth of the CMS, we&amp;rsquo;ve walked away from the repositories. We initially imbued them with lots of tools and features &amp;ndash; modeling, versioning, workflows, permissions, version control, etc. &amp;ndash; but these are ultimately… unsexy. It&amp;rsquo;s hard to sell tools that are literally designed to keep your life boring and uneventful.&lt;/p&gt;
&lt;p&gt;Soon, building content &lt;em&gt;output&lt;/em&gt; became more important. The content itself gave way in importance to site management and site building.&lt;/p&gt;
&lt;p&gt;Then, those even gave way to post-publish optimization tools. No one cared what happened &amp;ldquo;to the left of the Publish button.&amp;rdquo; All the cool kids moved to the right of it, and just wanted to talk about what happened once the content was published.&lt;/p&gt;
&lt;p&gt;In the background, our repositories haven&amp;rsquo;t really evolved. Show me a vendor that regularly releases new repository service features, and I&amp;rsquo;ll show you a vendor no one is talking about.&lt;/p&gt;
&lt;p&gt;But let&amp;rsquo;s back up a bit &amp;ndash; &lt;/p&gt;
&lt;p&gt;Right now, CMSs do a lot, especially if they&amp;rsquo;ve made the jump to that vague definition of &amp;ldquo;digital experience platform&amp;rdquo; (DXP). Let&amp;rsquo;s build it out from the bottom up:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Content Modeling:&lt;/strong&gt; defining what the content is &amp;ndash; types, properties, datatypes, validation rules, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Content Storage and Access:&lt;/strong&gt; providing basic persistence and access to content; APIs, both remote and native; querying facilities&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Content &amp;ldquo;Management:&amp;rdquo;&lt;/strong&gt; allowing everything that happens from creation to deletion, like permissions, workflow, lifecycle management, auditing, etc. (in quotes because this is the actual &lt;em&gt;management&lt;/em&gt; stuff; that word does too much work)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Content Aggregation:&lt;/strong&gt; grouping content in ways to provide increased value; trees, menus, tagging, collections, relations, assemblies, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Content Publishing:&lt;/strong&gt; generating and transmitting some kind of output artifact&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Content Optimization:&lt;/strong&gt; adapting content to immediate context;  personalization and experimentation and customer behavior tracking and all that&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is an onion of successive layers.&lt;/p&gt;
&lt;p&gt;The first few layers  &amp;ndash;  the first two? the first three? the first four?  &amp;ndash;  are very core to the idea of &amp;ldquo;managing content.&amp;rdquo; But as we go further down the list we get into more and more abstract levels of functionality that &amp;ldquo;wrap&amp;rdquo; the core.&lt;/p&gt;
&lt;p&gt;AI might start to peel this onion, meaning it will start to replace some of the outer layers and even redefine what they mean. Consequently, CMSs might start to shed those layers, effectively ceding them to AI, and retrench back to the core.&lt;/p&gt;
&lt;p&gt;When this happens, the question will become: where does it stop? How close to the core do we let AI absorb? At what point do we say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Enough. You can go no farther. The features and functionality this close to the core are managed by humans and cannot be manipulated by AI.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Specifically I&amp;rsquo;m thinking in particular about content modeling. This is on my mind because of a group discussion we had at &lt;a href="https://www.boye-co.com/conferences/cmsconnect25/"&gt;CMS Connect 25&lt;/a&gt; in Montreal last week. A bunch of us were batting around what content modeling looks like in the age of AI, and I started to get a little uneasy.&lt;/p&gt;
&lt;p&gt;The core question we all seemed to be dancing around was this: do we let AI manage our content models?&lt;/p&gt;
&lt;p&gt;Right now, I say NO.&lt;/p&gt;
&lt;p&gt;To me, this is the cliff that prevents us from retreating any further. While we might retreat to the very concept of defining what our content is, that&amp;rsquo;s where we turn toward the invader and make our stand.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Please understand that I&amp;rsquo;m prepared to be proven wrong someday, and I&amp;rsquo;m committed to consistently testing this belief as the market evolves.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a natural tension here between: (1) rational skepticism, and (2) stubborn obstinance because I&amp;rsquo;m a middle aged veteran and something new is changing everything I know. I genuinely hope I&amp;rsquo;m on the &amp;ldquo;rational skepticism&amp;rdquo; side of that fence, but I could be fooling myself.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m also deeply self-aware that I have a sometimes irrational love for content modeling. &lt;a href="/books/real-world-content-modeling/"&gt;I wrote a entire book about it.&lt;/a&gt; I quite sure this warps my thinking at some level.&lt;/p&gt;
&lt;p&gt;Related: I enjoyed this piece from Nick Cave recently (and the associated video is amazing): &lt;a href="https://www.theredhandfiles.com/tupelo-film-elvis/"&gt;Is changing your mind about things a sign of weakness? Sometimes, it feels that way.&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;I feel like content models should be inviolate. They&amp;rsquo;re built with a very human understanding of the nature of your content and how it relates to your organizational domain. So many decisions are implemented in content models that are based on a human&amp;rsquo;s understanding of what works at &lt;em&gt;that&lt;/em&gt; organization and the people who comprise it.&lt;/p&gt;
&lt;p&gt;Additionally, a good model represents not only what you need out of content now, but what you might need in the future. A smart human doesn&amp;rsquo;t have a myopic focus on only the output or usage they need immediately, but what they might do in the future, along multiple axes, including how to output the content, manage the content, operate on the content, govern the content, etc.&lt;/p&gt;
&lt;p&gt;Yes, this might be a Pollyanna-esque view of the whole thing. I get that. But this is where my head is at right now.&lt;/p&gt;
&lt;p&gt;For some years now, I&amp;rsquo;ve managed a database of all my books. As an initial build-time task, I needed to define a model of what constitutes a &amp;ldquo;book.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Each one  has a Title and a Subtitle and a bunch of other obvious stuff, of course. But then I include some data that only makes sense to me &amp;ndash; fields for &amp;ldquo;Loaned To,&amp;rdquo; and &amp;ldquo;Acquisition Notes&amp;rdquo; (how I came to possess it), and &amp;ldquo;Repair Notes&amp;rdquo; (poor bindings and stuff that could be repaired), &amp;ldquo;Reading Environment Notes&amp;rdquo; (where I was when I read it, if it was somewhere interesting, like on vacation or a business trip or a road trip).&lt;/p&gt;
&lt;p&gt;A lot of this is based purely on what I want to know and store about my books. In particular, it&amp;rsquo;s not related to any existing output (I don&amp;rsquo;t need to publish information about how a book needs to be repaired, for example), so there&amp;rsquo;s no existing thing to reverse-engineer. In fact, when I first put this content model together, I wasn&amp;rsquo;t even planning to output the data anywhere  &amp;ndash;  it was just a tracking exercise.&lt;/p&gt;
&lt;p&gt;To me, this content model is something that I own. This is the basic idea &amp;ndash; the nature, the notion &amp;ndash; of what I&amp;rsquo;m trying to manage. To be overly dramatic, this content represents the &amp;ldquo;soul&amp;rdquo; of what a book represents to me.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not ready to surrender this to AI. I don&amp;rsquo;t think I ever will be.&lt;/p&gt;
&lt;p&gt;Right now, I&amp;rsquo;m using this to output a &lt;a href="/library/"&gt;library inventory&lt;/a&gt; and &lt;a href="/library/reading/"&gt;a reading list&lt;/a&gt;, but who knows what I&amp;rsquo;ll do with it in the future? The model exists apart from any particular output. In fact, the outputs can be considered ephemeral. They&amp;rsquo;ve existed for many years, but who knows? I might throw them away someday and do something else with the data.&lt;/p&gt;
&lt;p&gt;Some people would say that AI should manage the model. In particular, it&amp;rsquo;s kind of vogue to say, &amp;ldquo;just show AI what you want to get out of it, and it will suggest and manage a content model for you.&amp;rdquo;&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;What do we even call this? &amp;ldquo;Output-driven modeling&amp;rdquo;? I hear about it so much, I feel like it needs a name.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;For smaller one-off projects where the content exists for the sake of that one output, maybe this would be fine. But for larger notions of enterprise content, I feel like this is short-sighted.&lt;/p&gt;
&lt;p&gt;In my situation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I didn&amp;rsquo;t have an output planned when I created the database. There was literally nothing to show to an AI.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I have at least two outputs now. And who knows what else I&amp;rsquo;ll do later? I can&amp;rsquo;t show AI &amp;ldquo;what I want out of the data&amp;rdquo; because the end of that story hasn&amp;rsquo;t been written and likely never will be. My model and my data is a bundle of potential energy which I haven&amp;rsquo;t finished harnessing in different ways yet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If I did have an AI work backwards to create my model, I would have gotten a model really good for &lt;em&gt;one&lt;/em&gt; particular output &amp;ndash; the one I showed to the AI. I worry that an &amp;ldquo;output-centric model&amp;rdquo; is way too specific to that particular output.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, at this moment, I&amp;rsquo;m settling on this working premise  &amp;ndash; &lt;/p&gt;
&lt;p&gt;Humans create the content model. An AI may work only within the bounds of it. AI is &lt;em&gt;subservient&lt;/em&gt; to the content model. It can &lt;em&gt;operate on&lt;/em&gt; content, but it cannot &lt;em&gt;define&lt;/em&gt; what content is.&lt;/p&gt;
&lt;p&gt;A good content repository in the age of AI should be well-defended and well-described.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Well-defended:&lt;/strong&gt; It should protect content by concise and expressive data and validation rules&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Well-described:&lt;/strong&gt; It should expose its modeling as openly and clearly as possible&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is the only way we&amp;rsquo;re going to keep everything under control when multiple AIs start working with our content as they evolve over the next decade.&lt;/p&gt;
&lt;p&gt;Imagine that our ironclad repository and model is the queen bee of a hive. Lots of AIs are hovering around it, working independently and concurrently, attending to The Queen&amp;rsquo;s needs and otherwise acting in &lt;em&gt;service&lt;/em&gt; of The Queen.&lt;/p&gt;
&lt;p&gt;But they are not The Queen. They are ultimately disposable.&lt;/p&gt;
&lt;p&gt;And the last point is non-trivial. What an AI does is or can often be ephemeral, and should be considered as such, which is utterly antithetical to the principles that a repository is designed around.&lt;/p&gt;
&lt;p&gt;Let me tangent a bit on this point  &amp;ndash; &lt;/p&gt;
&lt;p&gt;Remember when computer virtualization became a thing? My career started when a server was 1:1 to a plastic box in a data center somewhere. Servers were a big deal  &amp;ndash;  you ordered them, and they showed up on a wooden pallet, and you got a buddy to hold them for you while you bolted them into the rack.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;A couple anecdotes &amp;ndash; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Project launches actually got delayed sometimes because IT was &amp;ldquo;waiting on the new server,&amp;rdquo; and it was stuck in some shipping dock in Wichita.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I remember installing a CMS once from a CD-ROM inside a freezing cold data center via a little monochrome monitor and a flimsy built-in keyboard and trackball combo. The CD drive was incredibly slow, and I sat shivering on the floor in front of an industrial air conditioner for about an hour.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/aside&gt;
&lt;p&gt;But one day we got virtual servers, and so long as we could wrangle an IT guy, then we could get a new server by filing a ticket. And then when we got AWS and Azure, and suddenly we had the option to create servers in seconds, without even involving IT if we didn&amp;rsquo;t want to.&lt;/p&gt;
&lt;p&gt;And  &amp;ndash;  this was the really weird part  &amp;ndash;  &lt;em&gt;we could shut them down just as fast&lt;/em&gt;. Given the hourly billing, we were introduced to the idea of creating a server to do a set amount of work, then throwing it away. Servers really became &amp;ldquo;freelance computation&amp;rdquo; that you could hire for the specific period of time you needed.&lt;/p&gt;
&lt;p&gt;Computational power became disposable.&lt;/p&gt;
&lt;p&gt;This is where I think AIs is going in relation to content. We&amp;rsquo;ll use AI to work or create artifacts from content or UIs to work with content, with the understanding that what they create is basically disposable. Why? Because the cost to create what it is has been effectively driven to zero. When creating something doesn&amp;rsquo;t cost anything, you don&amp;rsquo;t need to keep the output. You can get it back by just asking for it.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Yes, I&amp;rsquo;m very aware of the environmental cost of AI. I&amp;rsquo;m talking about the financial cost to the organization, not the planet. To humanity&amp;rsquo;s absolute detriment, business cares about dollars far more than trees.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Let&amp;rsquo;s say that one day, I have a little extra time. To make sure all my books are tagged, I could very easily just say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hey Claude, connect to this repository and learn all about the content model and the content in it.&lt;/p&gt;
&lt;p&gt;Then produce an optimized UI as a browser-based app for me to apply tags to any book records that don&amp;rsquo;t already have them. In the UI, show me some details about the book, and maybe prefill the form field with some suggested tags. Also, show me all the tags currently across all books in use and the number of times they appear. Finally, show me a running percentage of how far I am toward getting all books tagged.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I get my UI in a few minutes and run it (maybe just on localhost). I work away until all my books are tagged, and &lt;em&gt;then I just throw the UI away.&lt;/em&gt; I don&amp;rsquo;t need it anymore, and if I ever do, I&amp;rsquo;ll just ask for it from scratch again.&lt;/p&gt;
&lt;p&gt;In the end, I didn&amp;rsquo;t want the UI. I wanted the outcome of having it. I didn&amp;rsquo;t want the shovel, I wanted a hole in the ground.&lt;/p&gt;
&lt;p&gt;This really re-frames the concept of &amp;ldquo;vibe-coding.&amp;rdquo; I care less about the textbook correctness of code that I&amp;rsquo;m not going to keep. And remember, since my content model is &amp;ldquo;well-described&amp;rdquo; and my repository &amp;ldquo;well-defended,&amp;rdquo; even stupid code is prevented from doing damage. I&amp;rsquo;ve put rules around The Queen, and I don&amp;rsquo;t much care how a worker bee does their job, so long as they obey the rules.&lt;/p&gt;
&lt;p&gt;A key point is that what I just did with Claude is only one thing that might be happening in the repository at any given time. Somewhere else, some other person might be doing this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hey ChatGPT, connect to this repository and learn all about the content model and the content in it.&lt;/p&gt;
&lt;p&gt;Then execute a batch process to identify books that have a Date Completed value for which there is no physical copy in the library. Append the tag &amp;ldquo;read-but-unowned&amp;rdquo; to the current value of the &amp;ldquo;Tags&amp;rdquo; field.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Think about what&amp;rsquo;s going on here:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;This operation is being done by a different AI engine. Let to its own devices, it might interpret the content different unless it has access to a clear, concise description of how the content is defined.&lt;/li&gt;
&lt;/ol&gt;
&lt;aside&gt;&lt;p&gt;I get a little skeptical when people talk simply of &amp;ldquo;AI&amp;rdquo; as if they can guarantee that all their employees will be using the &lt;em&gt;same&lt;/em&gt; engine with the &lt;em&gt;same&lt;/em&gt; settings and the &lt;em&gt;same&lt;/em&gt; context.&lt;/p&gt;
&lt;p&gt;In reality, I think we need to say &amp;ldquo;&lt;em&gt;an&lt;/em&gt; AI&amp;rdquo; to represent that every AI is like a new freelance contractor that shows up to do a job, without knowing any other contractor that has worked in the past or may be working right now.&lt;/p&gt;
&lt;p&gt;Thoughout this article, I&amp;rsquo;ve gone back and tried to be clear when I&amp;rsquo;m talking about &amp;ldquo;AI&amp;rdquo; as a general concept, or &amp;ldquo;an AI&amp;rdquo; as a specific computational process, or &amp;ldquo;AIs&amp;rdquo; as multiple individual instances of them. They&amp;rsquo;re not the same thing.&lt;/p&gt;
&lt;/aside&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;p&gt;This operation is being done simultaneously with the other operation. This means that they&amp;rsquo;re both depending on a stable content model. In this particular case, the two operations are &amp;ldquo;sharing&amp;rdquo; access to the Tags property, and each AI is ignorant of the fact that the other one is working with the same field. Each AI needs the definition of that property to stay the same as it was when the operation was started.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This operation is transactional and ephemeral. I&amp;rsquo;m just asking it to do a job then stop. Will I need to do this again? Maybe, but probably not enough to keep the code around. Note that I&amp;rsquo;m not specifically asking it to &amp;ldquo;create&amp;rdquo; anything. In the first instance I said &amp;ldquo;&lt;em&gt;produce&lt;/em&gt; a UI&amp;rdquo; and in the other I said &amp;ldquo;&lt;em&gt;execute&lt;/em&gt; a batch process.&amp;rdquo; I don&amp;rsquo;t want the shovel  &amp;ndash;  I just want the hole in the ground.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&amp;rsquo;s do it again:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hey Gemini, connect to this repository and learn all about the content model and the content in it.&lt;/p&gt;
&lt;p&gt;Then generate a static website that has a home page that lists all the books, a tag overview page that lists all the tags in use, a single page for each tag that lists the books with that tag, and then a single page for every book, to which any reference of the book is linked. Search Amazon to find the product URL for the book. If you find one, put that on the page too, using affiliate link token &amp;ldquo;jamesbondfan007.&amp;rdquo; Give this to me as a ZIP file of HTML documents that I can just extract to a web server root.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Another AI engine. Another ephemeral job. Another worker bee.&lt;/p&gt;
&lt;p&gt;What do all these scenarios have in common?&lt;/p&gt;
&lt;p&gt;The Queen.&lt;/p&gt;
&lt;p&gt;A content model, and a repository. They all depend on some common definition of what content is, and some common location to access the content itself.&lt;/p&gt;
&lt;p&gt;They are worker bees, performing actions on behalf of The Queen. They can&amp;rsquo;t usurp The Queen, only serve her and then die.&lt;/p&gt;
&lt;p&gt;Where we might have depended on tools in a CMS to do the jobs we&amp;rsquo;ve described, we&amp;rsquo;ll use temporary AI agents to do it in the future. We&amp;rsquo;ll probably use a lot of them with all sorts of different models and capabilities, invoked and given direction by different people, starting and stopping in overlap with each other, and occasionally coming into conflict with each other. Lots and lots of worker bees, all trying to serve The Queen at the same time.&lt;/p&gt;
&lt;p&gt;With the withering state of repositories, what possible hope do we have of controlling and coordinating all this, while keeping our content safe and avoiding risk?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Primarily,&lt;/strong&gt; we need a well-defended, well-described content model that no AI can change directly.&lt;/p&gt;
&lt;p&gt;In my mind, this becomes the limit of our retrenchment. This is the core of the onion. We cede no more territory than this.&lt;/p&gt;
&lt;p&gt;If an AI requires a change (a different property, a different type, whatever…), then it either needs to explain the change to a human, or put that property and its data somewhere else and manage it from there.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Example: if our last job needs to store the Amazon URL for a book, it can ask me to change the model, or  &amp;ndash;  more likely  &amp;ndash;  I&amp;rsquo;ll just tell to create a SQLite database in a temp folder and swap data to and from it, since it&amp;rsquo;s the only AI that needs that at the moment. That doesn&amp;rsquo;t rate a model change, and I don&amp;rsquo;t need that data in my repository, especially since I just want that static site to show a friend and then I&amp;rsquo;m getting rid of it.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;&lt;strong&gt;Secondly,&lt;/strong&gt; we&amp;rsquo;ll need to revisit security, audit, and concurrency capabilities. We&amp;rsquo;ll need to acknowledge the increasing frequency of &amp;ldquo;user agency&amp;rdquo; &amp;ndash; AIs acting on content on behalf of human users.&lt;/p&gt;
&lt;p&gt;If I give AI either of the first two scenarios above, how do we record those write operations? Did I do that? Or did the AI do that? Well, we both did. We&amp;rsquo;ll need to account for the scenario of an AI acting at a human&amp;rsquo;s direction. In addition to being clear that this was a delegated action, we might want to store meta about the AI that was used  &amp;ndash;  vendor, model, instance, etc.  &amp;ndash;  and we might even store the prompt so that we can audit and recreate what happened later, if we need to.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thirdly,&lt;/strong&gt; very boring, unsexy risk mitigation features will have renewed importance. Versioning, version control, rollback, and concurrency and conflict management will become a bigger concern, and will need to be more granular. We&amp;rsquo;ll need to track changes to content in a way that they can be reconciled, merged, or canceled after the fact, because the proliferation of worker bees will cause them to run over each other, in addition to the fact that AI will simply magnify the volume of activity a single human can initiate.&lt;/p&gt;
&lt;p&gt;Simply put: content repositories will need to get better and stronger.&lt;/p&gt;
&lt;p&gt;The Queen must rule. Long live The Queen.&lt;/p&gt;
&lt;p&gt;On the other side, the outputs  &amp;ndash;  the worker bees  &amp;ndash;  are less important. They can unbundle. I might use one worker bee for a specific project, but use a different one the next week, maybe even to re-do that same project. Worker bees are easier. I don&amp;rsquo;t bet the company on a worker bee.&lt;/p&gt;
&lt;p&gt;This is the future we&amp;rsquo;re in for, I think  &amp;ndash; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The resurgence of repository services as a key enabler of AI capabilities. Some repositories will perform well in the face of an AI swarm. Others will not.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rich, inviolate content models no AI can modify directly. Well-defended and well-described.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some common description protocol for these models. MCP is the telephone, but what language are we speaking? &lt;a href="https://en.wikipedia.org/wiki/RDF_Schema"&gt;RDF&lt;/a&gt;? &lt;a href="https://en.wikipedia.org/wiki/Content_repository_API_for_Java"&gt;JCR&lt;/a&gt;? &lt;a href="https://en.wikipedia.org/wiki/Web_Ontology_Language"&gt;OWL&lt;/a&gt;? &lt;a href="https://json-schema.org/"&gt;JSON Schema&lt;/a&gt;? …&lt;a href="https://en.wikipedia.org/wiki/Web_Services_Description_Language"&gt;WSDL&lt;/a&gt;?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;External APIs for description (&amp;ldquo;Connect to this repository and learn all about the content model…&amp;rdquo;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ephemeral content operations (&amp;ldquo;worker bees&amp;rdquo;) from which we simply want to retain the outcome, not the tool used to achieve it&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stronger and more granular control and auditing features, particularly those that increase the level of concurrency management&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Evolved security models that understand humans and AIs will work together, and so two &amp;ldquo;users&amp;rdquo; can and will collaborate on the same action&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Who is going to lead this charge? Which vendors and which architectural paradigms are closest to it already?&lt;/p&gt;
&lt;p&gt;Generally speaking: CMS vendors who have continued to improve their &amp;ldquo;boring&amp;rdquo; repositories over time, resisting the desire to concentrate only on more glamorous output and optimization tooling, and ensuring that their repositories provided a solid foundational base for everything else.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll resist the urge to be more specific than that. I&amp;rsquo;ll let others make their own arguments.&lt;/p&gt;
&lt;p&gt;Good luck, everyone.&lt;/p&gt;</description>
      <pubDate>Sun, 10 Aug 2025 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/cms-repo-ai/</guid>
    </item>
    <item>
      <title>The Joy of Mixing Custom Elements, Web Components, and Markdown</title>
      <link>https://live.deanebarker.net/tech/blog/custom-elements-markdown/</link>
      <description>&lt;table-of-contents title="Contents" selector="h2, h3, h4"&gt;&lt;/table-of-contents&gt;

&lt;p&gt;I love Markdown. I write faster and more natively in it than any other format or tool.&lt;/p&gt;
&lt;p&gt;If we zoom way out, here&amp;rsquo;s the most basic philosophy of Markdown: replace complicated stuff with simpler stuff.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all it does, really. It replaces some tedious nested taggy stuff with way simpler stuff that makes more visual sense and is  faster to type. At its core, Markdown is really just a bunch of macros.&lt;/p&gt;
&lt;p&gt;This website runs on 6,000-ish Markdown files. They&amp;rsquo;re processed on the server &amp;ndash; meaning the &lt;a href="https://github.com/xoofx/markdig"&gt;Markdig library&lt;/a&gt; from .NET processes them, then sends back the resulting HTML. I&amp;rsquo;m all-in on Markdown, to the point where I wrote my own online editor for it.&lt;/p&gt;
&lt;p&gt;Server-side processing of Markdown is a pretty common model &amp;ndash; most static site generators fundamentally do the same thing: they process the Markdown, turn it into HTML, and that gets sent to the server (via being written to files).&lt;/p&gt;
&lt;p&gt;One of the philosophical points of Markdown is that you can mix it with HTML. Meaning, a Markdown parser is supposed to leave HTML alone &amp;ndash; if a line of text looks like it has some tags, the parser should skip it.&lt;/p&gt;
&lt;p&gt;This means you can do this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markdown"&gt;This is some **Markdown!**

&amp;lt;img src=&amp;quot;yay.jpg&amp;quot; /&amp;gt;

This is some more ***Markdown!***
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that should work fine. The first and last lines will be processed and transformed, and the middle line will be left alone and output as it&amp;rsquo;s written.&lt;/p&gt;
&lt;p&gt;These were &lt;a href="https://daringfireball.net/projects/markdown/syntax#html"&gt;the original rules&lt;/a&gt; around inline HTML in Markdown:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The only restrictions are that block-level HTML elements […] must be separated from surrounding content by blank lines, and the start and end tags of the block should not be indented with tabs or spaces.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I didn&amp;rsquo;t find the need for blank lines in &lt;a href="https://spec.commonmark.org/0.31.2/#html-blocks"&gt;the CommonMark spec&lt;/a&gt;, but just note that every Markdown processor might be a little different in this respect, so test.&lt;/p&gt;
&lt;p&gt;Anyway, we&amp;rsquo;ll likely get HTML that&amp;rsquo;s something like this out of the above Markdown.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xhtml"&gt;&amp;lt;p&amp;gt;This is some &amp;lt;strong&amp;gt;Markdown!&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;img src=&amp;quot;yay.jpg&amp;quot; /&amp;gt;
&amp;lt;p&amp;gt;This is some more &amp;lt;em&amp;gt;&amp;lt;strong&amp;gt;Markdown!&amp;lt;/strong&amp;gt;&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our &lt;code&gt;img&lt;/code&gt; tag is intact and has been left alone.&lt;/p&gt;
&lt;p&gt;This is great, and helps you in some sticky situations. You can effectively &amp;ldquo;escape out&amp;rdquo; to HTML when you need to.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;A few years back, for &lt;a href="/tech/courses/advanced-cms/"&gt;a college class I was teaching at the time&lt;/a&gt;, I discussed the history of Markdown with &lt;a href="https://daringfireball.net/"&gt;John Gruber&lt;/a&gt;, the guy who invented it. He graciously recollected why he created it and some of the reasons behind his decisions. In particularly, pointed to this aspect of having an &amp;ldquo;HTML escape hatch&amp;rdquo; as one of the key things that led to its success.&lt;/p&gt;
&lt;p&gt;In Gruber&amp;rsquo;s original Markdown doc, he &lt;a href="https://daringfireball.net/projects/markdown/syntax#html"&gt;clearly states&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;HTML is a publishing format; Markdown is a writing format. Thus, Markdown&amp;rsquo;s formatting syntax only addresses issues that can be conveyed in plain text.&lt;/p&gt;
&lt;p&gt;For any markup that is not covered by Markdown&amp;rsquo;s syntax, you simply use HTML itself. There&amp;rsquo;s no need to preface it or delimit it to indicate that you&amp;rsquo;re switching from Markdown to HTML; you just use the tags.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/aside&gt;
&lt;p&gt;However, this still leaves you with the problem where you might have a bunch of complicated, tedious HTML that forms a repeatable component of some kind that you don&amp;rsquo;t want to hand-manage and reproduce over and over. What if you want a Markdown-friendly way to represent a feedback form, or a tabbed UI, or a mortgage calculator, or something else way beyond the scope of text formatting.&lt;/p&gt;
&lt;p&gt;For these situations, what you really want is to put a token or a placeholder in your Markdown, and have something else &lt;em&gt;expand&lt;/em&gt; it later on into a larger, more complicated HTML construct.&lt;/p&gt;
&lt;p&gt;What you sort of need is… Markdown for More Complicated HTML™.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements"&gt;Custom Elements&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These have been around a long time. They tend to get lost behind all the attention paid to the big client-side frameworks like React, but the first public spec was published in 2013, finalized in 2016, and we&amp;rsquo;ve had broad browser support since 2018 or so.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Also, the naming is a little confusing. They&amp;rsquo;re technically called Custom Elements, but that&amp;rsquo;s one part of a larger toolkit called &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components"&gt;Web Components&lt;/a&gt;. I can&amp;rsquo;t figure out which term is canonical.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m using Custom Elements because that&amp;rsquo;s very technically correct. But you see Web Components a lot too, so I put that in the title of the post.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Custom Elements can do a lot, but a core function is that they divorce the source markup from what&amp;rsquo;s effectively output into the DOM.&lt;/p&gt;
&lt;p&gt;You can write X in the markup; the Custom Element will output Y into the DOM.&lt;/p&gt;
&lt;p&gt;X is simple; Y is way more complicated.&lt;/p&gt;
&lt;p&gt;X is written by an editor; Y is written by logical processing.&lt;/p&gt;
&lt;p&gt;So, considered at that level, Custom Elements can be used as… HTML &lt;em&gt;macros&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This means that when you combine them with Markdown, you get a really neat synergy of features.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Markdown expands into text formatting&lt;/li&gt;
&lt;li&gt;Custom Elements (that the Markdown processor ignores) expands into more complicated stuff&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Consider this scenario: you have a blog post which is Part 1 of a series. You want to let people subscribe to be notified about Part 2, but that involves a little widget of some kind in the HTML. And for whatever reason, you have to put this between two paragraphs.&lt;/p&gt;
&lt;p&gt;What if you could do this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markdown"&gt;This is some **Markdown!**

&amp;lt;subscribe-to /&amp;gt;

This is some more **Markdown!**
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Remember, that middle line is HTML, so the Markdown processor will leave it alone.)&lt;/p&gt;
&lt;p&gt;Then, in the browser, that &lt;code&gt;subscribe-to&lt;/code&gt; tag will expand into something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xhtml"&gt;&amp;lt;div part=&amp;quot;outer&amp;quot;&amp;gt;
  &amp;lt;label part=&amp;quot;label&amp;quot;&amp;gt;Want to know when Part 2 is published?&amp;lt;/label&amp;gt;
  &amp;lt;input part=&amp;quot;input&amp;quot; type=&amp;quot;text&amp;quot; name=&amp;quot;email&amp;quot; placeholder=&amp;quot;Give us your email&amp;quot;&amp;gt;
  &amp;lt;button part=&amp;quot;button&amp;quot; type=&amp;quot;button&amp;quot;&amp;gt;Let me know!&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is &lt;em&gt;exactly&lt;/em&gt; what Custom Elements can do.&lt;/p&gt;
&lt;p&gt;To be clear, this is &lt;em&gt;not&lt;/em&gt; a tutorial about Custom Elements in general &amp;ndash; there&amp;rsquo;s a lot of depth there &amp;ndash; but just a joyful discovery of what happens when we combine them with hand-written Markdown and come to the conclusion that both Custom Elements and Markdown sort of operate on the same principle from the perspective of the writer: they replace simpler stuff with more complex stuff.&lt;/p&gt;
&lt;p&gt;Custom Elements can just be simple tokens like the above (actually, what&amp;rsquo;s above is not quite valid, but more on that below), or you can expose configuration parameters to make them more usable in more situations:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markdown"&gt;This is some **Markdown!**

&amp;lt;subscribe-to buttonText=&amp;quot;Get me the details!&amp;quot; /&amp;gt;

This is some more **Markdown!**
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can even put stuff between Custom Element tags then use that in the processing and output. (You can go even further, by defining child tag structures and &amp;ldquo;slots&amp;rdquo; and all sorts of stuff that we won&amp;rsquo;t get into. Again, there&amp;rsquo;s &lt;em&gt;so&lt;/em&gt; much depth there…)&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markdown"&gt;This is some **Markdown!**

&amp;lt;subscribe-to&amp;gt;

We'll use your email once, then delete it. _We promise!_

&amp;lt;/subscribe-to&amp;gt;

This is some more **Markdown!**
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Guess what happens to that line between the &lt;code&gt;subscribe-to&lt;/code&gt; tags? Yes, it gets processed by the Markdown engine, &lt;em&gt;because it&amp;rsquo;s not HTML&lt;/em&gt; &amp;ndash; there&amp;rsquo;s no tag on that line. So the Markdown engine will process it, but leave the line above and below it alone, resulting in this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;subscribe-to&amp;gt;
  &amp;lt;p&amp;gt;We'll use your email once, then delete it. &amp;lt;em&amp;gt;We promise!&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/subscribe-to&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;aside&gt;&lt;p&gt;Note that the blank lines in the Markdown matter here. I tested this with &lt;a href="https://spec.commonmark.org/dingus/"&gt;the CommonMark online editor&lt;/a&gt;, and the first blank line (after the opening &lt;code&gt;subscribe-to&lt;/code&gt;) was required to process the line of Markdown. Adding the second blank line surrounded the sentence in &lt;code&gt;P&lt;/code&gt; tags.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;During a bout of insomnia, I did some local testing of the general theory.&lt;/p&gt;
&lt;p&gt;I had &lt;a href="https://claude.ai/"&gt;Claude&lt;/a&gt; vibe-code a simple Node script that read a Markdown file which looked a lot like the samples above (Markdown paragraphs above and below, with a &lt;code&gt;subscribe-to&lt;/code&gt; Custom Element in the middle). Then it processed the Markdown &amp;ndash; Custom Element included &amp;ndash; and output the result into a file.&lt;/p&gt;
&lt;p&gt;&lt;a href="/tech/blog/images/custom-elements-markdown/content.txt"&gt;Here&amp;rsquo;s the Markdown source.&lt;/a&gt; There are two &lt;code&gt;subscribe-to&lt;/code&gt; tags in there &amp;ndash; one simple version, and one with a bunch of options I thought up.&lt;/p&gt;
&lt;p&gt;You can see that when the browser encounters this &amp;ndash; &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;subscribe-to /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;ndash; it expands into HTML (in a shadow DOM) that ends up looking like this in the browser:&lt;/p&gt;








&lt;img src="/tech/blog/images/custom-elements-markdown/custom-elements-markdown.png?w=700" loading="lazy" class="center allow-magnify" data-part="image" data-value="/tech/blog/images/custom-elements-markdown/custom-elements-markdown.png?w=700" /&gt;



&lt;p&gt;Or this when you add some advanced options:&lt;/p&gt;








&lt;img src="/tech/blog/images/custom-elements-markdown/custom-elements-markdown-adv.png?w=700" loading="lazy" class="center allow-magnify" data-part="image" data-value="/tech/blog/images/custom-elements-markdown/custom-elements-markdown-adv.png?w=700" /&gt;



&lt;p&gt;&lt;a href="/tech/blog/images/custom-elements-markdown/output.html"&gt;Here&amp;rsquo;s the output file.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(That&amp;rsquo;s raw HTML; you can view the source. Understand that it&amp;rsquo;s still &lt;code&gt;subscribe-to&lt;/code&gt; in the source, but inspect the DOM and you can see what it effectively expands into. The JavaScript definition for the Custom Element is inline in the HTML doc. I used &lt;a href="https://lit.dev/"&gt;Lit&lt;/a&gt; as a base because it makes a lot of things &lt;em&gt;so&lt;/em&gt; much easier.)&lt;/p&gt;
&lt;p&gt;I just &lt;em&gt;love&lt;/em&gt; this.&lt;/p&gt;
&lt;p&gt;An editor has Markdown acting as text macros, Custom Elements acting as HTML macros, &lt;em&gt;and they can mix the two in the same file&lt;/em&gt;.  Simpler things become more complicated things. They can use Gruber&amp;rsquo;s &amp;ldquo;escape hatch&amp;rdquo; to handle infinitely complexity while being abstracted away from verbosity.&lt;/p&gt;
&lt;p&gt;This opens some lovely possibilities for page, layout, and element complexity and functionality while retaining the &amp;ldquo;I wrote it in a simple text editor!&amp;rdquo; joy that made Markdown so awesome to start with.&lt;/p&gt;
&lt;h2&gt;Postscript: Minor Technical Note&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been lying to you a little in this entire document. You actually can&amp;rsquo;t do this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;subscribe-to /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Custom Elements cannot be self-closing (or a &amp;ldquo;void tag,&amp;rdquo; as they&amp;rsquo;re called). You technically have to do this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;subscribe-to&amp;gt;&amp;lt;/subscribe-to&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The self-closing version will work sometimes, kind of accidentally. Where it falls apart is when you put something between the tags, because the browser considers the self-closing tag as just the &lt;em&gt;opening&lt;/em&gt; tag, which it then claims never closes.&lt;/p&gt;
&lt;p&gt;But here&amp;rsquo;s how and why I started &lt;del&gt;lying to you&lt;/del&gt; displaying the self-closing version.&lt;/p&gt;
&lt;p&gt;Because &amp;ndash; and stick with me here &amp;ndash; here&amp;rsquo;s something &lt;em&gt;else&lt;/em&gt; you can&amp;rsquo;t do: put your tag attributes on multiple lines.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;subscribe-to
  buttonText=&amp;quot;I love getting email!&amp;quot;
  anotherAttribute=&amp;quot;Another value&amp;quot;
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This time, it&amp;rsquo;s not the browser that&amp;rsquo;s the problem &amp;ndash; the browser is totally fine with you breaking out the attributes to their own lines. This time, it&amp;rsquo;s the Markdown engine. It looks at those middle lines and decides that they&amp;rsquo;re not HTML, not understanding that it&amp;rsquo;s logically part of the opening tag. This means that &amp;ndash; you guessed it &amp;ndash; the Markdown engine tries to process it and everything falls apart.&lt;/p&gt;
&lt;p&gt;(As noted above, this might vary a bit between Markdown engines. Claude picked &lt;a href="https://marked.js.org/"&gt;Marked&lt;/a&gt; for this POC.)&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t like that I couldn&amp;rsquo;t do this. I wanted to be able to break out all my attributes on their own lines.&lt;/p&gt;
&lt;p&gt;To solve this, I had &lt;a href="https://claude.ai/"&gt;Claude&lt;/a&gt; vibe up a simple (?) Markdown pre-processor. So before the source Markdown got fed into Marked, some code in the Node app &amp;ldquo;fixes&amp;rdquo; the tag &amp;ndash; reassembles it all back on the same line.&lt;/p&gt;
&lt;p&gt;And, while I was doing that, I also &amp;ldquo;fixed&amp;rdquo; the self-closing tag issue. If the code detected a self-closing tag that contained a dash (which Custom Elements must), it changed it to an explicitly closed tag. That&amp;rsquo;s why I showed you the self-closing tag. But know that by the time it got to the Markdown engine, it was explicitly closed.&lt;/p&gt;
&lt;p&gt;It was just cleaner and less confusing while I was early in the explanation.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the source of the Node app with the preprocessor in a (pretty gross-looking) function called &lt;code&gt;preprocessMarkdown&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;(Full disclosure: I didn&amp;rsquo;t even bother to check this. It was just a POC, so I had Claude write it. I could have written it myself, but didn&amp;rsquo;t want to put in the effort for something with no larger goal.)&lt;/p&gt;
&lt;h2&gt;Postscript: Fun and Madness with Markdown Preprocessing&lt;/h2&gt;
&lt;p&gt;Once you crack open the door of Markdown pre-processing, you can be sorely tempted to head further down that road. For instance, if you don&amp;rsquo;t like the idea of raw HTML in your Markdown, you could essentially write your own mini-language.&lt;/p&gt;
&lt;p&gt;For example, something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@:subscribe-to
 buttonText: I love email!
 placeHolder: Give us your email!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All you have to do is write some preprocessing code that detects that construct and forms it into the Custom Element tag.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;It&amp;rsquo;s not that hard. Read this: &lt;a href="/tech/parlot/parser-combinators/" data-no-index&gt;Parsers and Parser Combinators&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Is that &amp;ldquo;better&amp;rdquo; than raw HTML? I don&amp;rsquo;t know… maybe?&lt;/p&gt;
&lt;p&gt;The looming problem is that this is just one simplistic Custom Element example. When you get into more advanced features like child tag structures and slots and such, you&amp;rsquo;d probably end up re-interpreting and re-implementing &lt;em&gt;way&lt;/em&gt; more of the HTML spec than you want to.&lt;/p&gt;
&lt;p&gt;I predict there will be a point where you regret trying to do this. Pre-processing and the initial excitement of a domain-specific language is a siren that might lead you to your doom.&lt;/p&gt;
&lt;p&gt;(I swear, I have never tried to do something this foolish… I &lt;em&gt;swear&lt;/em&gt;…)&lt;/p&gt;
&lt;h2&gt;Postscript: Fun with Language Design&lt;/h2&gt;
&lt;p&gt;When you realize that Custom Elements effectively abstract writing HTML away from deeper logical programming, you realize that designing the logical interface of your Custom Elements is a fun exercise in language design.&lt;/p&gt;
&lt;p&gt;The basic principle becomes: &lt;em&gt;don&amp;rsquo;t ask for anything you don&amp;rsquo;t absolutely need&lt;/em&gt;. Do as much work as possible for your editors in code. Require them to provide as little information as possible.&lt;/p&gt;
&lt;p&gt;If we want to embed a feedback form, for instance, we could do something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;input-form submitButtonText=&amp;quot;Send message!&amp;quot;&amp;gt;
  &amp;lt;input-text label=&amp;quot;Your Name&amp;quot; spec=&amp;quot;required &amp;gt;4&amp;quot; /&amp;gt;
  &amp;lt;input-text label=&amp;quot;Your Email&amp;quot; spec=&amp;quot;required email&amp;quot; /&amp;gt;
  &amp;lt;input-text label=&amp;quot;Ticket Number&amp;quot; spec=&amp;quot;required regex:[A-Z]{2}[0-9]{4}&amp;quot; /&amp;gt;
  &amp;lt;input-text label=&amp;quot;Your Message&amp;quot; spec=&amp;quot;required multiline&amp;quot; /&amp;gt;
  &amp;lt;submit-message&amp;gt;
    &amp;lt;p&amp;gt;Thanks for your submission! We normally respond in two business days.&amp;lt;/p&amp;gt;
  &amp;lt;/submit-message&amp;gt;
&amp;lt;/input-form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;aside&gt;&lt;p&gt;Remember that Custom Elements have to contain a dash (&amp;ldquo;-&amp;rdquo;) in the name, hence the odd-ish tag naming.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;This provides everything we (the developers) need to render a feedback form.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We control the layout, so we&amp;rsquo;ll expand those &lt;code&gt;input-text&lt;/code&gt; tags into multi-tag constructs to render each field.&lt;/li&gt;
&lt;li&gt;We can assume that things like the form &lt;code&gt;METHOD&lt;/code&gt; and &lt;code&gt;ACTION&lt;/code&gt; are standardized to the site, so we don&amp;rsquo;t need to ask for those.&lt;/li&gt;
&lt;li&gt;We can automatically obtain the URL/page from which they submitted. We could even develop some system where data from specific &lt;code&gt;META&lt;/code&gt; tags in the &lt;code&gt;HEAD&lt;/code&gt; are written to the form in hidden fields, meaning additional data can be injected into the form at the page templating level.&lt;/li&gt;
&lt;li&gt;We assume the form needs a submit button, so there&amp;rsquo;s no need to specify it.&lt;/li&gt;
&lt;li&gt;We can provide an &amp;ldquo;override default setting&amp;rdquo; model, where lots of stuff have default values that will be used if not provided. For example, I&amp;rsquo;m passing in &lt;code&gt;submitButtonText&lt;/code&gt;, but that would certainly have a default value (&amp;ldquo;Submit Form&amp;rdquo;) that would be used if I didn&amp;rsquo;t feel like changing it.&lt;/li&gt;
&lt;li&gt;Inside the &lt;code&gt;input-text&lt;/code&gt; tags, we can roll up validation (&lt;code&gt;required&lt;/code&gt;, &lt;code&gt;&amp;gt;4&lt;/code&gt; meaning at least five characters) and UI (&lt;code&gt;multiline&lt;/code&gt;) specification into the same &lt;code&gt;SPEC&lt;/code&gt; attribute, so we have no need for another tag for &lt;code&gt;textarea&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We can derive all the field names from the &lt;code&gt;label&lt;/code&gt;. Assuming we submit the form with client-side code, we could easily find the value of the the &lt;code&gt;label&lt;/code&gt; for each input field via the &lt;code&gt;for&lt;/code&gt; attribute, then serialize and submit that data as well, so the server would also get the &amp;ldquo;friendly name&amp;rdquo; of each input field.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What we&amp;rsquo;ve done here is designed a specification language &amp;ndash; two of them, actually.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The combination of tags to specify the information we need to display and submit the form&lt;/li&gt;
&lt;li&gt;The embedded &lt;code&gt;spec&lt;/code&gt; values which define validation and UI variations&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is really, &lt;em&gt;really&lt;/em&gt; fun. You start to ask interesting questions about what information you actually need explicitly, and what information you can derive. You&amp;rsquo;ll find situations where you can make vast changes based on fun combinations of explicit information and environmental data.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not hard to put together something that is unique to your specific situation and strikes a lovely combination among granularity, utility, and simplicity.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;This weirdly gets me thinking about &lt;a href="https://en.wikipedia.org/wiki/Claude_Shannon"&gt;Claude Shannon&lt;/a&gt; and his seminal paper &lt;a href="https://en.wikipedia.org/wiki/A_Mathematical_Theory_of_Communication"&gt;A Mathematical Theory of Communication&lt;/a&gt; where he stripped communication down to the absolute core of its variability. Trivia: it&amp;rsquo;s from him and his work at Bell Labs that we have the concept and name for a &amp;ldquo;bit.&amp;rdquo;&lt;/p&gt;
&lt;/aside&gt;
&lt;h2&gt;Postscript: Processing Markdown Client-Side&lt;/h2&gt;
&lt;p&gt;The original point of this post was about how to mix Markdown that&amp;rsquo;s processed server-side with Custom Elements that are processed client-side. As I noted, this is a common model, and the basis for all of the static site generation that happens these days.&lt;/p&gt;
&lt;p&gt;But, what if you just wanted to process the Markdown client-side as well?&lt;/p&gt;
&lt;p&gt;You certainly can. I&amp;rsquo;ve read that &lt;a href="https://md-block.verou.me/"&gt;md-block&lt;/a&gt; is quite good for this.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t do it for a few reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I still have weird hang-ups about sending content source to the browser. Something about airing my dirty laundry? It&amp;rsquo;s not entirely rational, and I&amp;rsquo;ve spent a lot of time thinking about how it correlates to &lt;a href="/tech/narratives/fourth-wall/"&gt;breaking the fourth wall&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I wrote a bunch of &lt;a href="https://github.com/xoofx/markdig/blob/master/src/Markdig/MarkdownExtensions.cs"&gt;Markdig extensions&lt;/a&gt; specific to my site and needs. I wrote these in C#, so I wouldn&amp;rsquo;t be able to port them to the browser (…I don&amp;rsquo;t think? &lt;a href="https://developersvoice.com/blog/architecture/webassembly-wasm-and-net/"&gt;WASM&lt;/a&gt; might be able to do it?). Some client-side implementations might have extension frameworks too (here&amp;rsquo;s &lt;a href="https://zerodevx.github.io/zero-md/?a=advanced-usage.md#extensibility"&gt;an example of one in zero-md&lt;/a&gt;), however my Markdown usage on this site extends back six years to when I was really a &amp;ldquo;C# or death&amp;rdquo; kind of guy.&lt;/li&gt;
&lt;/ol&gt;
&lt;aside&gt;&lt;p&gt;Sidenote: I rolled all my extensions into a C# wrapper which I call… wait for it… &amp;ldquo;Barkdown.&amp;rdquo; I am very proud of this name.&lt;/p&gt;
&lt;/aside&gt;
&lt;ol start="3"&gt;
&lt;li&gt;Some of the extensions I wrote require information from the server, which means rendering the Markdown in the browser would require multiple round-trips back to the server to get information, and I don&amp;rsquo;t love this.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you did want to render client-side, there&amp;rsquo;s also a bit of a perspective shift needed. Somewhat ironically in the context of this post, you&amp;rsquo;d need to surround your Markdown in a Custom Element (like the aforementioned &lt;code&gt;md-block&lt;/code&gt; tag).&lt;/p&gt;
&lt;p&gt;This means that your Markdown rendering is a Custom Element on the same &amp;ldquo;level&amp;rdquo; as the Custom Elements we&amp;rsquo;ve been talking about above. The Custom Elements are not &amp;ldquo;embedded and ignored&amp;rdquo; by the Markdown engine, but rather they exist &amp;ldquo;alongside&amp;rdquo; the Markdown.&lt;/p&gt;
&lt;p&gt;Depending on the Markdown library, you might need to close that tag before opening the Custom Element.&lt;/p&gt;
&lt;p&gt;Like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;client-markdown&amp;gt;
  This is some ***Markdown!***
&amp;lt;/client-markdown&amp;gt;
&amp;lt;subscribe-to /&amp;gt;
&amp;lt;client-markdown&amp;gt;
  This is some more ***Markdown!***
&amp;lt;/client-markdown&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your need to do this probably depends on the library you use. I can&amp;rsquo;t generalize with any authority.&lt;/p&gt;
&lt;p&gt;In the end, your document is now fully an HTML document, not a Markdown document that &lt;em&gt;becomes&lt;/em&gt; an HTML document. It&amp;rsquo;s a minor perspective shift, but might have some cascading effects on things I&amp;rsquo;ve written above.&lt;/p&gt;
&lt;h2&gt;Postscript: Processing Custom Elements Server-Side&lt;/h2&gt;
&lt;p&gt;You can also do the opposite of the above &amp;ndash; if your server-side process is running in JavaScript (so, something like Node, Deno, or Bun), you can render the Custom Elements into expanded HTML on the server and send the HTML.&lt;/p&gt;
&lt;p&gt;I have never done this, but &lt;a href="https://lit.dev/docs/ssr/overview/"&gt;Lit supports it&lt;/a&gt;. They even have a library that will re-hydrate the resulting HTML into &amp;ldquo;regular&amp;rdquo; Custom Elements when the page is finished loading.&lt;/p&gt;
&lt;p&gt;Clearly, unless you do that, you&amp;rsquo;re not going to get any interactivity, so this is mostly useful as a templating language (…I think? Honestly, I know very little about it, other than that it exists).&lt;/p&gt;


&lt;section class="postscript"&gt;
&lt;hgroup class="ps"&gt;
&lt;h2&gt;Update: Additional Links&lt;/h2&gt;

&lt;p class="date"&gt;Added on &lt;time datetime="2025-08-31"&gt;August 31, 2025&lt;/time&gt;&lt;/p&gt;

&lt;/hgroup&gt;

&lt;p&gt;This post got some &lt;a href="https://news.ycombinator.com/item?id=44865997"&gt;good traction on Hacker News&lt;/a&gt;, and a few interesting resources popped up there. Additionally, lots of people emailed me after reading the thread to offer more links.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://markdown-ui.com/"&gt;Markdown UI&lt;/a&gt; is an attempt to basically do what I did above, but in some type of Markdown language.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://mdxjs.com/"&gt;MDX&lt;/a&gt; is an attempt to combine Markdown and the JDX language from React&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://markdoc.dev/"&gt;MarkDoc&lt;/a&gt; is a Markdown-based documentation format made by Stripe. It looks like a mix of Markdown and &lt;a href="/tech/fluid/"&gt;Liquid&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://vitepress.dev/"&gt;VitePress&lt;/a&gt; is some combination of Markdown and Vue&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.npmjs.com/package/react-markdown-with-mdx"&gt;react-markdown-with-mdx&lt;/a&gt; is something I do not understand very well. The description is &amp;ldquo;Higher Order Component to add MDX syntax support to react-markdown,&amp;rdquo; and there there is a &lt;a href="https://www.timetler.com/2025/08/19/unlocking-rich-ui-components-in-ai/"&gt;long explanation here&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;/section&gt;</description>
      <pubDate>Sat, 9 Aug 2025 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/custom-elements-markdown/</guid>
    </item>
    <item>
      <title>The Missing Protocol: Let Me Know</title>
      <link>https://live.deanebarker.net/tech/blog/let-me-know/</link>
      <description>&lt;p&gt;I want a new protocol, tentatively called &amp;ldquo;Let Me Know&amp;rdquo; (LMK). The purpose is to provide someone an anonymous way to get notified when a singular, specific event occurs.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a basic use case:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Some random blog author has published Parts 1 and 2 of a series. You enjoyed it, and you want to know when Part 3 is published.&lt;/p&gt;
&lt;p&gt;You don&amp;rsquo;t want to give away any personal information, you don&amp;rsquo;t want to subscribe to an RSS feed of other content, you don&amp;rsquo;t want to follow them on social media, etc. You just want an anonymous way to find out when Part 3 is published without having to manually check their website and evaluate it for the content.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My idea is that there&amp;rsquo;s a button at the bottom of Part 2, called &amp;ldquo;Let Me Know.&amp;rdquo;&lt;/p&gt;








&lt;img src="/tech/blog/images/lmk.png?w=400" loading="lazy" width="400" height="168" class="center allow-magnify" data-part="image" data-value="/tech/blog/images/lmk.png?w=400" /&gt;



&lt;p&gt;The user clicks this, and it registers an endpoint with some agent.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &amp;ldquo;endpoint&amp;rdquo; is a URL specific to that singular event.&lt;/li&gt;
&lt;li&gt;An &amp;ldquo;agent&amp;rdquo; is a persistent background service of some kind that will check to see if this event has occurred. For example, a browser extension will add it to a &amp;ldquo;check list.&amp;rdquo; Alternately, some subscription service could add it to a list.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whatever agent registers the endpoint will ping the end point at a specific interval. Let&amp;rsquo;s say once per day by default.&lt;/p&gt;
&lt;p&gt;The endpoint will often simply return:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{
  &amp;quot;happened&amp;quot;: false
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-text"&gt;204 No Content
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Either of those responses mean, &amp;ldquo;The subscribed event has not happened yet. Check back later.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Alternately, the endpoint can advise the agent when to check again.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{
  &amp;quot;happened&amp;quot;: &amp;quot;false&amp;quot;,
  &amp;quot;delay&amp;quot;: 604800 // Don't check again for one week
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your agent will keep dutifully checking on its default schedule, or obeying the delay response if it&amp;rsquo;s provided.&lt;/p&gt;
&lt;p&gt;But hopefully, on some bright shining day in the future, something like this will be returned:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{
  &amp;quot;happened&amp;quot;: true,
  &amp;quot;when&amp;quot;: &amp;quot;2025-08-06T05:38:20.234Z&amp;quot;,

  // This can be included in the notification
  &amp;quot;message&amp;quot;: &amp;quot;Part 3 of the Awesome Blog Post Series has finally been published!&amp;quot;,

  // The notification can provide one or more things to do from here
  &amp;quot;actions&amp;quot;:
  [
    {
      &amp;quot;Read the post&amp;quot;,
      &amp;quot;https://domain.com/part-3&amp;quot;
    },
    {
      &amp;quot;Visit the home page&amp;quot;,
      &amp;quot;https://domain.com/&amp;quot;
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You will get this notification… somehow.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If your agent is in a browser extension, you might get a pop-up.&lt;/li&gt;
&lt;li&gt;If you agent is some subscription service, you might get an email.&lt;/li&gt;
&lt;li&gt;If your agent is a mobile app, you might get a push notification.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But &lt;em&gt;somehow&lt;/em&gt;, you will be notified that the event &amp;ndash; whatever the thing was you were waiting for &amp;ndash; has occured.&lt;/p&gt;








&lt;picture&gt;&lt;source srcset="/tech/blog/images/lmk-alert.png?w=480" media="(max-width: 480px)"&gt;&lt;/source&gt;&lt;img src="/tech/blog/images/lmk-alert.png?w=500" loading="lazy" width="500" height="124" class="center allow-magnify" data-part="image" data-value="/tech/blog/images/lmk-alert.png?w=500" /&gt;&lt;/picture&gt;



&lt;p&gt;And then &amp;ndash; and this is key &amp;ndash; &lt;em&gt;the endpoint is automatically deleted from your agent&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The event has happened, so the agent does not check again. The one task you assigned to it has been completed. If you want to find out about Part 4, you&amp;rsquo;ll subscribe (presumably) using a button at the bottom of Part 3. Or not. Whatever.&lt;/p&gt;
&lt;p&gt;At any given time, you can review the endpoints registered in your agent, see when they were registered, when they were last checked, when they are scheduled to check again, force then to check again, etc. And you can delete any that you don&amp;rsquo;t really care about anymore.&lt;/p&gt;
&lt;p&gt;As for the button that lets you subscribe to the event (which has now occurred), a few things could happen:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The author could manually delete it.&lt;/li&gt;
&lt;li&gt;If the endpoint architecture was built into their CMS, it could be automatically suppressed when the event happens (or, more likely, proactively display when the event hasn&amp;rsquo;t happened yet; default would be to not display).&lt;/li&gt;
&lt;li&gt;The button could consist of some client-side code that would ping the endpoint itself and decide whether or not to display.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If the button still shows up after the event has occured, it&amp;rsquo;s not that big of a deal. If an agent tries to register an endpoint for an event that has occured, the worst that could happen is that it notifies immediately. Alternately, the agent could detect this when it tries to register and notify the user that there&amp;rsquo;s no point in registering it and provide the actions from the response.&lt;/p&gt;
&lt;p&gt;From the author&amp;rsquo;s standpoint, their CMS or other system could have an &amp;ldquo;LMK Control Panel&amp;rdquo; that would let them register new endpoints, manually resolve endpoints by providing messages and actions (they would &amp;ldquo;publish a resolution&amp;rdquo;), archive endpoints, get &amp;ldquo;ping analytics&amp;rdquo; of the traffic to specific endpoints, etc.&lt;/p&gt;
&lt;p&gt;And… that&amp;rsquo;s it. That&amp;rsquo;s all it does.&lt;/p&gt;
&lt;p&gt;You register an endpoint, the agent starts checking it, and then the agent lets you know when the endpoint returns in the affirmative.&lt;/p&gt;
&lt;p&gt;You have never given anyone any personal information. Your agent checking the endpoint is as anonymous as you visiting the website. There is no commitment or cognitive overhead &amp;ndash; you&amp;rsquo;re not exposed to a bunch of other events of content you don&amp;rsquo;t care about, and if the event never happens, you will never hear about it again.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s no AI to this. No magic. No problems to be solved. Like any standard or protocol, it&amp;rsquo;s just a matter of agreeing on it and evangelizing it.&lt;/p&gt;
&lt;p&gt;But…&lt;/p&gt;
&lt;p&gt;I showed this all to a friend, and he pointed out the &amp;ldquo;Subscribe&amp;rdquo; button &amp;ldquo;at the bottom of every YouTube video.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I responded:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Yeah, but I don&amp;rsquo;t want to &amp;ldquo;subscribe.&amp;rdquo; I just want to know when this ONE THING happens.&lt;/p&gt;
&lt;p&gt;There might be 20 unrelated videos between the one I watched and the Part 2 that I want to see. Just yell when Part 2 is out, and then never talk to me again and forget we ever had this interaction, unless I subscribe to something else.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And he responded with the cold, hard truth:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;That makes sense. I can understand why you&amp;rsquo;re asking for that, and can understand why creators would never want to build it&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;…[sigh]. Yeah.&lt;/p&gt;
&lt;h2&gt;Technical Postscript&lt;/h2&gt;
&lt;p&gt;The only thing I might add is a &lt;code&gt;/meta&lt;/code&gt; pseudo-endpoint that would provide data about the endpoint. It could return something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &amp;quot;created&amp;quot;: &amp;quot;2025-08-05&amp;quot;,
  &amp;quot;purpose&amp;quot;: &amp;quot;To notify when Part 2 of Awesome Blog Post Series is published&amp;quot;
  &amp;quot;contact&amp;quot;: &amp;quot;deane@deanebarker.net &amp;lt;Deane Barker&amp;gt;&amp;quot;,
  &amp;quot;happened&amp;quot;: false // So the agent can filter for active events
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your agent could retrieve this when the endpoint is registered and use the data to maintain its list and give you more information about the endpoints you&amp;rsquo;re checking.&lt;/p&gt;


&lt;section class="postscript"&gt;
&lt;hgroup class="ps"&gt;
&lt;h2&gt;Update&lt;/h2&gt;

&lt;p class="date"&gt;Added on &lt;time datetime="2025-10-12"&gt;October 12, 2025&lt;/time&gt;&lt;/p&gt;

&lt;/hgroup&gt;

&lt;p&gt;Someone wrote &lt;a href="http://verisimilitudes.net/2025-10-10"&gt;an implementation of both the client and server&lt;/a&gt; in Ada (server) and POSIX/Bash (client; presumed).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The protocol couldn&amp;rsquo;t be far simpler: A client sends a UDP packet containing the tag, and the server replies with the tag if the event has occurred or an empty packet otherwise.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;/section&gt;</description>
      <pubDate>Tue, 5 Aug 2025 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/let-me-know/</guid>
    </item>
    <item>
      <title>The Perennial Question of Diegetic Ludonarrative Kayfaybe</title>
      <link>https://live.deanebarker.net/tech/blog/fourth-wall/</link>
      <description>&lt;p&gt;Lately, I&amp;rsquo;ve been introduced to some fascinating words:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Diegesis:&lt;/strong&gt; this is the concept that audible noises in a narrative are sometimes &amp;ldquo;in&amp;rdquo; the story, meaning the characters can hear them, and sometimes they&amp;rsquo;re on the soundtrack, meaning only the viewers can hear them. (I wrote about this a bit &lt;a href="/huh/diegesis/"&gt;here&lt;/a&gt;.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ludonarrative Dissonance:&lt;/strong&gt; this is the idea that some aspects of a video game are part of a larger narrative, and other parts are part of the gameplay, and there are times when the intended narrative and the player&amp;rsquo;s actions disagree, leading to dissonance (did you know &amp;ldquo;&lt;a href="https://en.m.wikipedia.org/wiki/Game_studies"&gt;ludology&lt;/a&gt;&amp;rdquo; is the study of video games?)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Kayfaybe:&lt;/strong&gt; this is the staging of reality inside professional wrestling, both in shows and events, and as well as when interacting with fans (yes, it&amp;rsquo;s a weird word, and there doesn&amp;rsquo;t seem to be an accepted etymology for it, other than a rumor it&amp;rsquo;s pig latin-ish for &amp;ldquo;be fake&amp;rdquo;; more at &lt;a href="https://en.m.wikipedia.org/wiki/Kayfabe"&gt;Wikipedia&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not to get absurdly philosophic on you or anything, but in the entertainment or content industries, there are three &amp;ldquo;levels of existence&amp;rdquo;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The production of it (ex: the writers of a TV show)&lt;/li&gt;
&lt;li&gt;What happens in the narrative or the content (ex: the characters in the TV show)&lt;/li&gt;
&lt;li&gt;The consumption of it (ex: the person watching the TV show)&lt;/li&gt;
&lt;/ol&gt;
&lt;aside&gt;&lt;p&gt;Something I&amp;rsquo;ve always loved: this is basically a time-shifted connection from creator (#1) to consumer (#3) through the medium of story (#2).&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;When we&amp;rsquo;re watching a TV show, at some level, we&amp;rsquo;re aware that the content is happening &amp;ldquo;away&amp;rdquo; from us. We are watching entertainment, and we&amp;rsquo;re not part of it. We go where the action goes, and we have no agency or choice what happens.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s the equivalent of digital experiences? When we view a website, do we maintain that distance, mentally?&lt;/p&gt;
&lt;p&gt;Sure, we can navigate, but only within prescribed patterns. When we search, we see results that are given to us, we can&amp;rsquo;t see how they were created or get access to the repository of content. We have more agency than when we watch TV, but we&amp;rsquo;re still operating within prescribed channels.&lt;/p&gt;
&lt;p&gt;Maybe intranets or groupware are different? With those platforms we understand the larger constructs at work. We usually have some concept of IA or content organization &amp;ndash; we know that we&amp;rsquo;re looking at a &amp;ldquo;site&amp;rdquo; or a &amp;ldquo;list&amp;rdquo; in Sharepoint, for example. We&amp;rsquo;re oriented to how the information is managed. We understand the constructs; we can visualize the building blocks; we can see &lt;a href="https://m.youtube.com/watch?v=liFjsSDj1eM"&gt;The Matrix&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To what extent is this helpful? To what extent do we need or want our users to &amp;ldquo;break the fourth wall&amp;rdquo; of our information structures? Is it helpful for users to be able to mentally frame what our content is in a meta-sense?&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;To my knowledge, the fourth wall in &lt;em&gt;Friends&lt;/em&gt; was only shown once, in the episode where Chandler opens Monica&amp;rsquo;s messy closet. &lt;a href="https://www.reddit.com/r/howyoudoin/comments/zi9d8y/rare_look_at_the_4th_wall_of_monicas_apartment/"&gt;Here it is&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;In more concrete terms: what if we published and linked our content models to the content they underpin? What if every page had a link at the bottom to our data dictionary with the type definition, all the properties, and showed where in the repository the content existed, spatially and all the processes acting on it?&lt;/p&gt;
&lt;p&gt;Would that help the user&amp;rsquo;s experience? Would it help them understand the content?&lt;/p&gt;
&lt;p&gt;Gregort Litt &lt;a href="https://www.geoffreylitt.com/2025/03/03/the-nightmare-bicycle"&gt;discusses the &amp;ldquo;nightmare bicycle&amp;rdquo; concept&lt;/a&gt; from a book by Andrea diSessa:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Imagine a bicycle where the product manager said: &amp;ldquo;people don&amp;rsquo;t get math so we can&amp;rsquo;t have numbered gears. We need labeled buttons for gravel mode, downhill mode, …&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This is the hypothetical &amp;ldquo;nightmare bicycle&amp;rdquo; that Andrea diSessa imagines in his book Changing Minds.&lt;/p&gt;
&lt;p&gt;As he points out: it would be terrible! We&amp;rsquo;d lose the intuitive understanding of how to use the gears to solve any situation we encounter. Which mode do you use for gravel + downhill?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;He makes the point that humans are capable of figuring out what &amp;ldquo;mode&amp;rdquo; applies to them, so long as we make the model clear.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Good designs expose systematic structure; they lean on their users&amp;rsquo; ability to understand this structure and apply it to new situations. We were born for this.&lt;/p&gt;
&lt;p&gt;Bad designs paper over the structure with superficial labels that hide the underlying system, inhibiting their users&amp;rsquo; ability to actually build a clear model in their heads.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For casual users this might not be helpful. But for more indoctrinated users (&lt;a href="/tech/blog/information-needs-of-the-indoctrinated-audience/"&gt;I made that label up&lt;/a&gt;) that are going to be spending more than a trivial amount of time with a content repository, would help for them to &amp;ldquo;peel back the curtain&amp;rdquo; and understand how the content… works? Should we bring them inside and show them how the sausage is made?&lt;/p&gt;
&lt;p&gt;Consider that you can download the entire Wikipedia database. They have &lt;a href="https://en.m.wikipedia.org/wiki/Wikipedia:Database_download"&gt;an long page&lt;/a&gt; telling you how to do it and how to work with it. You can basically &amp;ldquo;walk backstage&amp;rdquo; and see everything, down the the level of a raw database dump.&lt;/p&gt;
&lt;p&gt;I talked about this at the Codegarden conference back in 2019. &lt;a href="https://youtube.com/watch?v=0wf35x5BZV0"&gt;Watch the first five minutes or so of this talk&lt;/a&gt;. It&amp;rsquo;s got &lt;em&gt;Friends&lt;/em&gt; and Old Spice and shirtless dudes.&lt;/p&gt;
&lt;p&gt;Also, I talk about we (those of us working in content) do &amp;ndash; &lt;/p&gt;
&lt;p&gt;&lt;em&gt;We lie for a living&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That sounds harsh, but a huge part of our job is hiding the messy reality of how things work. Sure, we know the user has some concept of a &amp;ldquo;page,&amp;rdquo; but we want to pretend that our content was birthed to a virgin and borne softly on the wings of angels right to the viewer&amp;rsquo;s browser.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;I went deeper on this concept in the foreword I wrote to &lt;a href="/tech/content-ops-foreword/" data-no-index&gt;Content Operations: From Start to Scale&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;I&amp;rsquo;ve written about this line between us and them before: see &lt;a href="/tech/blog/breaking-the-fourth-wall-of-content/"&gt;Breaking the Fourth Wall of Content&lt;/a&gt;. I said, in part:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Unlike the traditional theater where the audience sits in the gallery and views the stage through the proscenium, intranets are like theater-in-the-round or &amp;ldquo;participatory theater,&amp;rdquo; where the stage is surrounded, there&amp;rsquo;s little place to hide, and actors come walking in through the aisles among the audience. The audience is &amp;ldquo;in&amp;rdquo; the performance. Other people are doing the acting, but the lines between &amp;ldquo;us&amp;rdquo; and &amp;ldquo;them&amp;rdquo; get blurrier and in some performances, actors come and sit in the audience and maybe even pull us up on stage. When this happens, we&amp;rsquo;re not voyeurs anymore; rather, we become part of the performance.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We spend a lot of time trying to pretend our IA and content modeling constructs don&amp;rsquo;t exist. They belong to &amp;ldquo;us,&amp;rdquo; not &amp;ldquo;them.&amp;rdquo; And if they&amp;rsquo;re ever detected, that&amp;rsquo;s like being caught in public in our underwear.&lt;/p&gt;
&lt;p&gt;I feel like we need to think about this a little more.  Digital experience is usually framed as an &amp;ldquo;us vs. them&amp;rdquo; proposition. Should it be? If not always, then when? And why does this matter?&lt;/p&gt;</description>
      <pubDate>Sun, 19 Jan 2025 00:00:00 -0600</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/fourth-wall/</guid>
    </item>
    <item>
      <title>What Are We All Afraid Of?</title>
      <link>https://live.deanebarker.net/tech/blog/afraid/</link>
      <description>&lt;p&gt;&lt;table-of-contents&gt;&lt;/table-of-contents&gt;&lt;/p&gt;
&lt;p&gt;We don&amp;rsquo;t talk enough about fear.&lt;/p&gt;
&lt;p&gt;In business &amp;ndash; and in marketing especially &amp;ndash; no one is &amp;ldquo;afraid&amp;rdquo; of anything. We&amp;rsquo;re &amp;ldquo;frustrated in our ability to execute&amp;rdquo; or we&amp;rsquo;re &amp;ldquo;concerned for changing market conditions.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;We speak in the detached patois of the insider; but we&amp;rsquo;re not &amp;ldquo;afraid&amp;rdquo; of anything. That&amp;rsquo;s a such a … pedestrian emotion.&lt;/p&gt;
&lt;p&gt;And, anyway, why would we be afraid? MarTech marketing is always telling us how great we are.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re &amp;ldquo;Rockstar CMOs&amp;rdquo; or &amp;ldquo;Change Agents&amp;rdquo; or &amp;ldquo;LeadGen Ninjas&amp;rdquo; or whatever our last LinkedIn blurb read. We call ourselves this because that&amp;rsquo;s what we&amp;rsquo;re told by … ironically … the marketing of companies who want us to spend our money with them.&lt;/p&gt;
&lt;p&gt;(You&amp;rsquo;d think people who worked in marketing would be less susceptible to marketing. You&amp;rsquo;d be wrong.)&lt;/p&gt;
&lt;p&gt;But inescapably, underneath the posturing, we&amp;rsquo;re all afraid of something.&lt;/p&gt;
&lt;p&gt;In 2014, Harvard Business Review &lt;a href="https://hbr.org/2015/02/what-ceos-are-afraid-of"&gt;asked 114 CEOs&lt;/a&gt; what they were afraid of. I expected to hear things about &amp;ldquo;disruptive technology&amp;rdquo; or &amp;ldquo;market displacement&amp;rdquo; &amp;ndash; things they didn&amp;rsquo;t cause but could only react to, heroically, even in defeat. One pictures them, back against the wall, valiantly swinging their swords against the advancing hordes, standing courageously between their org chart and the abyss.&lt;/p&gt;
&lt;p&gt;But, refreshingly, the number one fear was: &amp;ldquo;being found incompetent.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;That was followed by &amp;ldquo;underachievement&amp;rdquo; and &amp;ldquo;feeling vulnerable.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Someone finally told the truth. CEOs, even.&lt;/p&gt;
&lt;p&gt;I think fear is even more deeply seated in marketing because the field is, by nature, all about the appearance of value and fit. I&amp;rsquo;m trying to avoid using the word &amp;ldquo;pretension&amp;rdquo; here, but let&amp;rsquo;s be honest &amp;ndash; marketing is about creating a mood, a feeling, a brand. In few worlds is being afraid of something a good look, and in marketing we tend to turn our campaigns back on ourselves. We want to embody what we espouse, so we buy into our own press releases.&lt;/p&gt;
&lt;p&gt;And this is where it gets personal &amp;ndash; &lt;/p&gt;
&lt;p&gt;Marketing is often viewed as &amp;ldquo;art,&amp;rdquo; at some level. Accounting or operations is so easily separable from us as people &amp;ndash; we can keep it at arm&amp;rsquo;s length, because it&amp;rsquo;s just numbers or processes. But marketing requires … interpretation, emotion, and subjective judgments about beauty and the human condition. There&amp;rsquo;s vulnerability in the exercise of that.&lt;/p&gt;
&lt;p&gt;In the aptly titled &lt;a href="https://www.amazon.com/Art-Fear-Observations-Rewards-Artmaking/dp/0961454733"&gt;Art and Fear&lt;/a&gt;, David Barnes and Ted Orland says this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The chasm widens even further when your work isn&amp;rsquo;t going well, when happy accidents aren&amp;rsquo;t happening, or hunches aren&amp;rsquo;t paying off. If you buy into the premise that art can be made only by people who are extraordinary, such down periods only serve to confirm that you aren&amp;rsquo;t.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Screwing up finance might mean you don&amp;rsquo;t understand numbers. Screwing up marketing implies you don&amp;rsquo;t understand humans.&lt;/p&gt;
&lt;p&gt;Compounding this is that our failures are inherently public. Marketing is meant to be seen, so if we fall flat on our faces, it&amp;rsquo;s not in some backroom accounting process or private warehouse operation or intranet implementation. No, if marketing goes sideways, everyone sees it. You can hide an internal process that doesn&amp;rsquo;t work, but crappy marketing campaigns are everyone&amp;rsquo;s business.&lt;/p&gt;
&lt;p&gt;And there are just so many moving parts in the average MarTech suite. The &amp;ldquo;right&amp;rdquo; answer seems to be just around the corner.&lt;/p&gt;
&lt;p&gt;TK Rader did &lt;a href="https://www.linkedin.com/posts/tkkader_heres-how-a-shitty-marketer-can-keep-a-job-activity-7016889525402509313-L9EX/"&gt;a brilliant (if satirical) write-up&lt;/a&gt; on LinkedIn about how a bad CMO can keep their job for way too long, just because it&amp;rsquo;s so easy to get caught up and camouflaged by the constant eddy of technologies, stacks, suites, and methodologies in the marketing space.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Month 1: Tell the CEO that the MarTech stack is broken … Month 3: Marketo implementation is going well. It should come together any moment now. … But wait. Nothing is converting. I know WHY. Our BRAND is totally off. The website and the look and feel needs a re-design and our messaging needs a reboot. … Bounce rates up? It wasn&amp;rsquo;t our ICP traffic anyway so don&amp;rsquo;t worry. … Ok. Sure. We&amp;rsquo;ll do this. But listen, I really think we need to re-think how we capture demand and take a PLG approach. … Month 15: It&amp;rsquo;s not my fault. The Product just can&amp;rsquo;t support the PLG motion.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is likely why CMO tenure is the lowest in the C-Suite. You can find a lot of statistics about this, so I&amp;rsquo;m hesitant to cite just one, but the average tenure of a CMO is about three years, and for a CMO in technology it&amp;rsquo;s even lower than that &amp;ndash; less than two years, according to some studies.&lt;/p&gt;
&lt;p&gt;So, we posture. We pretend. We swallow our fears as if none of that mattered.&lt;/p&gt;
&lt;p&gt;But we all know there are things that keep us awake at night. There are things lurking out there past the light of the campfire that threaten to carry us off into the darkness.&lt;/p&gt;
&lt;p&gt;What are those things?&lt;/p&gt;
&lt;p&gt;Here are some ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&amp;ldquo;Our content underperforms. It&amp;rsquo;s so repetitive. It seems like we haven&amp;rsquo;t had an original thought in a long time.&amp;rdquo;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;ldquo;Our metrics are probably wrong. I&amp;rsquo;m not tracking the right things. I know how many people visited the website, but not what they did, what they liked, or how any of this even matters. What even is a &amp;lsquo;customer journey&amp;rsquo;?&amp;rdquo;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;ldquo;Our content process is poorly architected. Campaigns take way too long to get started, and small changes turn into big messes.&amp;rdquo;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;ldquo;We aren&amp;rsquo;t using the tools we paid for, and my boss is eventually going to notice. I promised that buying Tool X would make things better, but I can&amp;rsquo;t show that we&amp;rsquo;ve even been able to integrate it.&amp;rdquo;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Do any of those sound familiar?&lt;/p&gt;
&lt;p&gt;They certainly sound familiar to me, and I&amp;rsquo;m not even in marketing, technically.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m the guy people in marketing talk to about their problems and their fears. I&amp;rsquo;m the guy people ask to come in and help them with those problems.&lt;/p&gt;
&lt;p&gt;Sometimes they&amp;rsquo;re honest about them. Often, they&amp;rsquo;re not. A lot of times, I have to read between the lines.&lt;/p&gt;
&lt;p&gt;But I always ask myself: &amp;ldquo;What is this person afraid of?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;In the next few weeks, we&amp;rsquo;re going to throw off the shackles of pretension and get really honest about what worries us and what we can do about any of it. There are solutions, but a lot of them are disguised under layers of posturing and assumption that you know exactly what your problems are and can find the corresponding solution to any of them.&lt;/p&gt;
&lt;p&gt;So, let&amp;rsquo;s turn the lights on.&lt;/p&gt;
&lt;h2&gt;Theme 1: &amp;ldquo;Our content is not very good&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve always felt like the Martech industry is more concerned with swimming pools than it is with what goes in them. We spend an inordinate time building magnificent holes in the ground yet often forget to fill them with water.&lt;/p&gt;
&lt;p&gt;I keep trying to &amp;ldquo;back people up&amp;rdquo; to content &amp;ndash; the stuff we&amp;rsquo;re supposed to be managing.&lt;/p&gt;
&lt;p&gt;But we can back up further … human action. Because, in the end, this is what we&amp;rsquo;re trying to create: some form of human action, whether it be a &amp;ldquo;hard&amp;rdquo; conversion, like a checkout, or a softer conversion, like a changed opinion or a new perspective.&lt;/p&gt;
&lt;p&gt;And this is where we often break down in Martech. So long as the architecture is in place, the content becomes sadly interchangeable. Or, at best, it becomes fatalistic &amp;ndash; like, &amp;ldquo;We&amp;rsquo;ll just throw this out there and hope it works, and if it doesn&amp;rsquo;t, well… what&amp;rsquo;re gonna do? People like what they like.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;(And, while I&amp;rsquo;m not a Luddite by any measure, do you think Generative AI is going to make this better or worse?)&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not a content strategist, and I&amp;rsquo;m just going to assume you&amp;rsquo;ve engaged a good one. A good content strategist can help at the macro level &amp;ndash; they can develop messaging strategies and architecture which are geared to getting your message across.&lt;/p&gt;
&lt;p&gt;But let&amp;rsquo;s drill down further. How do you actually create better content? How do you create content that engages people? That delights people? That they share with other people, and return to more than once?&lt;/p&gt;
&lt;p&gt;(I&amp;rsquo;m reminded of &lt;a href="https://www.youtube.com/watch?v=aOS-DG5FrwA"&gt;this 1994 long-form ad for MCI&lt;/a&gt; which I watch probably once a year and have shared with dozens of people over decades. Please, create content like this.)&lt;/p&gt;
&lt;p&gt;I have a couple ideas here.&lt;/p&gt;
&lt;h2&gt;Solution 1.1: Better ideation and collaboration on content with a CMP&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ll always believe that content gets better with transparency. Great content teams that I&amp;rsquo;ve worked with have a wide funnel at the top. There&amp;rsquo;s maximum visibility into their process &amp;ndash; they &amp;ldquo;open the box&amp;rdquo; so everyone can look inside.&lt;/p&gt;
&lt;p&gt;Great content doesn&amp;rsquo;t just come from a vaunted few. Lots of people inside your organization have one half off a great idea. The trick is to find the other half and put them together.&lt;/p&gt;
&lt;p&gt;And this might sound weird coming from a guy so closely associated with CMS, but your CMS is not the place that this happens. A CMS is a publishing platform, not really a collaboration or ideation platform.&lt;/p&gt;
&lt;p&gt;Years ago, I wrote a blog post called &lt;a href="/tech/blog/first-85/"&gt;The First 85%&lt;/a&gt;, which posited that most of the &amp;ldquo;work&amp;rdquo; that goes into content happens outside your CMS. When someone actually logs into the CMS to create an &lt;em&gt;artifact&lt;/em&gt; (the material form that the content takes), this is way, way into the process.&lt;/p&gt;
&lt;p&gt;There are platforms designed specifically for that first 85% &amp;ndash; the category is called &amp;ldquo;Content Marketing Platforms.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;(Honestly, I&amp;rsquo;ve never loved that label or acronym, because I think they have value far beyond just marketing. They&amp;rsquo;re more &amp;ldquo;Content Collaboration Platforms&amp;rdquo; or &amp;ldquo;Content Creation Platforms,&amp;rdquo; but then the acronym gets problematic…)&lt;/p&gt;
&lt;p&gt;CMPs are based around the idea that &lt;em&gt;content&lt;/em&gt; and its &lt;em&gt;artifact&lt;/em&gt; are two different things. We tend to look at a web page and says, &amp;ldquo;that&amp;rsquo;s content.&amp;rdquo; But it&amp;rsquo;s not. That&amp;rsquo;s actually an artifact &amp;ndash; a web page. The content is the message, the idea, the persuasion, all the effort and input that went into it. At artifact is just the media it got wrapped in.&lt;/p&gt;
&lt;p&gt;In perfect world, we move to &amp;ldquo;multi-artifact&amp;rdquo; or &amp;ldquo;multi-channel&amp;rdquo; content. The same content turned into multiple artifacts and pushed into multiple channels reinforces the difference.&lt;/p&gt;
&lt;p&gt;CMPs are about &lt;em&gt;content&lt;/em&gt;. They assist with all the things you need to come up with better ideas and work through the sometimes-messy process that results in great content that affects people.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Intake:&lt;/strong&gt; providing the ability for anyone in the organization to contribute ideas&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Campaign management:&lt;/strong&gt; figuring out how to group content into thematic campaigns&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Large-scale content scheduling and editorial calendaring:&lt;/strong&gt; &amp;ndash;  coordinating all the content efforts of entire organization for maximum efficient and effectiveness&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Drafting content:&lt;/strong&gt; actually putting fingers to keys and creating words or video or audio&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Commenting and discussion:&lt;/strong&gt; providing feedback and editorial review&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Work process management:&lt;/strong&gt; defining and tracking the steps that move content through editorial and publication processes&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &amp;ldquo;word du jour&amp;rdquo; in Martech is &amp;ldquo;content supply chain.&amp;rdquo; The goal is for your organization to strip the &amp;ldquo;heroics&amp;rdquo; out of content creation. No content process should require champions. No one should do battle. There should be no surprises.&lt;/p&gt;
&lt;p&gt;Content creation should be &amp;ndash; dare I say it &amp;ndash; &lt;em&gt;boring&lt;/em&gt;. In a good way. You want predictability. Reliability. And this is what a CDP seeks to provide.&lt;/p&gt;
&lt;p&gt;(I maintain it should be boring like a trip to the dentist is boring. If your trip to the dentist is anything other than &amp;ldquo;boring,&amp;rdquo; that&amp;rsquo;s never good.)&lt;/p&gt;
&lt;p&gt;Whenever I contemplate the idea of content being boring, I think back to a documentary called &lt;a href="https://www.youtube.com/watch?v=Eu3LyygiSJM"&gt;Saturday Night&lt;/a&gt;, which chronicles the weeklong development of an episode of Saturday Night Live. Contrary to the popular image of freewheeling insanity, the process of delivering an episode of SNL is incredibly precise and predictable. After watching that, I came to understand that creativity has to exist with process. It can run wild, but within guardrails that ensures that everything gets done.&lt;/p&gt;
&lt;p&gt;This is what CDPs provide. They give you the framework to abstract the process of developing content to an enforceable platform, and let your staff concentrate and creating the best content they can.&lt;/p&gt;
&lt;p&gt;Too much content either never gets started because it doesn&amp;rsquo;t get captured and developed, or derails because there isn&amp;rsquo;t a framework in place to shepherd it to publication.&lt;/p&gt;
&lt;h2&gt;Solution 1.2: Content accountability with micro-events and experimentation&lt;/h2&gt;
&lt;p&gt;I was in Helsinki once when a woman came up to me after a talk and asked, &amp;ldquo;How can I get my content creators to care about their content?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;She was stating an inconvenient truth out loud &amp;ndash; a lot of times, people just create the content and publish it. Whether or not it actually &lt;em&gt;does&lt;/em&gt; anything is not really their problem. They just throw it over the wall and hope for the best&lt;/p&gt;
&lt;p&gt;One of the problems here is simple attribution &amp;ndash; we generally don&amp;rsquo;t identify or track conversions as well as we should, so how would we know if our content was &amp;ldquo;effective&amp;rdquo;? In many cases, we can&amp;rsquo;t even define what &amp;ldquo;effective&amp;rdquo; even means.&lt;/p&gt;
&lt;p&gt;A lot of content creators know this. I don&amp;rsquo;t want to say they hide behind it, but they simply know that their accountability ends with publication. They just have to get content out the door and are less concerned with what happens after that.&lt;/p&gt;
&lt;p&gt;This is what my Finnish friend was struggling with. Her editors created a bunch of content, but after they hit publish, they didn&amp;rsquo;t have any skin in the game.&lt;/p&gt;
&lt;p&gt;One of the solutions here is to include your tracking down to the &amp;ldquo;micro-event&amp;rdquo; or &amp;ldquo;micro-action&amp;rdquo; level. So, you don&amp;rsquo;t just track cart checkouts, but you break tracking down into smaller actions. If we accept that a conversion funnel includes lots of smaller events leading up to the moment where someone provides demonstrable value, you can start tracking those events.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Don&amp;rsquo;t just track who clicks a video link from your home page. Track who plays it. Who gets to 10%. 50% 100% percent.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don&amp;rsquo;t just track page views, track scroll depth. How far &amp;ldquo;down&amp;rdquo; a piece of content does the visitor progress? (I like this so much better than time-on-page. Scrolling implies they&amp;rsquo;re doing something, and didn&amp;rsquo;t just switch windows or go to the bathroom.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once you&amp;rsquo;ve drilled down this level, you can more accurately track that wildly over-used word: &amp;ldquo;engagement.&amp;rdquo; And because you can track this more granularly, that means you can bring experimentation to bear.&lt;/p&gt;
&lt;p&gt;Experimentation is what it sounds like: trying different things, with a structured tracking system to definitively define which option works better.&lt;/p&gt;
&lt;p&gt;Consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Don&amp;rsquo;t just write one headline for that article. Write five, each taking a different angle or in a different format or tone. Then find out which one gets clicked on more often.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fiddle with design elements on the page. Try different images that completely change the tone and focus of the article.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Break the content down into different lengths. Find which one gets people to the Call to Action more consistently. Clearly, more people are likely to get to the end of shorter content, but how serious are they? Fewer people will stick with longer content, but they might be naturally more qualified leads.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Believe me when I said that you don&amp;rsquo;t know the answer to any of this. You don&amp;rsquo;t &amp;ndash; you might have theories or suspicions, but you don&amp;rsquo;t &lt;em&gt;know&lt;/em&gt;. The only people who know are the people who are consuming your content, and experimentation fundamentally becomes a way to ask them.&lt;/p&gt;
&lt;p&gt;I would never be so bold as to say that you&amp;rsquo;ll ever be able to absolutely predict with your customers want and what will resonate with them, but experimentation and micro-analytics gets you closer to refining that prediction over time.&lt;/p&gt;
&lt;h2&gt;Solution 1.3: Content desire with CDP journey analytics&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s a great scene in &lt;em&gt;Friends&lt;/em&gt; where the gang is having a trivia contest to see who knows each other better (remember: the winner gets Monica and Rachel&amp;rsquo;s apartment).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ross: Rachel claims this is her favorite movie…&lt;/p&gt;
&lt;p&gt;Chandler: Dangerous Liaisons&lt;/p&gt;
&lt;p&gt;Ross: Correct. Her actual favorite movie is…&lt;/p&gt;
&lt;p&gt;Joey: Weekend at Bernie&amp;rsquo;s!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I love this, because it reveals a truth: &lt;em&gt;we are what we consume&lt;/em&gt;. Humans have a process of &amp;ldquo;content association&amp;rdquo; and &amp;ldquo;content disassociation.&amp;rdquo; We love to be associated with &lt;em&gt;Dangerous Liaisons&lt;/em&gt; because that makes us look erudite. We might not be so open about &lt;em&gt;Weekend at Bernies&lt;/em&gt;, because that less of the image we&amp;rsquo;re going for.&lt;/p&gt;
&lt;p&gt;No matter what people say they want, what they are is what they consume. There&amp;rsquo;s a lot of content out there, and there&amp;rsquo;s no better way to figure out someone likes than to follow them around and, well, keep track.&lt;/p&gt;
&lt;p&gt;You might think this is analytics, but it&amp;rsquo;s not &amp;ndash; analytics is about tracking content consumption is aggregate. Analytics tells you that 1,000 people read your blog post.&lt;/p&gt;
&lt;p&gt;But customer data is something different &amp;ndash; customer data tells you that this person read four blog posts, a product page, and downloaded a white paper. You might not even know who &amp;ldquo;this person&amp;rdquo; is, but they left a behavior trail in their wake.&lt;/p&gt;
&lt;p&gt;Analytics is channel-centric, and cross-identity. Customer data is identity-centric, and cross-channel.&lt;/p&gt;
&lt;p&gt;Let me say that again: analytics is about a channel, in aggregate. Customer data is about… Bob. Or Mary. Or whoever.&lt;/p&gt;
&lt;p&gt;Every trail tells a story. Content recommendation platforms can use that story to predict the content someone will consume next, specifically what content is most likely to lead that journey to a conversion.&lt;/p&gt;
&lt;p&gt;You see, if you watch enough journeys, you start to recognize patterns. Then you can consider Identity X and find patterns of (1) people consuming the same type of content, and (2) people who arrive at a positive outcome (a conversion). Combine those two things and you can pretty accurately figure out what Identity X should see next.&lt;/p&gt;
&lt;p&gt;Knowing this, it becomes much clearer what content in your system is most effective. Additionally, you can &amp;ldquo;load level&amp;rdquo; your content by figuring out if you have more content of a particular topic that your visitors want, or less content. This helps drive better decisions about what content to create.&lt;/p&gt;
&lt;p&gt;Again, this isn&amp;rsquo;t just about consumption. This is about consumption as part of a larger process. Just because someone consumes something doesn&amp;rsquo;t mean anything by itself. Hell, you can get people to consume &lt;em&gt;anything&lt;/em&gt; with clickbait-ish titles.&lt;/p&gt;
&lt;p&gt;But if they consume something, and then go on to convert or provide value, then that gives you a key piece of data. Now you have some understanding of the path that your customers go on, and you can develop content to meet that need, instead of just piling on more and more content that performs well in isolation.&lt;/p&gt;
&lt;p&gt;This speaks to a larger, healthy perspective shift &amp;ndash; moving from content to journey. Very few customers consume a single piece of content, then convert. Rather, everyone is on a journey through your content domain. They move from content to content, experience to experience. The key is not concentrating on specific &amp;ldquo;islands of consumption,&amp;rdquo; but rather to understand the transitions between them. Why does Content X lead to Content Y, and is that the path someone takes before they become a conversion?&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a study in what&amp;rsquo;s called &amp;ldquo;positive deviancy.&amp;rdquo; Instead of trying to figure out what&amp;rsquo;s wrong with your content, figure out what&amp;rsquo;s right. Use tooling to examine those journeys that worked, then extract the commonalities from those and capitalize on them.&lt;/p&gt;
&lt;p&gt;We can do all the focus groups we want, and we&amp;rsquo;ll never learn exactly what makes our customers tick. I&amp;rsquo;m not saying you shouldn&amp;rsquo;t talk to your customers, but they&amp;rsquo;re probably going to tell you about &lt;em&gt;Dangerous Liaisons&lt;/em&gt;, rather than &lt;em&gt;Weekend at Bernie&amp;rsquo;s&lt;/em&gt;. We don&amp;rsquo;t want to know what customer say they want; rather, we want to examine the successful journey they actually embark on.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;…and that was the end of the series. As I said, the intention was to create more &amp;ldquo;themes,&amp;rdquo; each with their own set of &amp;ldquo;solutions,&amp;rdquo; but the project never made it to the finish line.&lt;/p&gt;
&lt;p&gt;I did find this list of topics I may have expanded upon over the life of the series.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Competitors are using AI better than me&lt;/li&gt;
&lt;li&gt;My metrics are wrong&lt;/li&gt;
&lt;li&gt;My content process is poorly architected&lt;/li&gt;
&lt;li&gt;My website isn&amp;rsquo;t performing well&lt;/li&gt;
&lt;li&gt;I could push to more channels&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;m going to get sued over accessibility&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;m not capturing enough data&lt;/li&gt;
&lt;li&gt;We aren&amp;rsquo;t using the tools we paid for&lt;/li&gt;
&lt;li&gt;Campaigns take too long to get started&lt;/li&gt;
&lt;li&gt;We can&amp;rsquo;t attribute marketing success&lt;/li&gt;
&lt;li&gt;There are problems in our digital estate that we don&amp;rsquo;t know about&lt;/li&gt;
&lt;li&gt;There are too many things going on and I can&amp;rsquo;t control it all&lt;/li&gt;
&lt;li&gt;We don&amp;rsquo;t capture or understand our data; all our decisions are based on nothing but gut feeling and we can&amp;rsquo;t defend them&lt;/li&gt;
&lt;li&gt;We can&amp;rsquo;t track traffic all the way through to revenue&lt;/li&gt;
&lt;/ul&gt;
&lt;/aside&gt;</description>
      <pubDate>Fri, 17 Jan 2025 00:00:00 -0600</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/afraid/</guid>
    </item>
    <item>
      <title>Managing Service and Content Quality Over Time</title>
      <link>https://live.deanebarker.net/tech/blog/dqm/</link>
      <description>&lt;p&gt;I&amp;rsquo;ve spent time working with young people, specifically teenage boys. Being in that stage of life, they regularly regaled me with all the cool things they were going to buy when they got old and rich &amp;ndash; as if those two things were inextricably bound together &amp;ndash; cars and houses and electronics and gadgets, etc.&lt;/p&gt;
&lt;p&gt;At about this same time, I had a very successful (adult) friend who actually bought a Lamborghini. Soon, he was complaining about how he had to have it shipped to another city to get oil changes, and had to have the wrap re-done regularly (they don&amp;rsquo;t actually paint cars anymore, I guess?). I remember asking him how much it cost to insure &amp;ndash; I don&amp;rsquo;t remember the number, but it was absurd.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Alternately, just listen to T-Pain &lt;a href="https://www.youtube.com/watch?v=zcmEpKWOYbQ"&gt;profanely explain&lt;/a&gt; how he sold his Bugatti after hearing that repairing the radiator would cost $90,000.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;This gave me a handy object lesson for my young charges &amp;ndash; &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Expensive things aren&amp;rsquo;t expensive just once.&lt;/em&gt; They continue to be expensive over time. And while lots of people dream about getting these things, not enough people think about more boring topics like maintaining them.&lt;/p&gt;
&lt;p&gt;I feel like there&amp;rsquo;s a corollary with large websites. They&amp;rsquo;re not just difficult to build and accumulate &amp;ndash; they often continue to be difficult over time. If you don&amp;rsquo;t stay on top of them, they slowly (or quickly) fall apart.&lt;/p&gt;
&lt;p&gt;I have about 6,000 URLs of content on the website you&amp;rsquo;re reading right now. That represents so many things that could go wrong. In addition to all those URLs, I also possess a weird anal-retentivity against errors that has driven me to do some hilarious things to try and ensure quality (…for a website that makes no money and that I tinker with incessantly; I have great business sense…🙄).&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s think for a second about all the things that need to happen for a website to provide the value you&amp;rsquo;re hoping for &amp;ndash; &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The website has to be up &amp;ndash; it has to provide some response to a request&lt;/li&gt;
&lt;li&gt;That response has to be valid; 200 OK; not just an error page&lt;/li&gt;
&lt;li&gt;That response has to have valid HTML constructs that make sense when interpreted by a browser&lt;/li&gt;
&lt;li&gt;Functionality you have programmed &amp;ndash; like search or taxonomy &amp;ndash; has to work correctly&lt;/li&gt;
&lt;li&gt;The content has to be minimally valid &amp;ndash; located in the right place visually, spelled right, organized correctly, etc.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And this all comes before any whiff of content strategy. All of this has to happen &lt;em&gt;before someone can even decide if your content is any good&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Here are some things that I do. Keep in mind, this is a personal website, maintained by one person. What you might do for an enterprise property with more than one team member is likely different, but a lot of the themes are the same.&lt;/p&gt;
&lt;p&gt;The first step down this road is simple &lt;strong&gt;Site Monitoring&lt;/strong&gt;. There are services that do this &amp;ndash; they make requests against your site so often just to make sure it&amp;rsquo;s still up. At the most basic level, they check for a response. Any service worth its cost will also check that the status code is a 200 (because a 404 response is still a response…)&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Pro tip: test 404s too. A fake URL should return a genuine 404, and 404s can invoke functionality that doesn&amp;rsquo;t run during any other test. I wrote a story about this: &lt;a href="/tech/blog/404-wtf/" data-no-index&gt;My Own WTF, or How to Not Handle URL Redirects&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Going a bit further, you can configure a lot of them detect specific HTML patterns, to make sure what&amp;rsquo;s coming back is what you expect and not just some &amp;ldquo;we&amp;rsquo;re down for maintenance&amp;rdquo; page.&lt;/p&gt;
&lt;p&gt;Again, these exist as paid services, but they&amp;rsquo;re also wildly easy to script yourself.&lt;/p&gt;
&lt;p&gt;Back in the early days of the internet, I used a simple VBScript for this. HTML parsing in that language was basically non-existent, so I just embedded an HTML comment as the last thing on the page. The script would make sure the HTML comment was in the response, to ensure that the page rendering didn&amp;rsquo;t error out before that point.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Incidentally, the web site was for an NFL team. The HTML comment was &lt;code&gt;GoVikes2000&lt;/code&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;A long time ago, I used &lt;a href="https://www.nagios.org/"&gt;Nagios&lt;/a&gt; for this, but that system has long-since been eclipsed by others. For a particular project, I pointed it at a hidden URL that did a lot of things in the background &amp;ndash; connected to database, tried to access specific files &amp;ndash; any one of which would throw a nasty error if something went wrong. So one URL call effectively &amp;ldquo;ran&amp;rdquo; 20 or so tests.&lt;/p&gt;
&lt;p&gt;I was given a free account at &lt;a href="https://visualping.io/"&gt;Visualping&lt;/a&gt; last year. I&amp;rsquo;ve been using that for a while and quite like it. It&amp;rsquo;s meant to detect and summarize site changes &amp;ndash; which it does very well; it&amp;rsquo;s AI summaries of changes are eerily well-done &amp;ndash; but it also doubles as a site monitoring tool.&lt;/p&gt;
&lt;p&gt;So, that&amp;rsquo;s pretty simple. But, let&amp;rsquo;s go further. Say that we know the website is up and delivering a response. How do we know that response is what we want?&lt;/p&gt;
&lt;p&gt;This is where you move into &lt;strong&gt;Automated Browser Testing&lt;/strong&gt;. These are tools and services that will instantiate a &amp;ldquo;virtual browser&amp;rdquo; in memory, load your website, then interact with it as if they&amp;rsquo;re a person until they reach some state that constitutes a valid test.&lt;/p&gt;
&lt;p&gt;For example, you could have your test bring up your search page, &amp;ldquo;type&amp;rdquo; something in the search box, &amp;ldquo;press&amp;rdquo; the submit button, and ensure some results come back. It could even comb through those results to make sure an item that you expect appears in the list.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Admission: I may or may not have inserted the word &amp;ldquo;Gumby&amp;rdquo; into a page, just to enable a test like this.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;By setting up that test, we&amp;rsquo;re &amp;ldquo;forcing&amp;rdquo; a lot of preceding functionality be available. To get a specific list of results, our search engine has to have indexed the content properly…and our search UI has to be working…and our website has to be up…etc. We&amp;rsquo;re now effectively testing the end result of a long line of dominoes to make sure something is working.&lt;/p&gt;
&lt;p&gt;(Do you need &amp;ldquo;standard&amp;rdquo; Site Monitoring if you&amp;rsquo;re using Automated Browser Testing? Probably not, but I haven&amp;rsquo;t thought about it too hard. There are probably some cases where both would make sense.)&lt;/p&gt;
&lt;p&gt;A lot of these services are based on an open-source tool called &lt;a href="https://www.selenium.dev/"&gt;Selenium&lt;/a&gt;. The one I&amp;rsquo;ve worked with is called &lt;a href="https://ghostinspector.com/"&gt;Ghost Inspector&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Years ago, I used Ghost Inspector while working on a large project over the course of about a year. It effectively ran about 100 spot checks on different parts of a the developing website once an hour. If a change in Thing A caused an error in Thing Z, many levels removed, we got notified. It was basically holistic unit testing. The tests were timed, but you can run them on-demand as well, from an API call, so you could run the tests as part of a build process.&lt;/p&gt;
&lt;p&gt;(We were open with this customer about the testing suite, and we offered to transfer our Ghost Inspector account to them so they could continue using the tests after launch. They didn&amp;rsquo;t take us up on it, and I thought they were abandoning a huge amount of hard-won value.)&lt;/p&gt;
&lt;p&gt;So, now we know the website is up, and we know that all sorts of functionality is working. But, this is just technical &amp;ndash; it&amp;rsquo;s &lt;em&gt;service&lt;/em&gt; quality, not really &lt;em&gt;content&lt;/em&gt; quality. How can we be sure the website is returning what we want it to?&lt;/p&gt;
&lt;p&gt;This is where we move into &lt;strong&gt;Digital Quality Management&lt;/strong&gt; (sometimes called &amp;ldquo;Digital Governance Management&amp;rdquo; &amp;ndash; the term is currently a little slippery).&lt;/p&gt;
&lt;p&gt;There are an &lt;a href="https://www.g2.com/categories/digital-governance"&gt;entire category&lt;/a&gt; of software products here. They consume your website (remember, we&amp;rsquo;re just assuming that everything is working &amp;ndash; if it&amp;rsquo;s actually broken we would have caught it by now), and they verify and measure multiple factors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance:&lt;/strong&gt; how fast is the website responding, both from a service response and a client response; is any particular page slow to respond or render?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SEO:&lt;/strong&gt; how well is a particular URL performing in relation to a targeted set of keywords?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Accessibility:&lt;/strong&gt; are there accessibility violations at any URL, from something as simple as missing ALT text in an image, to things more complex, like poor color contrast (even inside individual images)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These platforms will crawl your website regularly (or on-demand), check for compliance, then send you notifications and reports about issues. Some of them will plug into your CMS to provide pre-publish checking, but they tend to be CMS-agnostic, as content for large enterprise properties often comes from many different sources. They consume the &lt;em&gt;finished product&lt;/em&gt;, regardless of what was used to generate it.&lt;/p&gt;
&lt;p&gt;These platforms come pre-configured with lots of rules for the above, but what gets interesting is when you build out custom rules.&lt;/p&gt;
&lt;p&gt;I have a homegrown DQM system running against my site (note: I do &lt;em&gt;not&lt;/em&gt; recommend this &amp;ndash; it&amp;rsquo;s an unholy mess of LINQpad scripts &amp;ndash; but it just kind of grew over time). You can see the latest report &lt;a href="/meta/report/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here are a few things I check for &amp;ndash; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each page must have one &amp;ndash; and only one &amp;ndash; H1 tag&lt;/li&gt;
&lt;li&gt;H2, H3, and H4 tags must be in the correct order, meaning an H3 can&amp;rsquo;t appear unless preceded by an H2; you can&amp;rsquo;t skip heading levels&lt;/li&gt;
&lt;li&gt;The clickable text of any link to a URL ending in &amp;ldquo;.pdf&amp;rdquo; must end with &amp;ldquo;(PDF)&amp;rdquo; so I&amp;rsquo;m not blind-linking someone to anything but HTML&lt;/li&gt;
&lt;li&gt;All internal site links should be relative (they should not include the domain), and they must either have a dot (&amp;ldquo;.&amp;rdquo;) or end in a slash (this is just a rule I made to be consistent…)&lt;/li&gt;
&lt;li&gt;…and so on &amp;ndash; I think there are 32 rules I run. I add a new one every once in a while, and some are temporary rules just to make sure some problem is fixed and doesn&amp;rsquo;t reoccur.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I can allow exceptions to these rules. Some pages break a rule or two, and I can &amp;ldquo;pre-acknowledge&amp;rdquo; this to avoid it throwing errors. I&amp;rsquo;ve even drilled this down to the HTML element level &amp;ndash; I can exempt single elements from particular rules if I need to.&lt;/p&gt;
&lt;p&gt;There are 30+ tests I run &amp;ndash; you can see them at &lt;a href="/meta/report/"&gt;the bottom of the report&lt;/a&gt;. Some are specific to my situation, some are related to some weird one-off problems that happened at some point (I should probably prune these…), and some are just good tests in general. Most all DQM tools will let you write your own tests to enforce your own concepts of quality and governance.&lt;/p&gt;
&lt;p&gt;So, now we&amp;rsquo;ve ensured the site is responding, that&amp;rsquo;s it&amp;rsquo;s sending back a valid response, and the content its sending back is performant, accessible, search-friendly, and complies with whatever arbitrary rules we want to put in place.&lt;/p&gt;
&lt;p&gt;Congratulations. We&amp;rsquo;ve achieved a minimal level of quality.&lt;/p&gt;
&lt;p&gt;This is getting long, but there are some other practices I&amp;rsquo;ll talk about in future installments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Systemic spellcheck.&lt;/strong&gt; This is not red squiggly lines in a text editor. Rather, how do you spellcheck &lt;em&gt;every last one&lt;/em&gt; of the million-plus words on a large website. For that matter, what even constitutes a &amp;ldquo;word&amp;rdquo;… but we&amp;rsquo;ll save that rabbit hole for the future.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Something I&amp;rsquo;m calling &lt;strong&gt;Novel Entity Analysis.&lt;/strong&gt; A lot of problems manifest with the spontaneous appearance of something new &amp;ndash; with 6,000 URLs and a million-plus words, it should be fairly rare that a new, previously unobserved token appears anywhere. And if it does, I should know about it. The same goes for new URLs and new HTML constructs (tag+ID, or tag+class).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simple &lt;strong&gt;random page review.&lt;/strong&gt; I have the ability to pull a truly random page from my website with one-click. Lemme tell you, you&amp;rsquo;d be &lt;em&gt;amazed&lt;/em&gt; at the stuff you find when you wander through content you haven&amp;rsquo;t looked at in years…&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;aside&gt;&lt;p&gt;Note: as I mentioned at the opening, this blog post belonged to an abandoned project, so there will not be any future installments. If you really want to know what I did for the above, &lt;a href="/contact/"&gt;get in touch&lt;/a&gt; and I&amp;rsquo;ll walk you through it.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;So, in the absence in covering those topics today, let me leave you with these three &amp;ldquo;meta issues&amp;rdquo; you&amp;rsquo;re going to have to figure out when implementing a digital quality program in any form. None of these issues are technical, but here the point to the larger issue with these programs &amp;ndash; &lt;/p&gt;
&lt;p&gt;&lt;em&gt;The biggest threat to digital quality is that no one cares, or interest wanes over time, so all of your wonderful plans amount to nothing.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So, to prevent that &amp;ndash; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You&amp;rsquo;ll need to &lt;strong&gt;manage exceptions.&lt;/strong&gt; Rules will be broken, often for good reasons, and how do specify that &amp;ldquo;this is wrong, but okay,&amp;rdquo; to avoid pointless alarm? Understand that &lt;em&gt;this isn&amp;rsquo;t a minor issue&lt;/em&gt;. It&amp;rsquo;s not just about convenience &amp;ndash; you need to acknowledge issues even if you don&amp;rsquo;t fix them, because persistent unacknowledged issues are the first step to people ignoring the system altogether. How do you get people to understand that every issue is a problem? If they think they can routinely ignore stuff, they will ignore everything.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You&amp;rsquo;ll need to &lt;strong&gt;manage notifications.&lt;/strong&gt; How do tell someone that something is wrong? Do you push notifications? At what severity? If you have people pull them from some report, how do you ensure this gets done? What auditing processes do you put in place to make sure that things aren&amp;rsquo;t just getting ignored?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You&amp;rsquo;ll need to &lt;strong&gt;manage follow-up.&lt;/strong&gt; For me, it&amp;rsquo;s easy (spoiler: I handle everything), but for larger organizations, who does what? How do you manage the triage, task assignment, discussion, and backlog that results from these things? Unquestionably, &lt;em&gt;you are creating new work&lt;/em&gt;. To be sure, it&amp;rsquo;s good and necessary work, but you&amp;rsquo;ll need processes to manage it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, there&amp;rsquo;s a lot here. I&amp;rsquo;ll just conclude by saying that &lt;em&gt;this matters, because content matters&lt;/em&gt;. If you publish something on the Internet, please take care of it. Make sure it doesn&amp;rsquo;t suck, or start to suck over time.&lt;/p&gt;
&lt;p&gt;The Internet can be a mess. Let&amp;rsquo;s all keep our ends of it clean.&lt;/p&gt;</description>
      <pubDate>Mon, 6 Jan 2025 00:00:00 -0600</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/dqm/</guid>
    </item>
    <item>
      <title>The Looming Art of Gist Management</title>
      <link>https://live.deanebarker.net/tech/blog/gist-management/</link>
      <description>&lt;p&gt;Lots of people think content strategy is a dying art, in the age of AI.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;I think that &lt;em&gt;content strategy has never been more important.&lt;/em&gt; AI has quietly forced content strategy to the forefront through a dynamic that a lot of people don&amp;rsquo;t quite realize yet.&lt;/p&gt;
&lt;p&gt;But let&amp;rsquo;s start by going way, way back. Let&amp;rsquo;s talk about how the history of how we develop for the web has always been a battle for control &amp;ndash; &lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been developing for the web for… 30-ish years? Since 1995, I think (the web was born in 1993, so this is pretty close to the beginning). I began in HTML 1.0 on Internet Explorer 1.0, if that tells you anything.&lt;/p&gt;
&lt;p&gt;I remember writing my first HTML page in Notepad, and when I realized that whatever it put in the &lt;code&gt;TITLE&lt;/code&gt; tag would appear in the title bar of the browser window, I felt like an elite hacker.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;I had someone bring up a website back in 1996 or so that had something new called an &amp;ldquo;animated GIF.&amp;rdquo; It didn&amp;rsquo;t move. I told him, with palpable disdain, &amp;ldquo;Well, you&amp;rsquo;re on Internet Explorer 1. Why haven&amp;rsquo;t you updated to version 2?&amp;rdquo;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;The first websites were intensely static, and built to stay that way. They only came one way. We designed for 640-pixels wide, because that&amp;rsquo;s basically the only thing we count on. Everyone had a 15&amp;rdquo; CRT, except for your rich friend who didn&amp;rsquo;t have any student loans &amp;ndash; he had a 17&amp;rdquo;. Back then, you had a wide array of font choices, so long as your choice was Times New Roman. Design options and browser choices were so limited that you could be pretty confident that what you &amp;ldquo;designed&amp;rdquo; would come out the same way.&lt;/p&gt;
&lt;p&gt;But, over time, the web has been in a steady, constant process of relinquishing control to the person who consumes the content.&lt;/p&gt;
&lt;p&gt;The web was a visual medium. We were determined to control that visual. How things looked was as important as the content being delivered.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Browsers eventually got some sense of user styles. You could start modifying the way pages looked, for the sake of accessibility. And then we got true user styles. People could change how websites looked, ever so slightly.&lt;/p&gt;
&lt;p&gt;I remember a friend being so infuriated that I was adding custom user styles to his website that he created a system to randomize his CSS class names. This sounds ridiculous in retrospect, but you had to understand the times back then &amp;ndash; we were stone-cold determined to deliver content &lt;em&gt;our&lt;/em&gt; way, period. We were obsessed with control.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Slowly, monitors got bigger. Screen sizes expanded. We couldn&amp;rsquo;t count on standard widths anymore, so we had to design for the lowest common denominator. Then new browsers came out, and we added all sorts of hacks to figure out what browser you were on and account for it.&lt;/p&gt;
&lt;p&gt;Eventually, monitors and graphics cards got better to the then-mind-blowing point where the monitor was sometimes bigger than you wanted your browser to be. So people would browse in a non-maximized window, which lead to all sorts of odd sizing.&lt;/p&gt;
&lt;p&gt;New browsers showed up. We had Mosaic, then Internet Explorer, then Mozilla showed up, and Opera was always lurking in the background. And they all had different rendering engines. Cross-browsing testing was a total crapshoot.&lt;/p&gt;
&lt;p&gt;Then RSS happened. This was (and is) a niche protocol (yes, yes, I know you and I love it, but does your grandmother?). However, the key is that it first introduced the basic idea of restructuring content for consumption elsewhere.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a quote from &lt;a href="https://web.archive.org/web/20110809151456/http://news.cnet.com/2100-1001-203893.html"&gt;the W3C release&lt;/a&gt; in 1997:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Code-named Aurora, the software will let PC users customize the way they view information on their desktops.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Content creators were suddenly confronted with the idea that their content could be stripped of its visuals and consumed outside their control (albeit with their permission). This was the first step in multi-channel publishing, and introduced us to concepts of channel rigidity &amp;ndash; some things just didn&amp;rsquo;t work in RSS. A lot of us limited the information to a preview and drove visitors back to the website &amp;ndash; where we had total control, dammit! &amp;ndash; but others developed different templates and renderings for RSS.&lt;/p&gt;
&lt;p&gt;And then mobile devices happened &amp;ndash; &lt;/p&gt;
&lt;p&gt;Suddenly, we couldn&amp;rsquo;t count on &lt;em&gt;anything&lt;/em&gt;. So we created mobile sites (&amp;ldquo;m-dots&amp;rdquo;) to hold onto control as long as possible, then eventually conceded to responsive design and let the container dictate the visuals.&lt;/p&gt;
&lt;p&gt;This was a monumental shift, mentally. We were conceding that &lt;em&gt;what something looked like&lt;/em&gt; was less important than the content we delivered. We made sure the content looked acceptable, but designs slowly became less complicated. We got back to simple single-column vertical scrollers (remember when we were floating everything…?). Since we couldn&amp;rsquo;t control how things looked exactly, we just made sure the content came through.&lt;/p&gt;
&lt;p&gt;We used to be in control. We weren&amp;rsquo;t anymore. We learned to accept this and adapt. It used to be important to make your visuals look the same everywhere. But suddenly it became more important just make sure the general design ideas and themes came through everywhere.&lt;/p&gt;
&lt;p&gt;Enter AI &amp;ndash; &lt;/p&gt;
&lt;p&gt;Weirdly, this is exactly the same thing, just down a different axis.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re not letting go of &lt;em&gt;visual&lt;/em&gt; control anymore. We&amp;rsquo;re letting go of &lt;em&gt;cognitive&lt;/em&gt; control. The current batch of AI tools is interpreting everything we create. It&amp;rsquo;s synthesizing it and translating it.&lt;/p&gt;
&lt;p&gt;The effect on delivery is paradigm-shifting &amp;ndash; &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Visuals are basically gone. Content is being delivered in other apps and tools that we have zero control over, so designing something might become extraneous.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Exact wording and phrasing is even gone. AI is like a big game of &amp;ldquo;Telephone&amp;rdquo; &amp;ndash; our exact words are being synthesized and changed and then delivered with the same claimed authority as the original author.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This shift is even more monumental than anything that has happened in the browser or front-end design wars. Not only can&amp;rsquo;t you control what your content looks like, but you can&amp;rsquo;t even control the words or visuals it&amp;rsquo;s delivered in.&lt;/p&gt;
&lt;p&gt;(And no, video and audio won&amp;rsquo;t help. Before long, more people will read, watch, or listen to AI-summarized output more than they consume the source.)&lt;/p&gt;
&lt;p&gt;So, where does this leave us? We&amp;rsquo;ve spent a long time designing content, and managing content, and now that&amp;rsquo;s becoming less and less important. I&amp;rsquo;ve seen predictions that the web will eventually succumb to &amp;ldquo;AI agents&amp;rdquo; that just gather stuff and do tasks for us.&lt;/p&gt;
&lt;p&gt;Weirdly, the agent concept was always the idea. Tim Berners-Lee &amp;ndash; the guy who invented the web &amp;ndash; wrote a landmark article back in 2001 called &lt;a href="https://lassila.org/publications/2001/SciAm.html"&gt;The Semantic Web&lt;/a&gt;. This was the abstract:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A new form of Web content that is meaningful to computers will unleash a revolution of new possibilities&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Berners-Lee was pushing &lt;a href="https://en.wikipedia.org/wiki/Resource_Description_Framework"&gt;RDF&lt;/a&gt; &amp;ndash; a method of infusing the web with machine-understandable meaning, so that computers could understand it all and do things for us. For the founder of the web, the &amp;ldquo;prescriptive web&amp;rdquo; was just a pause on the road to his ultimate goal.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Read &lt;a href="https://learning.oreilly.com/library/view/programming-the-semantic/9780596802141/"&gt;Programing the Semantic Web&lt;/a&gt; sometime. That blew my mind 15 years ago.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;However, AI almost seems to have gone &amp;ldquo;around&amp;rdquo; RDF and achieved basically the same thing. Instead of being fed structure, AI is just trying to figure out structure itself.&lt;/p&gt;
&lt;p&gt;AI is basically a new channel. Should we &amp;ldquo;publish&amp;rdquo; to it like we publish to social and email?&lt;/p&gt;
&lt;p&gt;Which brings me back to my to my original point &amp;ndash; &lt;/p&gt;
&lt;p&gt;When you strip away control of the visuals, which we&amp;rsquo;ve been doing for 20 years, and you strip away control over the exact content, which AI is steadily doing now, what&amp;rsquo;s left?&lt;/p&gt;
&lt;p&gt;The message.&lt;/p&gt;
&lt;p&gt;The core point.&lt;/p&gt;
&lt;p&gt;The… gist.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s the gist? That&amp;rsquo;s the basic idea. That&amp;rsquo;s the change you want to influence in the person who consume your content. It&amp;rsquo;s the idea you want to put in their head. The action you want them to take. The impression you want them to get.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;I spent some time in the Navy. I was at Amphibious Assault School watching big hovercraft come ashore. They careened all over the place, and I realized they had no wheels or rudder or anything else in contact with the ground. I asked our instructor how they steer, and he responded, &amp;ldquo;Well, it&amp;rsquo;s less about &lt;em&gt;steering&lt;/em&gt; and more about… &lt;em&gt;suggesting&lt;/em&gt;.&amp;rdquo;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;In the future, all we can really count on is the suggestion… the gist.&lt;/p&gt;
&lt;p&gt;In politics, people are constantly told to stay &amp;ldquo;on message.&amp;rdquo; Good political communicators know that with the frenzied, fractured, biased media world in which we live, they have to keep hammering away at simple points to be heard. They have to relentlessly push a core idea. They can&amp;rsquo;t control what happens to their words after they say them, so they have to stay true to the gist, or everything will get lost.&lt;/p&gt;
&lt;p&gt;And the gist is where content strategy rules. You have designers and you have developers and you have copywriters, but technology is advancing to the point where the value these people add can be circumvented. Things don&amp;rsquo;t have to be designed, or programmed, or even &lt;em&gt;written&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;But the gist will always be there. The new content strategist is going to understand that they can&amp;rsquo;t count on anything anymore, they can only try to make sure the the idea gets through. They will ideate campaigns and write words and film videos with the understanding that 95% of people will consume them through some level of AI filtering, summarization, or contextualization. And they&amp;rsquo;ll make sure the gist keeps coming through.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not visual anymore. It&amp;rsquo;s not words anymore. Instead, we&amp;rsquo;re trying to persuade machines to deliver the ideas we want to get across.&lt;/p&gt;
&lt;p&gt;To be clear: &lt;em&gt;the new skill of content strategy is your ability to train the machine.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In that sense, it&amp;rsquo;s a whole new world.&lt;/p&gt;</description>
      <pubDate>Tue, 31 Dec 2024 00:00:00 -0600</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/gist-management/</guid>
    </item>
    <item>
      <title>Software Isn't the Problem</title>
      <link>https://live.deanebarker.net/tech/blog/software-isnt-the-problem/</link>
      <description>&lt;p&gt;Everyone wants to believe their shortcomings lie elsewhere. Humans are &lt;em&gt;really&lt;/em&gt; good at placing the blame on anything but themselves.&lt;/p&gt;
&lt;p&gt;Often, this surfaces as limitations that we&amp;rsquo;ve convinced ourselves exist and are holding us back.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If only I didn&amp;rsquo;t have to do my chores, I could be a better guitar player.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If only the gym was closer, I would workout more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If only traffic wasn&amp;rsquo;t so bad in the morning, I wouldn&amp;rsquo;t be late for work.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If only…&lt;/p&gt;




&lt;table-of-contents title="Contents" selector="h2, h3, h4"&gt;&lt;/table-of-contents&gt;

&lt;h2&gt;The Projection Defense&lt;/h2&gt;
&lt;p&gt;This is called &lt;a href="https://en.wikipedia.org/wiki/Psychological_projection"&gt;projection&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Psychological projection is a defense mechanism in which the human ego defends itself against unconscious impulses or qualities (both positive and negative) by denying their existence in themselves while attributing them to others&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;No, no, you&amp;rsquo;re right &amp;ndash; it&amp;rsquo;s not &lt;em&gt;you.&lt;/em&gt; It&amp;rsquo;s clearly everyone else that&amp;rsquo;s wrong.&lt;/p&gt;
&lt;p&gt;We take limitations or shortcomings that are inherent to us, and we project them onto some other thing. &lt;em&gt;That thing&lt;/em&gt; is the problem, not us.&lt;/p&gt;
&lt;p&gt;&lt;img src="/tech/blog/images/software-isnt-the-problem/skinner-meme-300x200.jpg" class="center" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;We do this with software all the time. We blame software limitations for what ails our organizations. If only we had better software, things would be different. There&amp;rsquo;s no point trying to be better, because we&amp;rsquo;re hobbled by poor software.&lt;/p&gt;
&lt;p&gt;Some of this might be true, certainly. But a non-trivial portion of it isn&amp;rsquo;t. We put too much emphasis on software&amp;rsquo;s abilities to make up for our shortcomings.&lt;/p&gt;
&lt;p&gt;We look at new software like a kid with their nose pressed up against the window of a candy store. If only we had that software package, then everything would be different.&lt;/p&gt;
&lt;p&gt;But…would it? If you had the latest software package for whatever industry or practice you&amp;rsquo;re managing, would everything really be different? Would you expand to your full potential and begin to make leaps and bounds toward your goals?&lt;/p&gt;
&lt;p&gt;If the gym was a little closer, would you really become the triathlete you&amp;rsquo;re sure you &lt;em&gt;could&lt;/em&gt; be?&lt;/p&gt;
&lt;p&gt;Probably not. We project negativity onto existing software and positivity onto software not-yet-acquired, but often the limitations are outside the software. It&amp;rsquo;s not the software holding us back.&lt;/p&gt;
&lt;p&gt;My talk for 2017 was called &lt;a href="https://vimeo.com/221710557"&gt;Why Content Projects Fail&lt;/a&gt;. I gave it 6-7 times around the world, and this slide below never failed to get a laugh.&lt;/p&gt;
&lt;p&gt;This is all of us:&lt;/p&gt;
&lt;p&gt;&lt;img src="/tech/blog/images/software-isnt-the-problem/software-will-save-us-300x171.jpg" class="center" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;In my talk, I discussed why we project our problems onto software:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There&amp;rsquo;s a good chance significant parts of our problem originated externally to technology&lt;/li&gt;
&lt;li&gt;But, we tend not to look to people, governance, or process, because these things exist now&lt;/li&gt;
&lt;li&gt;If the problems could been fixed without new technology…then why weren&amp;rsquo;t they? We had all the control.&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s easy to say, &amp;ldquo;Things will be better when we have new technology because we&amp;rsquo;ll have something we don&amp;rsquo;t have now. We just don&amp;rsquo;t have the right tools now.&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Blaming software is a handy way out of awkward questions. And software has no opinion and no defense &amp;ndash; your old software can&amp;rsquo;t shirk this blame, and your new software can&amp;rsquo;t realistically manage your expectations.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve written about this before in relation to several different CMS features &amp;ndash; &lt;/p&gt;
&lt;p&gt;&lt;a href="/tech/blog/content-personalization-reality-check/"&gt;Content Personalization: A Reality Check&lt;/a&gt; (October 2016):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The sad truth: most organizations can barely manage a single effective version of their content, much less multiple versions. No client I know has multiple versions of their content just sitting around, tailored to different audiences. This is something you see in case studies, but that few organizations actually have the resources to do.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="/tech/blog/truth-about-cms-form-builders/"&gt;The Truth About CMS Form Builders&lt;/a&gt; (January 2017):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;After your website launched, how many forms did you need built in the following year? For most of my clients, the answer is &amp;ldquo;not many.&amp;rdquo; How many forms will you need built in the next year? It&amp;rsquo;s usually the same answer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="/tech/blog/you-want-collaboration-not-workflow/"&gt;You Want Collaboration, Not Workflow&lt;/a&gt; (June 2014):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Seemingly every project has grand plans around workflow. Editors are going to submit content to an approver, then it&amp;rsquo;s going to an editorial committee of which 60% need to sign off, then it&amp;rsquo;s going to a metadata specialist, then the legal department, and then it will be published when the temperature in Moscow hits 60 degrees and the Oakland Raiders win the Superbowl, etc. Of course, none of this ever happens.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I sound like a cynic, but 22 years in this business has taught me that all of the above is accurate.&lt;/p&gt;
&lt;p&gt;Truth: if the shackles were thrown off and they had all the marketing tools at their disposal…many (most?) customers just wouldn&amp;rsquo;t know what to do with them all. They&amp;rsquo;ve pinpointed their problems as deficient or missing software, but this implies that if this shortcoming was patched, everything would fall into place, and &lt;em&gt;this is just not true in so many cases&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This reminds me of &lt;a href="https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it"&gt;YAGNI&lt;/a&gt;, the programming principle of &amp;ldquo;You aren&amp;rsquo;t gonna need it.&amp;rdquo;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[…] a programmer should not add functionality until deemed necessary.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Perhaps we should modify it to &amp;ldquo;YAGUI: You aren&amp;rsquo;t gonna use it.&amp;rdquo;&lt;/p&gt;
&lt;h2&gt;The Boring Truth&lt;/h2&gt;
&lt;p&gt;Now, I&amp;rsquo;m not saying all marketing tools are pointless. This market is ruthless, and if they didn&amp;rsquo;t work, they&amp;rsquo;d get drummed out of existence. But they&amp;rsquo;re still around, so &lt;em&gt;someone&lt;/em&gt; is getting value from them.&lt;/p&gt;
&lt;p&gt;How do they do it? Magic?&lt;/p&gt;
&lt;p&gt;Nope. Just boring stuff like &amp;ndash; &lt;/p&gt;
&lt;h3&gt;Adequate Staffing&lt;/h3&gt;
&lt;p&gt;If you&amp;rsquo;re planning an expansion of your digital marketing technology, you need to take stock of your staffing. This stuff takes work. Is everyone sitting around with nothing to do? If not, you need to be prepared to hire.&lt;/p&gt;
&lt;p&gt;In fact, I just read &lt;a href="https://www.amazon.com/Why-need-content-team-build/dp/1720128448"&gt;a book entirely dedicated to the idea of building a &amp;ldquo;content team,&amp;rdquo;&lt;/a&gt; which is an idea foreign to a lot of organizations because content just kinda…happens, or &amp;ldquo;someone from marketing handles that.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;And it&amp;rsquo;s not just you &amp;ndash; &lt;a href="https://www.newyorker.com/magazine/2018/11/12/why-doctors-hate-their-computers"&gt;this article&lt;/a&gt; is a blistering indictment of the implementation of an electronic records system at a hospital. They found that it meant they had to hire &lt;em&gt;more&lt;/em&gt; people &amp;ndash; each doctor now had to have a &amp;ldquo;scribe&amp;rdquo; follow them around to patient visits to &amp;ldquo;work the software&amp;rdquo; while the doctor did their original job.&lt;/p&gt;
&lt;h3&gt;Adequate Training&lt;/h3&gt;
&lt;p&gt;Software likes to pretend that it&amp;rsquo;s easy to use and everything &amp;ldquo;just works.&amp;rdquo; This is compounded in the era of AI and ML (&amp;ldquo;It learns by itself!!&amp;rdquo;). Don&amp;rsquo;t believe it. You&amp;rsquo;ll likely need formal training to activate the software and evaluate the results.&lt;/p&gt;
&lt;p&gt;Consider: Sitecore is so complex that it has an entire service line &amp;ndash; &lt;a href="https://www.sitecore.com/getting-started/maturing-digitally/about-sbos"&gt;Sitecore Business Optimization Strategies&lt;/a&gt; &amp;ndash; that &lt;em&gt;uses your Sitecore installation for you&lt;/em&gt;. You can buy a car and a driver in the same transaction.&lt;/p&gt;
&lt;h3&gt;Adequate Time&lt;/h3&gt;
&lt;p&gt;Transformation doesn&amp;rsquo;t happen overnight. You&amp;rsquo;re going to make a lot of mistakes. Once you have all the tools at your disposal that you were convinced you need, give yourself a year to make All the Mistakes™.&lt;/p&gt;
&lt;p&gt;You need time to absorb all that new functionality, figure out how to work it into your processes, probably shed or swap some people, and then actually get down to business. Search for the phrase &amp;ldquo;&lt;a href="https://duckduckgo.com/?q=software+adoption"&gt;software adoption&lt;/a&gt;&amp;rdquo; sometime. There have been many, many books written on the psychology and time required to get people to adopt new processes. This is not just like flipping a switch.&lt;/p&gt;
&lt;p&gt;(Michael Sampson has written a good book here &amp;ndash; &lt;a href="https://michaelsampson.net/books/useradoption/"&gt;User Adoption Strategies&lt;/a&gt;. It&amp;rsquo;s a bit Sharepoint-centric, but still widely applicable.)&lt;/p&gt;
&lt;h3&gt;Adequate Leadership and Vision&lt;/h3&gt;
&lt;p&gt;If the things you want to do are as transformational as you believe, then you&amp;rsquo;re going to need to paint a picture for the rest of the organization to get on board. You&amp;rsquo;re going to have to slay political dragons and fight for budget, people, and reorganization. We might need to reframe your organization&amp;rsquo;s entire relationship to its content and communications channels.&lt;/p&gt;
&lt;p&gt;A client was just in my office last week to discuss rebuild of their website. As we talked about different technologies we could bring to bear, it became obvious that their relationship with their customer was still rooted to when they started the company in 1986. Some of their processes were just thinly-veiled versions of the originals. They needed to completely change how they related to their customer.&lt;/p&gt;
&lt;p&gt;New technology might lay these situations bare, and there&amp;rsquo;s no ThanosSnap 5.0™ that&amp;rsquo;s going to magically fix what you find. You might be waking a sleeping giant, and you need to make sure you have the leadership, vision, and executive backing to see it through when it unravels.&lt;/p&gt;
&lt;p&gt;…&lt;/p&gt;
&lt;p&gt;Software doesn&amp;rsquo;t work in a vacuum. It&amp;rsquo;s nothing but a tool that assists an otherwise healthy and prepared organization to move forward. It&amp;rsquo;s a force multiplier &amp;ndash; it can absolutely make you better, but you have to bring something to the party.&lt;/p&gt;
&lt;h2&gt;The Awkward Part&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s what gets tricky as a someone in software and service sales: &lt;em&gt;how do you tell someone that the software isn&amp;rsquo;t the problem?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I was at a &lt;a href="https://www.boye-co.com/groups/cms-experts"&gt;Boye and Company CMS Experts Group&lt;/a&gt; meeting in Brooklyn two weeks ago, and we had a raging discussion about the &lt;a href="https://www.theregister.co.uk/2019/04/23/hertz_accenture_lawsuit/"&gt;Hertz Accenture fiasco&lt;/a&gt; that&amp;rsquo;s in the news right now. Some of us expressed amazement at the $32 million price tag. Clearly, Hertz is a big customer with big needs, and there&amp;rsquo;s a lot of integration there, but…&lt;em&gt;$32 million?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We imagined someone at Accenture and Adobe just selling Hertz everything they could toss into the deal, whether Hertz could use it or not.&lt;/p&gt;
&lt;p&gt;Of course, we debated, what&amp;rsquo;s the alternative? As people selling software and sales, do we need to pretend that customers can use everything we sell? Or should we advocate for our customers and tell them that we just don&amp;rsquo;t think they&amp;rsquo;re going to get any use out of Feature X?&lt;/p&gt;
&lt;p&gt;A pause…then &lt;a href="https://10up.com/about/#employee-john-eckman"&gt;John Eckman from 10Up&lt;/a&gt; said what everyone was thinking:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you do that, then you&amp;rsquo;re passing judgment on their skill level.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And he&amp;rsquo;s right. If I tell a customer they shouldn&amp;rsquo;t buy a personalization engine because they&amp;rsquo;re not going to use it, what I&amp;rsquo;m really saying is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The problem isn&amp;rsquo;t the software. The problem is &lt;em&gt;you&lt;/em&gt;. You just don&amp;rsquo;t have the skill to use that.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It might be graceless, but there it is.&lt;/p&gt;
&lt;p&gt;&lt;img src="/tech/blog/images/software-isnt-the-problem/problem-is-you-300x178.jpg" class="center" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Obviously, you can&amp;rsquo;t say that. But what you &lt;em&gt;can&lt;/em&gt; do is nudge this customer toward a more holistic approach to their software when they have unrealistic expectations. From &lt;a href="/tech/blog/content-personalization-reality-check/"&gt;the prior post about personalization&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When I discussed personalization with a client once, I kept asking them, &amp;ldquo;Okay, now that we know who the visitor is, what do you want to do about it?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;They kept responding: &amp;ldquo;Well, we want to change the value proposition.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This isn&amp;rsquo;t enough.&lt;/em&gt; There is no button in your CMS that says &amp;ldquo;Change the value proposition.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My client was convinced the software would Just Work.&lt;/p&gt;
&lt;p&gt;In reality, personalization actually made their job &lt;em&gt;harder&lt;/em&gt; because it put them in a position where they now had to bring acute content strategy to bear to respond to an identified audience. Put another way: ignorance is bliss, and if your software can now resolve your ignorance and enlighten you to tiny changes in your audience demographic, &lt;em&gt;are you skilled enough to do anything about it?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;These things can&amp;rsquo;t be easily deconstructed, and the software can&amp;rsquo;t save you. Some problems are complex just because they&amp;rsquo;re complex. This stuff isn&amp;rsquo;t magic.&lt;/p&gt;
&lt;p&gt;Customers need to be introduced to the breadth of what they need to do, then guided into a integrated approach that circles all the organizational wagons around whatever uber-feature they have their eye on.&lt;/p&gt;
&lt;p&gt;Otherwise, you just aren&amp;rsquo;t gonna use it.&lt;/p&gt;
&lt;h2&gt;Words with Friends&lt;/h2&gt;
&lt;p&gt;I wanted to make sure I wasn&amp;rsquo;t all alone on this, so I got in touch with a few friends to get some outside perspective.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Note: all of these quotes are in specific response to this blog post, which the respondent was able to view in advance. That, of course, unavoidably introduced some bias, as the respondent knew the tone of the post before they responded. But the answers below all reflect sentiments long-expressed by these people and others in the industry.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Here&amp;rsquo;s &lt;a href="https://twitter.com/jessicafardin"&gt;Jessica Fardin&lt;/a&gt;, CMO of &lt;a href="http://episerver.com"&gt;Episerver&lt;/a&gt; who says the organization&amp;rsquo;s culture is often to blame.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Software only becomes a vanity fix if a company&amp;rsquo;s culture isn&amp;rsquo;t onboard to really diagnose problems from top to bottom. You can&amp;rsquo;t blame the plumber if you never opened the walls and just painted over a leak in the ceiling.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve witnessed the most successful Episerver customers not being afraid to communicate operational flaws with impacted groups often and early. It&amp;rsquo;s OK to say, &amp;ldquo;This isn&amp;rsquo;t working.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The alternative is finger pointing after the fact and, to Deane&amp;rsquo;s point, it&amp;rsquo;s less awkward to blame a platform than a person or the processes they can&amp;rsquo;t let go of.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;First, never under-estimate any organization&amp;rsquo;s ability to point fingers. Second, that last point is so true, especially the word &amp;ldquo;awkward.&amp;rdquo; It&amp;rsquo;s easy to blame software because you can&amp;rsquo;t hurt its feelings, and it won&amp;rsquo;t demand severance pay. It&amp;rsquo;s easy to walk away from.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s &lt;a href="https://twitter.com/twentworth12"&gt;Tom Wentworth&lt;/a&gt;, SVP of Product Marketing for &lt;a href="https://acquia.com/"&gt;Acquia&lt;/a&gt; who points some of the blame back at vendors.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There&amp;rsquo;s an &lt;a href="https://en.wikipedia.org/wiki/The_Innovator%27s_Dilemma"&gt;Innovator&amp;rsquo;s Dilemma problem&lt;/a&gt; in web content management. Products are evolving in capabilities and complexity at a much faster rate than customers are able to consume them.&lt;/p&gt;
&lt;p&gt;Vendors get some of the blame because we make it look so easy to deliver a personalized 1-1 customer journey in a product demo. The truth is that customers underestimate the impact of organizational change.&lt;/p&gt;
&lt;p&gt;You can&amp;rsquo;t just double click on &amp;ldquo;DigitalTransformation.exe&amp;rdquo;. The customers who are most successful &amp;ndash; and avoid the $32 million dollar price tag &amp;ndash; are the ones who do the hard but boring work to connect people, process, then products.&lt;/p&gt;
&lt;p&gt;But vendors do need to simplify our products to help customers get to value faster. The future of web content management is less complexity, not more.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I give Tom credit for going there. Vendors reinforce &amp;ldquo;Wedding Day Syndrome&amp;rdquo; &amp;ndash; your spouse is never gonna look better than on your wedding day. When you see them all made-up in a wedding gown or looking dapper in a tux and tails, don&amp;rsquo;t get the idea that this is how it&amp;rsquo;s always going to be. They&amp;rsquo;re just not gonna look that good stumbling back into bed in a vomit-stained t-shirt after a 3 a.m. feeding.&lt;/p&gt;
&lt;p&gt;So far, we have customers and vendors to blame. For some balance, here&amp;rsquo;s &lt;a href="https://twitter.com/ahenrichsen"&gt;Arild Henrichsen&lt;/a&gt; from &lt;a href="https://www.epinova.no/"&gt;Epinova&lt;/a&gt; who says that we integrators share some of it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We can&amp;rsquo;t forget that there is also a middle ground between the over-promise of vendors and the skill limitations of users: Botched CMS implementations by agencies.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The most competent CMS platform and editorial team can be rendered almost useless by a bad implementation  &amp;ndash; usually from a team that either lacks understanding of that particular CMS platform, or lacks understanding of the customer&amp;rsquo;s needs.&lt;/p&gt;
&lt;p&gt;Integrators have a special responsibility to strike that balance between customers&amp;rsquo; creative ambitions and their skillset &amp;ndash; creative flexibility vs editorial control &amp;ndash; and executing implementations in a way that can scale as the customer reaches a higher level of digital maturity.&lt;/p&gt;
&lt;p&gt;Sure, I&amp;rsquo;ll take that blame.&lt;/p&gt;
&lt;p&gt;But, just to keep score, The Blame Game™ is currently:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Customers: 1&lt;/li&gt;
&lt;li&gt;Vendors: 1&lt;/li&gt;
&lt;li&gt;Integrators: 1&lt;/li&gt;
&lt;li&gt;Software: 0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(Or Humans 3, Computers 0, depending on how you want to roll that up.)&lt;/p&gt;
&lt;p&gt;Back to vendors for a second &amp;ndash; &lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/TonyByrne"&gt;Tony Byrne&lt;/a&gt; from &lt;a href="http://realstorygroup.com"&gt;Real Story Group&lt;/a&gt; provides this slide which presents the &amp;ldquo;Capacity/Hyperbole Gap&amp;rdquo; problem. On the far right is what the vendor claims their software can do under the best conditions. Moving leftwards we find what the software can &lt;em&gt;actually&lt;/em&gt; do assuming you have the skill to use it. Then far left is what the software can do with the skill an average customer actually possesses.&lt;/p&gt;
&lt;p&gt;&lt;img src="/tech/blog/images/software-isnt-the-problem/capacity-hyperbole-300x195.jpg" class="center" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Tony adds:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I think an organization that really focuses on capacity building first and tools later is going to discover that they can get away with much simpler tools at the customer engagement tier and push complexity down in the stack.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here&amp;rsquo;s &lt;a href="https://twitter.com/brodydorland"&gt;Brody Dorland&lt;/a&gt;, co-founder of &lt;a href="https://divvyhq.com/"&gt;DivvyHQ&lt;/a&gt;, an editorial management platform, who says that organizational pain drives motivation.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The two main drivers for success in the Divvy world seem to be &amp;ldquo;shared pain&amp;rdquo; and &amp;ldquo;readiness.&amp;rdquo; And the two actually go hand in hand.&lt;/p&gt;
&lt;p&gt;Meaning, a good number of folks walk through our virtual front door everyday and, upon our initial conversation, they have communicated some level of pain in their current processes. But pain can come from the top (i.e. leadership lacking visibility/oversight into a siloed operation), or from the bottom (i.e. users in the trenches).&lt;/p&gt;
&lt;p&gt;More often than not, only one of these groups is hurting and driving for change. That&amp;rsquo;s an average customer for us and we may not get full adoption. But once in a blue moon, both the top and bottom have come together, acknowledged each other&amp;rsquo;s shared pain points, and recognized that they are &amp;ldquo;ready&amp;rdquo; for a change.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Those on the top need to feel the tactical pain of those on the bottom; and those on the bottom need to appreciate the organizational pressure felt by those on the top. This is basic human empathy &amp;ndash; we need to step into each other&amp;rsquo;s shoes and try to feel what they feel.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s &lt;a href="https://twitter.com/brandonkelly"&gt;Brandon Kelly&lt;/a&gt; from &lt;a href="https://craftcms.com/"&gt;Craft CMS&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;All the successful Craft shops have mastered the art of follow-through. Even if an implementation seems like a perfect fit on day one, it&amp;rsquo;s not going to last. Business needs and workflows evolve. If the CMS doesn&amp;rsquo;t adapt to those changes, the client will grow to resent it and eventually look for a new solution, and a new partner.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, Brandon is pushing for a refined implementation over time. Get it in, then smooth it out on the back slope.&lt;/p&gt;
&lt;p&gt;And here&amp;rsquo;s &amp;ldquo;Rock You Like a &lt;a href="https://twitter.com/carriehd"&gt;Carrie Hane&lt;/a&gt;&amp;rdquo; (that joke will never get old) from &lt;a href="https://www.tanzenconsulting.com/"&gt;Tanzen&lt;/a&gt; who says you should start with the goal state and work backwards.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;My clients&amp;rsquo; and students&amp;rsquo; technology is never perfect, so we get creative and work backwards from the ideal. We create our strategy with no tech stack in mind, but what needs to be accomplished. Then we either find tech to support the goals or figure out how we can adjust our tactics using what we&amp;rsquo;ve got.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To repeat Carrie: &amp;ldquo;no tech stack in mind.&amp;rdquo; Get your non-tech house in order first.&lt;/p&gt;
&lt;p&gt;All these people are seasoned professionals who have &lt;em&gt;forgotten&lt;/em&gt; more about this business than most people will ever know. And I have yet to find someone who is willing to blame the software.&lt;/p&gt;
&lt;p&gt;To make sure I got as many angles as possible, I reached out to &lt;a href="https://www.linkedin.com/in/meghanawalsh"&gt;Meghan Walsh&lt;/a&gt;, Senior Director of Content Services for Hilton. Meg is well-known in the content community as a doer &amp;ndash; someone in the trenches trying to make all this theory work.&lt;/p&gt;
&lt;p&gt;Meg says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&amp;rsquo;ve worked places with dying CMS platforms and been able to do great things with content &amp;ndash; maybe not as much as we hoped &amp;ndash; but great things &amp;ndash; because we focused on the what of content first - -which is all people and process and goals. It&amp;rsquo;s the system-agnostic stuff. The technology is the how.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve made some bad decisions in my career about content structure, use and operations. Some of those bad decisions were hidden behind the curtain of the technology. I&amp;rsquo;m continually trying to learn from that.&lt;/p&gt;
&lt;p&gt;[…] Technology is the easy blame because it is, well, technology. As a practitioner, as a content leader in my company, I can&amp;rsquo;t take the easy way out.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let&amp;rsquo;s round this out with the legendary &lt;a href="https://en.wikipedia.org/wiki/Karen_McGrane"&gt;Karen McGrane&lt;/a&gt;, a friend with whom I&amp;rsquo;ve shared many war stories and commiserated over many drinks.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I say flat out to clients all the time &amp;ldquo;your technology isn&amp;rsquo;t your problem. YOU are your problem.&amp;rdquo; And everybody laughs, probably because they&amp;rsquo;ve all been through enough implementations to know that the software won&amp;rsquo;t save them.&lt;/p&gt;
&lt;p&gt;They say that success has many parents, but failure is an orphan. To me it seems like this failure has all kinds of deadbeat parents. Execs that just want to write a big check and make a problem go away. Budgeting that allocates money for software but not services. Under-resourced internal teams that don&amp;rsquo;t have the influence they need to make changes. Unrealistic timelines that don&amp;rsquo;t allow for the kind of iteration we take for granted in other processes.&lt;/p&gt;
&lt;p&gt;Never enough time and money to get it right, but always enough to do it over.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I saved Karen for last because I was sure she was gonna put the period on this sentence, and I&amp;rsquo;m not sure I can add anything more to that.&lt;/p&gt;
&lt;h2&gt;Parting Thoughts&lt;/h2&gt;
&lt;p&gt;Earlier this week, I was having a DM conversation with &lt;a href="https://twitter.com/mde_sitecore"&gt;Mark Demeny&lt;/a&gt; from Sitecore about something. We realized, to our delight, that we were both going to be in Copenhagen at the end of the week. So, that Friday, I had a lovely dinner with Mark and &lt;a href="https://twitter.com/AmandaShiga"&gt;Amanda Shiga&lt;/a&gt; overlooking Copenhagen&amp;rsquo;s South Harbor (&lt;a href="https://www.google.com/maps/place/The+Harbour/@55.6629827,12.5632433,162m/data=!3m1!1e3!4m5!3m4!1s0x4652536e2a0dafe9:0x5368adc7c1408d62!8m2!3d55.663078!4d12.5635987"&gt;in this spot&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;CMS geeks are gonna geek, and we dutifully talked for a couple of hours about all the usual topics, companies, and people (our greatest accomplishment might have been to &lt;a href="https://twitter.com/CMS_Borat"&gt;awaken CMS Borat&lt;/a&gt; after almost three years of silence). I love it when people who are passionate about something have free time to go deep, and this was that kind of dinner &amp;ndash; none of us had anywhere we needed to be.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;Postscript: I was given &lt;a href="https://www.amazon.com/Little-Book-Hygge-Danish-Secrets/dp/0062658808"&gt;a book about &lt;em&gt;hygge&lt;/em&gt;&lt;/a&gt; from the conference I spoke at in Denmark. I&amp;rsquo;m reading it now, and I&amp;rsquo;ve come to realize that our dinner was &lt;em&gt;hyggelig&lt;/em&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Towards the end, our conversation turned to how we can actually get better as professionals in this industry. Related to this, I&amp;rsquo;ve had discussions with multiple people over the years about the idea of an &amp;ldquo;unconference&amp;rdquo; in Reykjavík or somewhere thereabouts (we have our eye on &lt;a href="https://ionadventure.ioniceland.is/the-hotel/"&gt;this hotel&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Mark, Amanda, and I discussed what this might look like: who would we have speak, would we have some collective theme or goal, and what would be the value proposition? There are a lot of angles to this business, and what front should we attack first?&lt;/p&gt;
&lt;p&gt;In the end, we centered about this idea &amp;ndash; &lt;/p&gt;
&lt;p&gt;The most valuable thing we could do would be to talk about organizational and personal psychology and motivations.&lt;/p&gt;
&lt;p&gt;Far more than software, this is the biggest problem we face in this industry &amp;ndash; getting organizations out of their own way and finding ways to get groups of people working effectively and consistently towards a common goal. The best idea we had was to invite a bunch of organizational therapists to the event and just listen.&lt;/p&gt;
&lt;p&gt;Afterwards, I was reminded of one of the best business books I&amp;rsquo;ve ever read: &lt;em&gt;&lt;a href="https://www.amazon.com/Advantage-Organizational-Health-Everything-Business/dp/0470941529/"&gt;The Advantage&lt;/a&gt;&lt;/em&gt; by &lt;a href="https://en.wikipedia.org/wiki/Patrick_Lencioni"&gt;Patrick Lencioni&lt;/a&gt;. (Honestly, you could swap in any number of Lencioni&amp;rsquo;s books here: &lt;em&gt;&lt;a href="https://www.amazon.com/Five-Dysfunctions-Team-Leadership-Fable/dp/0787960756/"&gt;The Five Dysfunctions of a Team&lt;/a&gt;&lt;/em&gt;; &lt;a href="https://www.amazon.com/Silos-Politics-Turf-Wars-Competitors/dp/0787976385/"&gt;&lt;em&gt;Silos, Politics and Turf Wars&lt;/em&gt;&lt;/a&gt;; etc.&lt;em&gt;).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In &lt;em&gt;The Advantage&lt;/em&gt;, Lencioni says this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Most leaders prefer to look for answers where the light is better… and the light is certainly better in the measurable, objective, and data-driven world of organizational intelligence than in the messier, more unpredictable world of organizational health.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You could substitute almost anything for &amp;ldquo;organizational intelligence&amp;rdquo; in that sentence (i.e. &amp;ldquo;technology&amp;rdquo;) because almost anything else is easier than confronting the messy reality of human frailties, egos, and shortcomings. So we look elsewhere, at easier targets.&lt;/p&gt;
&lt;p&gt;But the light isn&amp;rsquo;t any better, we just don&amp;rsquo;t like the dark.&lt;/p&gt;
&lt;p&gt;Someday, all of us consultants, engineers, and designers are going to finally summit The Mountain of Efficacy and reach that place when we have figured out the most effective way to move our clients forward.&lt;/p&gt;
&lt;p&gt;On that day, when we at last pull ourselves over that peak, exhausted and bleeding, we shouldn&amp;rsquo;t be at all surprised to find a bunch of governance, operations, and strategy experts who have been sitting there for years.&lt;/p&gt;
&lt;h2&gt;Postscript: Romano Tours&lt;/h2&gt;
&lt;p&gt;This SNL sketch is worth watching. It might accidentally be the deepest, most thoughtful bit they&amp;rsquo;ve done in years, and it highly relates to this post.&lt;/p&gt;
&lt;p&gt;You are still going to be you, wherever you go, and no matter what software you use.&lt;/p&gt;


&lt;div class="video-container"&gt;
    &lt;iframe src="https://www.youtube.com/embed/TbwlC2B-BIg" title="A parody commercial clip from Saturday Night Live" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;</description>
      <pubDate>Tue, 28 May 2019 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/software-isnt-the-problem/</guid>
    </item>
    <item>
      <title>Towards a Content Modeling Standard</title>
      <link>https://live.deanebarker.net/tech/blog/towards-content-modeling-standard/</link>
      <description>&lt;p&gt;We (I?) talk incessantly about headless CMS. But not many people are talking about the &amp;ldquo;head.&amp;rdquo; Headless is obsessed with how content is managed but ambivalent about how it&amp;rsquo;s delivered. It seems that delivery is always custom, and this is largely the selling point.&lt;/p&gt;
&lt;p&gt;But does it always have to be custom? &lt;em&gt;Should&lt;/em&gt; it always be custom? What&amp;rsquo;s stopping us from making it…less custom?&lt;/p&gt;
&lt;p&gt;But, first, a quick recap &amp;ndash; &lt;/p&gt;
&lt;p&gt;Headless CMS is a content management system without a publishing infrastructure. Content is &amp;ldquo;published&amp;rdquo; by simply making it available through an API (though, usually, by pushing it into a CDN), and some channel &amp;ndash; a website, a mobile app, etc. &amp;ndash; proactively retrieves the content for display.&lt;/p&gt;
&lt;p&gt;(Also, see the definition of &lt;a href="http://flyingsquirrelbook.com/glossary/term/coupling-model"&gt;coupling models&lt;/a&gt; over at the &lt;a href="http://flyingsquirrelbook.com/glossary"&gt;Web Content Management Glossary&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;What are the majority use cases of headless? &lt;a href="/tech/blog/use-cases-for-headless-cms/"&gt;I wrote about this at length a couple years ago.&lt;/a&gt; In that post, I made the point that headless in WCM is still very much a question mark:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What might be surprising is that we more or less agreed on this: the use case of a single repository of information feeding a single website is not a great value-add for a headless CMS.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &amp;ldquo;we&amp;rdquo; in that post is me and some of the folks from &lt;a href="http://contentful.com/"&gt;Contentful&lt;/a&gt;, who I visited in Berlin. In that afternoon, and in that post, we talked about &lt;em&gt;a lot&lt;/em&gt; of different things you can do with a headless CMS, but running a single website wasn&amp;rsquo;t really one of them.&lt;/p&gt;
&lt;p&gt;Can you run a website from a headless CMS? Of course. And, as I pointed out &lt;a href="https://www.cmswire.com/web-cms/with-content-delivery-what-goes-around-comes-around/"&gt;in a CMSWire article last year&lt;/a&gt;, headless CMS is something of a return to how we were all building sites at the turn of the century. Back then, we built all &amp;ldquo;headless&amp;rdquo; CMSs &amp;ndash; systems that managed content using one set of logic, and displayed it using another.&lt;/p&gt;
&lt;p&gt;Fourteen years ago, &lt;a href="/tech/blog/cms-administration-vs-presentation-languages/"&gt;I wrote this&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Now, lets put the 50-yard line of this game at the database. So the creation, management, approval, and general administration of content all leads up to one moment &amp;ndash; when a certain content record in a database table is declared &amp;ldquo;active.&amp;rdquo; Everything is working up to that point. The &amp;ldquo;active&amp;rdquo; records in the database table are free to be used on the public side of the site.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Why not just create a view of the database that only includes those records, then give your designers and presentation specialists a read-only user and a copy of ColdFusion? Who says that the language the CMS is programmed in has to be the language the content is presented in?&lt;/p&gt;
&lt;p&gt;Today, that seems a little prescient.&lt;/p&gt;
&lt;p&gt;Headless is all about administration and management. It actively eschews presentation. It &lt;em&gt;does not care&lt;/em&gt; what you do with the content it manages.&lt;/p&gt;
&lt;p&gt;So…who &lt;em&gt;does&lt;/em&gt; care?&lt;/p&gt;
&lt;p&gt;Put another way, what is the &amp;ldquo;head&amp;rdquo; in headless, when it comes to WCM?  What is the counterpart to the headless system that manages the content?&lt;/p&gt;
&lt;p&gt;To be pedantic, we could just say &amp;ldquo;website,&amp;rdquo; and this isn&amp;rsquo;t wrong. But just like we created content management systems to standardize the common patterns of managing content, will someone create a &amp;ldquo;content delivery system&amp;rdquo; to standardize the delivery of content?&lt;/p&gt;
&lt;p&gt;Yes, there are any number of web frameworks to build a website on, but they&amp;rsquo;re just tools that neither know nor care what you&amp;rsquo;re writing. The line between content-based website and transactional web application gets pretty slippery.&lt;/p&gt;
&lt;p&gt;Speaking of content sites in particular, there are patterns. Meaning, there are things we have to do over and over again, and these are patterns that traditional web CMSs have organically grown around. Things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Global page elements&lt;/li&gt;
&lt;li&gt;Hierarchical navigation&lt;/li&gt;
&lt;li&gt;Positionable content elements&lt;/li&gt;
&lt;li&gt;Personalized content delivery&lt;/li&gt;
&lt;li&gt;Full-text search&lt;/li&gt;
&lt;li&gt;Object-level permissions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When will someone standardize these elements into a framework that can be &amp;ldquo;backed&amp;rdquo; by a headless CMS?&lt;/p&gt;
&lt;p&gt;(True story: &lt;a href="http://blendinteractive.com"&gt;Blend&lt;/a&gt; is sort of stuck on a project to create a &amp;ldquo;base site&amp;rdquo; profile, meaning we&amp;rsquo;re trying to codify the basic, foundational elements that go in every site we end up building. It&amp;rsquo;s harder than you think, but work continues.)&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example how this might play out at a business level.&lt;/p&gt;
&lt;p&gt;Some enterprising front-end dev might look deeply at &lt;a href="https://kenticocloud.com/"&gt;Kentico Cloud&lt;/a&gt; and think,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;You know, I could build a front-end for this. With some conventions and a little training, I could create a system that would give you a packaged website, backed by a Kentico Cloud instance.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And then, later, when this has become a raging success &amp;ndash; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Man, there are a lot of Contentful users. Maybe we should create a version of the front-end to be backed by Contentful.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Even later &amp;ndash; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Okay, now I have versions for Kentico Cloud, Contentful, &lt;a href="https://getdirectus.com/"&gt;Directus&lt;/a&gt;, &lt;a href="https://prismic.io/"&gt;Prismic.io&lt;/a&gt;. And for the traditional systems that have remote APIs, like &lt;a href="http://sitecore.com"&gt;Sitecore&lt;/a&gt;, &lt;a href="http://episerver.com/"&gt;Episerver&lt;/a&gt;, &lt;a href="http://drupal.org"&gt;Drupal&lt;/a&gt;, etc. And also for the ECM systems like &lt;a href="http://alfresco.org"&gt;Alfresco&lt;/a&gt; and &lt;a href="http://nuxeo.com"&gt;Nuxeo&lt;/a&gt;.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And then this person dies from exhaustion because they&amp;rsquo;re updating all these front-ends all the time.&lt;/p&gt;
&lt;p&gt;The point: before we could standardize a front-end (a &amp;ldquo;head&amp;rdquo;), &lt;em&gt;we would need to standardize the APIs&lt;/em&gt;. All of these headless systems would either need to agree on an API, or there would need to be a thriving ecosystem of API abstractions for them. This way, your front-end could make generic calls into the void and not care who responds to them.&lt;/p&gt;
&lt;p&gt;And when I say &amp;ldquo;standardize an API,&amp;rdquo; I don&amp;rsquo;t mean to standardize the bindings or the protocols. So, not like &lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer"&gt;REST&lt;/a&gt;, for example. And I don&amp;rsquo;t mean to standardize the discovery, like &lt;a href="https://en.wikipedia.org/wiki/Web_Services_Description_Language"&gt;WSDL&lt;/a&gt; or &lt;a href="https://swagger.io/"&gt;Swagger&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I mean that we need to abstract and standardize &lt;em&gt;the very idea of content&lt;/em&gt;. We need to come up with a common lens with which to view content types, content objects, properties, datatypes, values, and relationships in the ways they relate to WCM.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t to say we haven&amp;rsquo;t tried. There are two major content-centric API systems in (somewhat) common use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Content_repository_API_for_Java"&gt;Content Repository API for Java&lt;/a&gt; (&amp;ldquo;the JCR&amp;rdquo;). This was developed at Day Software for their CQ product (now &lt;a href="https://www.adobe.com/marketing-cloud/experience-manager.html"&gt;Adobe Experience Manager&lt;/a&gt;), then spun off as a standard (&lt;a href="https://docs.adobe.com/content/docs/en/spec/jcr/1.0/index.html"&gt;JSR 170&lt;/a&gt;). It&amp;rsquo;s popular in the Java WCM space (AEM, of course, is built on it, as is &lt;a href="https://www.magnolia-cms.com/"&gt;Magnolia&lt;/a&gt;). Clearly, it&amp;rsquo;s Java-centric, but does have &lt;a href="https://jackalope.github.io/"&gt;a PHP port&lt;/a&gt; (but no .NET port, to my eternal temptation).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Content_Management_Interoperability_Services"&gt;Content Management Interoperability Services&lt;/a&gt; (CMIS). This is an open-standard started by the Association for Intelligent Information Management (AIIM) and &lt;a href="http://docs.oasis-open.org/cmis/CMIS/v1.1/CMIS-v1.1.html"&gt;since approved by OASIS&lt;/a&gt;. It&amp;rsquo;s very well-accepted in the enterprise content management space.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, I don&amp;rsquo;t claim to be an expert in either of these, but my understanding is that they&amp;rsquo;re not competing standards. They have specific angles and &lt;a href="https://web.archive.org/web/20130601011646/http://dev.day.com/content/ddc/blog/2009/05/jcrcmiscomparison.html"&gt;can work together productively&lt;/a&gt;.&lt;/p&gt;


&lt;aside&gt;
&lt;p&gt;Editorial note: headless vendors &amp;ndash; for the love of all that is good and holy &amp;ndash; &lt;em&gt;embrace trees&lt;/em&gt;. Look at the JCR and CMIS &amp;ndash; what do you see? Hierarchical trees. So some very smart people who specifically set out to model generic content decided that &lt;em&gt;the natural way to do it was a tree&lt;/em&gt;. Why is no headless vendor letting anyone build content trees? Why is the state-of-the-art in headless seemingly just a series of flat database tables? End rant.&lt;/p&gt;

&lt;/aside&gt;


&lt;p&gt;When will something like API standardization come to the headless space, to define the interactions with a WCM &amp;ldquo;head&amp;rdquo;? I think the next logical step in the slow uncoupling of content management and delivery is the commoditization of a delivery layer. There are a ton of front-end ninjas floating around out there that are probably just dying to build something, but the headless market is so &lt;a href="http://www.blueoceanstrategyaustralia.com.au/what-is-bos/red-vs-blue/"&gt;red ocean&lt;/a&gt; right now that some people don&amp;rsquo;t know which horse to back.&lt;/p&gt;
&lt;p&gt;I think the market might be waking up to this. I had a demo of &lt;a href="http://gatsybyjs.org/"&gt;GatsbyJS&lt;/a&gt; a while back, which purports to be the front-end for a headless website. It&amp;rsquo;s a set of JS libraries around &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt;. Combined with static site generation, this provides a presentation layer that actually doesn&amp;rsquo;t rely on JavaScript and has a static version for all the content. (During the demo, my partner was browsing &lt;a href="https://www.gatsbyjs.org/docs/"&gt;their docs&lt;/a&gt;. For giggles, he shut off JavaScript. It worked exactly the same, just a little slower.)&lt;/p&gt;
&lt;p&gt;On the subject of standardization of APIs, &lt;a href="https://twitter.com/calcsam"&gt;Sam Bhagwat&lt;/a&gt; from &lt;a href="https://www.gatsbyjs.org/"&gt;GatsbyJS&lt;/a&gt; had this to say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The tricky part here, of course, is that CMS-es don&amp;rsquo;t want to be commoditized any more than newspaper publishers do (hence all the controversy around AMP!). And publishing your data in a standard format is basically screaming &amp;ldquo;I&amp;rsquo;m a commodity!&amp;rdquo; So every CMS will output different schemas, and probably will for a while.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://twitter.com/aschauerhuber"&gt;Andrea Schauerhuber&lt;/a&gt; from &lt;a href="https://getmesh.io/"&gt;Gentics Mesh&lt;/a&gt;, based in Vienna, mentioned that perhaps we don&amp;rsquo;t need to standardize, given the flexibility of one of the common API protocols:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[…] with GraphQL in the game I think that today it is very easy to offer APIs that are extremely flexible. Developers basically are able to tailor the requests to their need. […] with GraphQL it has become so simple to &amp;ldquo;model&amp;rdquo; the data response in a way that your app can process it easily.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(Andrea also wanted to point out that Gentics Mesh &lt;a href="https://getmesh.io/docs/beta/features.html"&gt;supports content trees&lt;/a&gt;, in defiance of my rant above…)&lt;/p&gt;
&lt;p&gt;From the traditional (coupled) CMS vendor side, I&amp;rsquo;ve recently become aware of &lt;a href="http://jss.sitecore.net/"&gt;JavaScript Services for Sitecore&lt;/a&gt;, which is an attempt by Sitecore to provide a front-end for a headless implementation of their system. JSS is a set of libraries that will bind components directly to Sitecore objects and do all the plumbing behind the scenes.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s look at The Headless Equation™ as having three layers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Repository&lt;/li&gt;
&lt;li&gt;API&lt;/li&gt;
&lt;li&gt;Delivery Channel (the &amp;ldquo;head&amp;rdquo;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this model, the title of this post is getting ahead of itself. We can&amp;rsquo;t standardize the head until we standardize the API. And we can&amp;rsquo;t standardize the API until we standardize how repositories conceptualize content models. For us to make progress here, we&amp;rsquo;re going to need to agree on a set of concepts around which we slap on any API (REST, GraphQL, SOAP, whatever).&lt;/p&gt;
&lt;p&gt;Some of the basic content modeling questions need need to resolve to create &lt;a href="https://xkcd.com/927/"&gt;The One Standard™&lt;/a&gt; (some are obvious; others, less so) &amp;ndash; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Are there structured content types?&lt;/li&gt;
&lt;li&gt;Do those types have attributes?&lt;/li&gt;
&lt;li&gt;What base data types can we agree on?&lt;/li&gt;
&lt;li&gt;What description framework can we put around custom types?&lt;/li&gt;
&lt;li&gt;Can attributes repeat?&lt;/li&gt;
&lt;li&gt;How are empty attributes/null indicated?&lt;/li&gt;
&lt;li&gt;Can attributes be a full, encapsulated object? Can this be restricted by type?&lt;/li&gt;
&lt;li&gt;Can attributes reference another object? Can this restricted by type?&lt;/li&gt;
&lt;li&gt;Are those references two-way?&lt;/li&gt;
&lt;li&gt;Can we enforce referential integrity?&lt;/li&gt;
&lt;li&gt;Is content in a hierarchy?&lt;/li&gt;
&lt;li&gt;What base grouping or sectioning structures can we agree on? (Categories, types, branches of a content tree, etc.)&lt;/li&gt;
&lt;li&gt;What parametric search options can we agree on?&lt;/li&gt;
&lt;li&gt;Do we support full-text, tokenized search?&lt;/li&gt;
&lt;li&gt;What discovery framework can we create to allow programmatic investigations of capabilities? (&lt;a href="https://en.wikipedia.org/wiki/Web_Services_Description_Language"&gt;WSDL&lt;/a&gt;, FTW, &lt;em&gt;finally&lt;/em&gt;.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finding a baseline standard here would help the entire headless industry enormously. And there&amp;rsquo;s precedent for this &amp;ndash; standards like &lt;a href="https://en.wikipedia.org/wiki/Dublin_Core"&gt;Dublin Core&lt;/a&gt; and &lt;a href="https://commonmark.org/"&gt;CommonMark&lt;/a&gt; and even &lt;a href="https://blog.ansi.org/2018/10/sql-standard-iso-iec-9075-2016-ansi-x3-135/"&gt;ANSI SQL&lt;/a&gt; have tried (or are trying) to create a baseline for a wide variety of implementations. Vendors can do whatever they want as a superset of this, but claiming standards compliance means they &lt;em&gt;at least&lt;/em&gt; support the baseline.&lt;/p&gt;
&lt;p&gt;But I circle back to a cynical problem endemic to these situations: vendors in the space right now probably don&amp;rsquo;t want portability. They want lock-in.&lt;/p&gt;
&lt;p&gt;No one who is depending on subscription revenue or looking for a seed round wants to be easily swappable. Rather, they want people to base the upper layer around their product and &lt;em&gt;Cement. That. In. Place.&lt;/em&gt; And this probably has some variance based on the size of the vendor &amp;ndash; a smaller vendor likes the idea of portability to gain new adherents, while an established vendor with an existing base of users wants to keep them in place.&lt;/p&gt;
&lt;p&gt;So, this entire idea will likely remain a pipe dream. But there&amp;rsquo;s value here, and if anyone knows of a way to build some momentum behind this idea, I&amp;rsquo;m all ears.&lt;/p&gt;</description>
      <pubDate>Wed, 24 Apr 2019 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/towards-content-modeling-standard/</guid>
    </item>
    <item>
      <title>Content, Campaigns, and Context: Why CDPs Are Having a Moment</title>
      <link>https://live.deanebarker.net/tech/blog/cdp/</link>
      <description>&lt;p&gt;Someone &lt;a href="https://twitter.com/blendquotes/status/1111737388051693568"&gt;tweeted about me&lt;/a&gt; the other day:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;@gadgetopia loves to hear himself write.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And it&amp;rsquo;s true. I love to write. And I write for myself, really.&lt;/p&gt;
&lt;p&gt;If someone reads me, that&amp;rsquo;s awesome, but it&amp;rsquo;s not really required. Honestly, I&amp;rsquo;ll just yell into the void all day long.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m content-centric. For me, creating the content is the point. I need to do it at some base psychological level, and I guess it&amp;rsquo;s just a bonus if it coincides with a business goal.&lt;/p&gt;
&lt;p&gt;The average organization has historically been content-centric as well. We create content first, and we hope that it has some value to some person down the road. The value is usually just assumed, because you can&amp;rsquo;t exactly predict these things, but we hope we do okay.&lt;/p&gt;
&lt;p&gt;Personally, my feeling is that if you create good content, it&amp;rsquo;ll pay off at some point. Call that &amp;ldquo;shotgun content strategy&amp;rdquo; &amp;ndash; shoot a lot in one general direction, and eventually you&amp;rsquo;ll hit something. This is grossly inefficient, but a hard thing to accept is that &lt;em&gt;creating content is the easiest part&lt;/em&gt; &amp;ndash; getting an actual return on that content is harder.&lt;/p&gt;
&lt;p&gt;(Note: I showed this post to my marketing manager. She said, &amp;ldquo;When I was at an agency, we used to call that &amp;lsquo;spray and pray&amp;rsquo; marketing.&amp;rdquo;)&lt;/p&gt;
&lt;p&gt;Exhibit A: the &lt;em&gt;content&lt;/em&gt; management system. We build our processes around systems for creating, editing, and managing &lt;em&gt;content&lt;/em&gt;. Our strategy often starts and ends with content &amp;ndash; we&amp;rsquo;ll create it then throw it out into the world and hope that it works. There are people out there consuming it…somewhere. We hope they like it.&lt;/p&gt;
&lt;p&gt;The dream of content-centrism is something like throwing bread on the ground at the beach, and watching swarms of seagulls descend on it and fight over it. Wouldn&amp;rsquo;t this be great? We don&amp;rsquo;t know anything about the seagulls or their story or their relationship with the bread. We just toss it out, and they descend, and we hope this is how it works with our content.&lt;/p&gt;
&lt;p&gt;This is &lt;strong&gt;First Wave Content Marketing&lt;/strong&gt;: content management systems as the foundational pillar of a content marketing infrastructure. Names like Episerver and Sitecore and Drupal loom large here.&lt;/p&gt;
&lt;p&gt;The next stage of maturation is the Rubicon an organization crosses when they go from content-centrism to &lt;em&gt;campaign&lt;/em&gt;-centrism. There&amp;rsquo;s always a very different vibe to organizations that speak of &amp;ldquo;content&amp;rdquo; and those that speak of &amp;ldquo;campaigns.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The former will say &amp;ldquo;we published a blog post!&amp;rdquo; and the latter will say, &amp;ldquo;we&amp;rsquo;re seeing great conversions and engagement from our last campaign!&amp;rdquo; The former just throws content into the void (guilty), while the latter plans coordinated marketing campaigns around ideas they what to communicate, then builds content in support of those ideas. They can&amp;rsquo;t imagine just creating content without being part of a larger effort to influence.&lt;/p&gt;
&lt;p&gt;The campaign is a conceptual framework of positioning and framing. The content is just what gets bolted onto that framework. The campaign became The Thing &amp;ndash; content was now just created and managed in support of The Thing.&lt;/p&gt;
&lt;p&gt;This shift changed how we sell CMS. We used to lead pitches with &lt;em&gt;management&lt;/em&gt; &amp;ndash; &amp;ldquo;This is how you edit a page of content.&amp;rdquo;  But then the market changed, and we started to lead pitches with &lt;em&gt;marketing&lt;/em&gt; &amp;ndash; &amp;ldquo;This is how you set-up an A/B test campaign.&amp;rdquo; It was a tectonic shift in how this industry was structured. Management became secondary to marketing, and content became secondary to campaigns. This was a healthy change.&lt;/p&gt;
&lt;p&gt;So, let&amp;rsquo;s call this &lt;strong&gt;Second Wave Content Marketing&lt;/strong&gt;: when &lt;em&gt;campaign&lt;/em&gt; management began to take precedence over &lt;em&gt;content&lt;/em&gt; management. This is when names like Pardot and Eloqua and Marketo started to creep into more and more conversations. In addition to a CMS, people wanted to know how that was going to integrate with their larger marketing platforms.&lt;/p&gt;
&lt;p&gt;I feel like there&amp;rsquo;s a &lt;strong&gt;Third Wave of Content Marketing&lt;/strong&gt; coming, driven by a technology shift called Customer Data Platforms, or CDPs. This is where content and campaigns become subordinate to &lt;em&gt;context&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Haven&amp;rsquo;t heard of these? You will. (apologies to &lt;a href="https://www.youtube.com/watch?v=2kfIFDX9kE4"&gt;Tom Selleck&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;They are:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[…] packaged software which creates a persistent, unified customer database that is accessible to other systems. Data is pulled from multiple sources, cleaned and combined to create a single customer profile. This structured data is then made available to other marketing systems.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The idea is that your CDP is the single source of truth for your customer data and a history of their behavior &amp;ndash; their &amp;ldquo;context&amp;rdquo; with you. A CDP tracks customer activity across every channel, even when the customer can&amp;rsquo;t be identified.&lt;/p&gt;
&lt;p&gt;If your customer identifies themselves at some point (ex: they register for a webinar), their profile is &amp;ldquo;de-anonymized&amp;rdquo; and can then be matched up to all sorts of other information, and you can begin to push known information about that customer into your CDP.&lt;/p&gt;
&lt;p&gt;(And, yes, this is where some vaguely creepy things can start to happen with data purchased from profiling firms, but that has nothing to do with a CDP, directly. A CDP is just where organizations put that data, alongside lots of other &amp;ndash; less creepy &amp;ndash; data.)&lt;/p&gt;
&lt;p&gt;Two differentiating points to note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;This is not a CRM.&lt;/strong&gt; A CRM tracks the actions of humans dealing with humans around specific tasks &amp;ndash; selling or supporting something. You&amp;rsquo;ll often push data from your CRM into your CDP, and vice-versa.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;This is not analytics.&lt;/strong&gt; Analytics is usually channel-centric. They tell you what aggregate visitors did in aggregate on a particular channel, not everything a specific person did. Additionally, analytics are historically declarative (&amp;ldquo;this thing happened&amp;rdquo;), not an aggregation platform &amp;ndash; put another way, you don&amp;rsquo;t go pushing data into them after the fact to reference later.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A CDP is a central clearing house for massive amounts of data about your customers&amp;rsquo; &lt;em&gt;behavior&lt;/em&gt;. It might share data with a CRM in both directions, but it&amp;rsquo;s very much a separate segment. A CDP gives you intricate details about their behaviors &amp;ndash; &amp;ldquo;Person X took Action Y in channel Z&amp;rdquo; &amp;ndash; and gives you a place to put data about them that you source externally and after their direct interaction with you.&lt;/p&gt;
&lt;p&gt;CDPs are suddenly a big deal in the digital marketing world. Vendors are sprouting up everywhere. CMS vendors are offering integrations or building their own offerings. Marketing suite vendors are adding CDPs as core parts of their family of tools.&lt;/p&gt;
&lt;p&gt;You might be thinking, &amp;ldquo;Didn&amp;rsquo;t big companies already do this?&amp;rdquo; And they did. But these systems have never really been productized &amp;ndash; bigger, more advanced organizations just built their own, and only now are patterns emerging that are driving generalized products.&lt;/p&gt;
&lt;p&gt;From my friend &lt;a href="https://www.realstorygroup.com/About/Team/3-Byrne"&gt;Tony Byrne&lt;/a&gt; from &lt;a href="http://realstorygroup.com/"&gt;Real Story Group&lt;/a&gt; &amp;ndash; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The search for unified customer and prospect data is not new. For more than a decade now, larger enterprises have been custom-building &amp;ndash; often at great effort &amp;ndash; what RSG calls &amp;ldquo;Customer Data Backbones.&amp;rdquo; These were typically API layers built with traditional enterprise integration toolsets and data warehouse platforms. Early-adopter enterprises have built impressive customer data backbones, but the resulting layer tended to be very bespoke and IT-intensive and therefore not as adaptive as agile marketers always needed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;CDPs are the technology industry&amp;rsquo;s attempt to replace custom backbones with more marketer- friendly, packaged solutions.&lt;/p&gt;
&lt;p&gt;TLDR: we already did this ourselves, just like we built custom CMSs for a long time. Companies are just productizing these now.&lt;/p&gt;
&lt;p&gt;And this is why the shift is coming: when something gets productized and ultimately commoditized, it becomes part of the common lexicon of an industry. Now we can all talk about a &amp;ldquo;CDP&amp;rdquo; and know we&amp;rsquo;re discussing the same thing &amp;ndash; either an actual platform/tool, or the generalized concept of warehousing customer context data.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;data warehouse&amp;rdquo; analogy is apt. These are data warehouses for customer behavior, in the sense that they&amp;rsquo;re designed to store and make sense of data pushed into them from all directions. And like that segment, custom solutions without names existed for a long time.&lt;/p&gt;
&lt;p&gt;The adoption pattern might be similar too &amp;ndash; back in the 90s, before the data warehouse market became productized, this was a space where every company just built their own thing.&lt;/p&gt;
&lt;p&gt;But then someone slapped a name on it &amp;ndash; Bill Inmon published &lt;em&gt;&lt;a href="https://www.amazon.com/Building-Data-Warehouse-W-Inmon/dp/0764599445/"&gt;Building the Data Warehouse&lt;/a&gt;&lt;/em&gt; in the early 90s (I read it when I was starting my career in IT a few years later) &amp;ndash; and now there was a &amp;ldquo;named market&amp;rdquo; that vendors could coalesce around. We weren&amp;rsquo;t just building consolidated databases &amp;ndash; we were &lt;em&gt;data warehousing!&lt;/em&gt; Sometimes all anything needs is a name to give birth to a segment (and a million &amp;ldquo;expert consultants&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s &lt;a href="https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=cxs"&gt;a developing OASIS standard&lt;/a&gt; that was spun out of &lt;a href="https://www.jahia.com/home.html"&gt;Jahia&lt;/a&gt;, the WCM company. It was originally called a &amp;ldquo;context server,&amp;rdquo; but then they conceded that a name had happened:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Since the OASIS Context Server TC has been established, the term Customer Data Platform (CDP) has emerged and can be interchangeably be used for the Context Server. To reflect this, the specification produced by this TC has changed its name to : the Customer Data Platform specification.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I actually like the &amp;ldquo;context&amp;rdquo; name better. That&amp;rsquo;s what this is &amp;ndash; the &lt;em&gt;context&lt;/em&gt; that your customer has with your digital channels. If you ever ask the question, &amp;ldquo;What does this person know about us?,&amp;rdquo; then these products seek to provide that answer. They want to record the context between your customer and you.&lt;/p&gt;
&lt;p&gt;Organizations are acquiring packaged CDPs from three main sources:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Pure-play vendors&lt;/li&gt;
&lt;li&gt;CMS vendors&lt;/li&gt;
&lt;li&gt;Marketing suite vendors&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are slew of &lt;strong&gt;pure plays&lt;/strong&gt; in this space, almost all of them SaaS vendors.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.blueconic.com"&gt;BlueConic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lytics.com/"&gt;Lytics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tealium.com/"&gt;Tealium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.treasuredata.com/"&gt;Treasure Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;and dozens more…&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I know, I know &amp;ndash; you haven&amp;rsquo;t heard of any of these. That&amp;rsquo;s fine. Back in 2003, you hadn&amp;rsquo;t heard of WordPress either.&lt;/p&gt;
&lt;p&gt;RSG is currently &lt;a href="https://www.realstorygroup.com/Reports/CDP/"&gt;covering&lt;/a&gt; 26 pure plays and another 3-4 larger suite vendors. I spent some time with a handful of reports that RSG was kind enough to provide. Axes of evaluation seem to be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ingestion:&lt;/strong&gt; how easy is it to get data into the platform?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Analysis and Segmentation:&lt;/strong&gt; how can you play around with the data inside the platform?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Usability:&lt;/strong&gt; what user level is targeted by the platform? Developers? Marketers?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connectors:&lt;/strong&gt; what external services does the product integrate with, either for automatic data ingestion or more complicated analysis?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vendors are all over the map, both in core functionality and also seemingly in targeting. Some products are for developers, some marketers, some for data scientists.&lt;/p&gt;
&lt;p&gt;Another problem &amp;ndash; simultaneously more mundane and more dangerous &amp;ndash; is that no one is disclosing revenue, so you have no way of knowing who the real players are, and who&amp;rsquo;s going to be around when the inevitable shakeout and consolidation happens. That problem is what tends to drive people away from pure plays and into the arms of their existing marketing suite or CMS vendor.&lt;/p&gt;
&lt;p&gt;So &lt;strong&gt;traditional CMS vendors&lt;/strong&gt; are jumping into the fray with their own solutions. Here&amp;rsquo;s &lt;a href="https://twitter.com/joeyizzy"&gt;Joey Moore from Episerver&lt;/a&gt; about their &lt;a href="https://www.episerver.com/products/platform/personalization/actionable-insights/"&gt;Insight&lt;/a&gt; product.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The digital experience platform is the natural home of the CDP. This became increasingly apparent, and why we developed our own solution some years back. Clients were pulling customer data out of the platform to use somewhere else or pushing external data in, often from solutions that we now provide (think email marketing or product recommendations). So in that regard we kind of had a head start as we understood the lifecycle and the value of the data that was being captured.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Fundamentally a CDP comes down to three things; Scalability, there&amp;rsquo;s only ever going be an increasing amount of data. Interoperability, to realize the value of the data, you need to be able to put it to work. Security, your customers trust you to look after their data and breach of that trust can cause irreparable harm.&lt;/p&gt;
&lt;p&gt;And here&amp;rsquo;s &lt;a href="https://twitter.com/mde_sitecore"&gt;Mark Demeny from Sitecore&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We&amp;rsquo;d agree that we&amp;rsquo;re in the midst of a third wave of content marketing built around context, and that&amp;rsquo;s been one of the guiding principles for &lt;a href="https://www.sitecore.com/resources/context-marketing"&gt;our development efforts&lt;/a&gt; for quite some time now, particularly with the xDB, where our primary focus wasn&amp;rsquo;t to provide analytics for historical analysis, but to provide a foundation for audience interaction (and be deeply integrated with our marketing automation and other tools).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the past, there was some opinion that CDP would be subsumed as a feature into other marketing and advertising technologies, but shifts in the market have changed the dynamic towards something more capable of handling the complexity of the current state of the market.&lt;/p&gt;
&lt;p&gt;First, the number of channels is starting to increase to include things like offline, support, voice and IoT that don&amp;rsquo;t necessarily go through the web and martech channels particularly easily. Second, first party control over how your customers choose to interact with your brand is even more important in the age of GDPR and diminishing comfort and ROI from social channels.&lt;/p&gt;
&lt;p&gt;But, like any move into an adjacent market, not all CMS vendors are convinced this is the right direction. Here&amp;rsquo;s an opinion from a mid-tier vendor who asked to remain anonymous, as they&amp;rsquo;re still watching the market develop.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We&amp;rsquo;re all for using customer data to improve content choices, to sharpen customer experiences or to upgrade personalization. Plenty of our customers have been integrating our CMS with their custom-built CDPs in the past and we now see customers making the connections between their CMS the new productized CDPs. However, the risk of feature creep and missing clearly identifiable excellence in the CMS is palpable. We don&amp;rsquo;t want to be yet another DXP that tries to do everything but can&amp;rsquo;t really get the fundamentals right &amp;ndash; or which cannot realize the promised benefits of the integrated suite.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The trend toward data-driven content and experience management is great &amp;ndash; we just believe CMS users are better off handling their marketing use case needs through more specialized tools that connect well.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;marketing suite vendors&lt;/strong&gt; are all jumping in as well. A couple of them declined to comment, but Adobe and Salesforce &lt;a href="https://www.theretailbulletin.com/news/salesforce-and-adobe-announce-theyre-working-on-a-cdp-12-04-19/"&gt;both announced CDP plans&lt;/a&gt; in the last week.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;After the Adobe and Salesforce announcements of entry into the CDP space, very few people doubt its usefulness. However, many people still rightfully challenge the ability of CDPs to deliver value, as the value is only seen after integration with channels that allow both transactional and personalized communications.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I love that quote because it says, &amp;ldquo;This is something we&amp;rsquo;re all super-excited about, but we&amp;rsquo;re not sure everyone can make it work…&amp;rdquo; Which, let&amp;rsquo;s face it, is the story told of all higher-end marketing features from the last 10 years.&lt;/p&gt;
&lt;p&gt;Regardless, in the end, all indications appear that this is What&amp;rsquo;s Next. (apologies to &lt;a href="https://www.youtube.com/watch?v=gSUHgAp7V7c"&gt;Martin Sheen&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;In writing this, I&amp;rsquo;m not trying to savvy anyone. If you&amp;rsquo;re creating good content regularly, good for you &amp;ndash; you&amp;rsquo;re doing better than most, even if you&amp;rsquo;re just yelling into the void.&lt;/p&gt;
&lt;p&gt;But, the natural maturation of a content marketing engine has traditionally moved that focus from content to campaigns. Organizations that got there were once on the leading edge. But the advent of the CDP signals that we&amp;rsquo;re moving up the scale to organizations that have comprehensive, contextual customer tracking, and who develop campaigns in response to that data, and target content directly to defined segments of that data.&lt;/p&gt;
&lt;p&gt;A gross over-simplification: Good &lt;strong&gt;content&lt;/strong&gt; gets you to 90%. A good &lt;strong&gt;campaign&lt;/strong&gt; strategy gets you to 99%. Perhaps understanding and leveraging &lt;strong&gt;context&lt;/strong&gt; is that last 1%?&lt;/p&gt;
&lt;p&gt;(Until, of course, the next thing comes along. To preserve my alliteration, I hope it starts with a hard &amp;ldquo;C.&amp;rdquo;)&lt;/p&gt;
&lt;p&gt;And this brings me to my final point, and what I think might be the natural end stage of this trend &amp;ndash; &lt;/p&gt;
&lt;p&gt;A CDP might become the foundational pillar of a content marketing engine. To date, we&amp;rsquo;ve been fixated on CMS. But when undergoing a digital transformation (a phrase I loathe, but which fits here), &lt;em&gt;organizations might shop for a CDP first&lt;/em&gt;, then layer a CMS over top of that. The CDP will be the core of their content efforts, &lt;em&gt;not a CMS&lt;/em&gt;. The CMS will just serve in support of a CDP.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m interested to see how the market develops. The current batch of CDPs aren&amp;rsquo;t cheap, and there doesn&amp;rsquo;t seem to be much of an open-source community around them, despite &lt;a href="https://unomi.apache.org/"&gt;Apache Unomi &lt;/a&gt;being a top-level project and the reference implementation for the OASIS standard.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.cmswire.com/digital-experience/why-the-apache-unomi-open-source-customer-data-platform-is-worth-a-look/"&gt;This article at CMSWire&lt;/a&gt; puts some more context around Unomi &amp;ndash; notably that it&amp;rsquo;s a &amp;ldquo;headless CDP,&amp;rdquo; to which you bring your own interface or third-parties start selling productized interfaces and data mining solutions for it. (Trivia: I can&amp;rsquo;t find confirmation of this, but the fact that Unomi sounds just like &amp;ldquo;you know me&amp;rdquo; cannot be an accident.)&lt;/p&gt;
&lt;p&gt;I think we might see three-way a digital divide, where we group organizations by what &amp;ldquo;C&amp;rdquo; they&amp;rsquo;ve achieved:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Content-centric:&lt;/strong&gt; most all organizations will remain here&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Campaign-centric:&lt;/strong&gt; will require some investment in marketing automation and considerable investment in staffing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context-centric:&lt;/strong&gt; will require a further investment in CDP tools&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m a old-school, server-side content guy. I was never comfortable with marketing technology, honestly &amp;ndash; I believed in the management and publication of good content, full stop. Start with that and you&amp;rsquo;ll be fine.&lt;/p&gt;
&lt;p&gt;But, weirdly, CDPs don&amp;rsquo;t freak me out. And part of this is probably because I&amp;rsquo;ve been selling the idea of human-centered content for more than a decade, and the promise of moving the locus of control from the content to the customer seems like a natural, healthy progression to me. I particularly like the separation of customer and behavior data from content &amp;ndash; I feel like there&amp;rsquo;s a crossing of concerns there otherwise, that makes things muddier.&lt;/p&gt;
&lt;p&gt;Also, I&amp;rsquo;ve mentioned the phrase &amp;ldquo;content marketing&amp;rdquo; a few times in this post. It&amp;rsquo;s little-known fact that when you say that three times, &lt;a href="http://robertrose.net/"&gt;Rob Rose&lt;/a&gt; appears, &lt;a href="https://www.youtube.com/watch?v=Ot11DMJKhj8"&gt;just like Beetlejuice&lt;/a&gt;. (I&amp;rsquo;m kidding &amp;ndash; Rob has been a friend for 10 years. I sent him the draft of this post and asked him to comment.)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Successful Marketers are starting to look at their databases as &amp;ldquo;audiences&amp;rdquo; rather than simply &amp;ldquo;leads&amp;rdquo; or &amp;ldquo;opportunities&amp;rdquo;. The pressures of GDPR and other data management challenges require companies to take a CRM-like approach to their classic marketing data. This is where CDP&amp;rsquo;s can truly serve as the pre-customer database. This is where marketers utilize (and manage) a much more holistic (and cross channel) view of audiences and their preferences in order to develop trust much earlier in their journey.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here&amp;rsquo;s what I like about this quote:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&amp;quot;audiences&amp;rdquo;:&lt;/strong&gt; We do our best work for audiences. We &lt;em&gt;perform&lt;/em&gt; for audiences. Whether it&amp;rsquo;s theater or digital, a more concrete concept of the &amp;ldquo;audience&amp;rdquo; makes us better at what we do. Editors like to know their stuff is being consumed, and if they can have a longer view of that context, they&amp;rsquo;re likely to get higher satisfaction from content creation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&amp;quot;pre-customer&amp;rdquo;:&lt;/strong&gt; This speaks to the fact that with a CRM, you&amp;rsquo;re talking to customers or direct prospects. A CDP, rather, is elevating your content consumers to a higher level. You can still push content like crazy, but now you&amp;rsquo;re taking direct steps to realize some return on that.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&amp;quot;develop trust much earlier in their journey&amp;rdquo;:&lt;/strong&gt; And this has always been the implicit dream of content marketing. We&amp;rsquo;re going to show you what we know and what we can do before we even start talking to you about a sale. Hopefully, we&amp;rsquo;ll build credibility (trust) before we unleash sales on you.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If this reasoning helps organizations push more content because they can realize a return on it more easily, then that&amp;rsquo;s a good thing.&lt;/p&gt;
&lt;p&gt;CDPs might provide the justification and ROI necessary for organizations to invest in better content. If they can identify a piece of the ROI puzzle earlier, then more exploratory content is easier to justify. A CMO might throw more money at content creation if there&amp;rsquo;s a mechanism for them to isolate a return on it, and a CDP might be that mechanism.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m here for that. We all should be.&lt;/p&gt;</description>
      <pubDate>Thu, 18 Apr 2019 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/cdp/</guid>
    </item>
    <item>
      <title>Repouring the Foundation: The Perils of Content Modeling on the Fly</title>
      <link>https://live.deanebarker.net/tech/blog/modeling-on-the-fly/</link>
      <description>&lt;p&gt;I teach &amp;ldquo;Introduction to Content Management&amp;rdquo; in the &lt;a href="https://www.fh-joanneum.at/content-strategie-und-digitale-kommunikation/master/en/programme/"&gt;Content Strategy&lt;/a&gt; program at &lt;a href="https://www.fh-joanneum.at/en/"&gt;FH Joanneum&lt;/a&gt;. I talk about &lt;a href="http://flyingsquirrelbook.com/glossary/term/content-model"&gt;content modeling&lt;/a&gt; quite a bit, and in the final lecture, I have a slide that just says this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Content models are foundational.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And they are. Your content model is the base on which you build most everything else you do with your CMS.&lt;/p&gt;
&lt;p&gt;Defining the content model of a CMS implementation is one of the first things you do. At &lt;a href="http://blendinteractive.com/"&gt;Blend&lt;/a&gt;, we&amp;rsquo;ll usually start by paging through wireframes and writing down the content types we see, adding attributes, combining them, abstracting reusable elements, etc. This forms the core of the entire implementation.&lt;/p&gt;
&lt;p&gt;A content model can be said to be &amp;ldquo;established&amp;rdquo; when you&amp;rsquo;ve implemented it and built a bunch of functionality on top of it. During the implementation, you&amp;rsquo;ll realize you have some mistakes and inefficiencies, which you can correct as an expected task of development.&lt;/p&gt;
&lt;p&gt;But fast forward two years down the road &amp;ndash; your model is now loaded up with actual content, and you have templates, workflows, external integrations, and all sorts of other things built which depend on your content being in the format that you settled on when you launched the site.&lt;/p&gt;
&lt;p&gt;Like it or not, your model is now &amp;ldquo;established.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Changing content models after they&amp;rsquo;re established can be tricky, just like changing the foundation of a house can be tricky after you&amp;rsquo;ve poured it.&lt;/p&gt;
&lt;p&gt;True story: I don&amp;rsquo;t have a front porch on my house because &amp;ndash; 20 years ago &amp;ndash; the contractor started building it four feet (just over one meter) too close to the road. We didn&amp;rsquo;t realize this until after the foundation was poured. At that point, it was too late.&lt;/p&gt;
&lt;p&gt;I was talking to my friend Allan Thraen about this the other day. Allan worked at Episerver for a decade, and now he&amp;rsquo;s off on his own at &lt;a href="https://codeart.dk/"&gt;CodeArt&lt;/a&gt;. Our conversation drifted into the idea of letting editors modify an established content model without a developer being involved, and was this a good idea?&lt;/p&gt;
&lt;p&gt;The conversation resulted in a great blog post from Allan: &lt;a href="https://www.codeart.dk/blog/2019/4/the-curious-case-of-content-modelling/"&gt;The Curious Case of Content Modeling&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s worth reading. In particular, Allan recounts the situation of a client using Contentful, and allowing business users to do their own content modeling, without any developers being consulted:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If they for instance added a new field, or even a new content type, it would of course not be visible on the web site until their developer had put it into their rendering, but they could start to create content for it right away and that way it would be easy for the developer to see just how it would fit and make the proper front-end adjustments. In fact, all they needed was a front-end developer to update their site with the desired changes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As a back-end engineer, this just freaks me right the hell out, but it seems to be working for them so who am I to judge?&lt;/p&gt;
&lt;p&gt;The key is this: content modeling takes skill. It&amp;rsquo;s easy to build a dumb, inefficient content model that makes future changes difficult (&amp;ldquo;We don&amp;rsquo;t need &amp;lsquo;FirstName&amp;rsquo; &lt;em&gt;and&lt;/em&gt; &amp;lsquo;LastName.' That&amp;rsquo;s just wasteful! Let&amp;rsquo;s just have one &amp;lsquo;Name&amp;rsquo; field!&amp;rdquo;)&lt;/p&gt;
&lt;p&gt;However, if you &lt;em&gt;do&lt;/em&gt; have skill at it, then it doesn&amp;rsquo;t matter what your job title is. These skills are more often found with engineers than editors, just because engineers have experience with data modeling and abstraction, but a good content strategist can generate perfectly fine content models. In many teams, there might be a super-user, administrator, or &lt;a href="https://www.realstorygroup.com/Blog/1653-Let-us-now-praise-metators"&gt;metator&lt;/a&gt; (all hail &lt;a href="https://ischool.uw.edu/people/faculty/profile/bboiko"&gt;Boiko&lt;/a&gt;!) that has the wisdom and perspective to do this well.&lt;/p&gt;
&lt;p&gt;In fact, here are two books that do a wonderful job of bringing content modeling into the editorial space:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://rosenfeldmedia.com/books/content-everywhere/"&gt;Content Everywhere&lt;/a&gt;, by Sara Wachter-Boettcher&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Designing-Connected-Content-Products-Tomorrow/dp/0134763386"&gt;Designing Connected Content&lt;/a&gt;, by Carrie Hane and Mike Atherton&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(I wrote a sidebar for the former, and I&amp;rsquo;m quoted in the latter…but, really, who&amp;rsquo;s keeping track?)&lt;/p&gt;
&lt;p&gt;Also, Ann Rockley did a lovely job several years ago in defining a &amp;ldquo;back end content strategist&amp;rdquo;: &lt;a href="https://contentmarketinginstitute.com/2016/02/types-content-strategist/"&gt;Why You Need Two Types of Content Strategist&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Back-end strategists … have a love for structure, scalability, and technology. They make recommendations about how to use technology &amp;ndash; hardware and software &amp;ndash; to handle all that content in efficient and powerful ways. This type of strategist answers questions like these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How can we organize content so that our authors can easily store and retrieve it, and prepare it for automated selection and delivery in the relevant channels?&lt;/li&gt;
&lt;li&gt;How do we structure the content so that modules are consistent and can be easily assembled (mixed and matched) on-demand to meet customer needs?&lt;/li&gt;
&lt;li&gt;How do we make sure that we aren&amp;rsquo;t creating, recreating, and recreating content over and over for each channel?&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&amp;rsquo;s great stuff, and it really gets to the absolute core of content modeling. All those questions are critical when defining what your content looks like inside your CMS.&lt;/p&gt;
&lt;p&gt;But content modeling still has a reputation for being something like the Dark Arts, which is done by a select few and requires an Act of God to be deployed where it can provide some productive value.&lt;/p&gt;
&lt;p&gt;So, the desire to modify established content models &amp;ldquo;on-the-fly&amp;rdquo; is still something people ask for in RFPs. More and more editorial groups want to be able to do everything without a developer involved, in a continuing quest to liberate themselves from any external limitations.&lt;/p&gt;
&lt;p&gt;Generally speaking, content modeling can be done two ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;As Allan points out in this article, many systems allow for the definition of content models &lt;strong&gt;from the administrative interface&lt;/strong&gt;. Episerver used to do this, Drupal does this &amp;ndash; dozens of systems do this. At any time, an editor with sufficient permissions could conceivably go in and just…change stuff.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In contrast, many systems require content modeling to be done &lt;strong&gt;from code or configuration&lt;/strong&gt;. In most every current Episerver implementation, content models are C# classes. In Sitecore, a lot of developers do their content modeling from a Visual Studio extension called Sitecore Rocks, then this can be synchronized with the production instance. These are things that a developer needs to do.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When you model content from code, you have technically &amp;ldquo;done development,&amp;rdquo; and you&amp;rsquo;ll need a code deploy to get your changes launched. Many editorial teams hate this, because then they&amp;rsquo;re dependent on someone else, not to mention being subject to deployment schedules, change control, regression testing, etc. They&amp;rsquo;re trying to achieve this ideal vision of being able to do everything without outside resources or limitations.&lt;/p&gt;
&lt;p&gt;However, this is often not realistic for the same reason I quote at the beginning of this post:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Content models are foundational.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And just like the foundation of a house, a lot of stuff rides &amp;ldquo;on top&amp;rdquo; of an established content model. The model change might just be the tip of the iceberg, and is all the stuff below the waterline &lt;em&gt;also&lt;/em&gt; editable from the interface?&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s assume an editorial team can edit their content model, and they decide to add a property/attribute &amp;ndash; let&amp;rsquo;s say they add &amp;ldquo;Mood&amp;rdquo; to an article to track the mood that the author was in when they wrote it. Let&amp;rsquo;s also assume they know what they&amp;rsquo;re doing, and they know to add it as a dropdown or a checkbox list or a text box or whatever is correct for their implementation.&lt;/p&gt;
&lt;p&gt;Doing this from the interface allows them to do exactly one thing: &lt;em&gt;capture data&lt;/em&gt;. But they don&amp;rsquo;t capture data just for giggles. Clearly, the editorial team is going to &lt;em&gt;do something else&lt;/em&gt; with this property.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Do they want to output it somewhere?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do they want to use this in some event tracking or workflow, maybe to trigger additional review of the author is &amp;ldquo;angry&amp;rdquo; or &amp;ldquo;hostile&amp;rdquo;?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do they want it to affect channel distribution? So, &amp;ldquo;happy&amp;rdquo; articles also get pushed into the &lt;a href="https://twitter.com/goodnews"&gt;@goodnews&lt;/a&gt; tweet stream.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do they only want this attribute only available to editors who have been working at the company for six months?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do they want to disallow editing of this attribute after the article is published, or prevent editors from changing their mood after the fact?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, you can sure add the property, but how much more can do you than that? Most systems have file-based templating, so to get that attribute even added to an output artifact, someone is going to have to change a template file and deploy it…which brings you right back to the code change you were trying to avoid in the first place.&lt;/p&gt;
&lt;p&gt;Now, this isn&amp;rsquo;t the case with all systems. Some CMSs will allow you to do a lot more than just add the attribute.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Drupal is probably the King of Configuration. You can do a lot in Drupal without writing code, and you could conceivably get that attribute output somewhere from the interface by adding it to a view or modifying the display fields of a type. And there are other Drupal-like CMSs that treat output as a matter of configuration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some systems like Umbraco and TERMINALFOUR allow templating from the interface. The actual templates are editable through embedded code editors, and don&amp;rsquo;t have to be &amp;ldquo;deployed.&amp;rdquo; In some cases, they read/write from the file system, so you get the best of both worlds (spoiler: it&amp;rsquo;s actually the &lt;em&gt;worst&lt;/em&gt; of both worlds because now you&amp;rsquo;re writing files in production that aren&amp;rsquo;t in source control, but whatever…)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But here we&amp;rsquo;re still just discussing the ideal scenario: (1) &lt;em&gt;adding&lt;/em&gt; an attribute, and (2) getting that to display somewhere. This is probably the simplest use case. And even if you accomplish this purely from the UI, you&amp;rsquo;ve still had to engage a developer-ish person to re-template or style the output.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re working this hard to avoid a code deploy, maybe you just have a DevOps problem? Or if you&amp;rsquo;re &lt;em&gt;that&lt;/em&gt; estranged from developers, maybe you have an organizational or managerial problem?&lt;/p&gt;
&lt;p&gt;And don&amp;rsquo;t even get me started about the scarier edge cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Content model changes or deletions.&lt;/strong&gt; Aside from losing data &amp;ndash; which is a &lt;em&gt;huge&lt;/em&gt; problem &amp;ndash; there might be dozens of processes that editors don&amp;rsquo;t know about that depend on the content being in a specific format.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Things other than templating.&lt;/strong&gt; Integrations, workflows, advanced permissions, and anything that involves data exchange with an external system.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The larger principle at work here is the division of duties. Who can do what in a CMS implementation? I touched on this a while back in a post about another quasi-development feature that editorial teams constantly want to do: ~/tech/blog/truth-about-cms-form-builders/&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Understand that if your expectations are to integrate your forms with a wide variety of other systems, then you&amp;rsquo;re not going to get the freedom from development that you&amp;rsquo;re looking for, and only having the UI portion of these integration scenarios under editorial control will rarely ever be helpful.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The same thing applies here. You can find systems that will let editors change content models on-the-fly, but that&amp;rsquo;s not nearly as much freedom as they actually want.&lt;/p&gt;
&lt;p&gt;In most cases, it will give them very limited control over a very limited number of things. In addition to waiting on a development team to finish all the things they can&amp;rsquo;t, they might find that the first thing the developer does is undo all their work and re-implement it to account for technical parameters they weren&amp;rsquo;t aware of and couldn&amp;rsquo;t be expected to understand.&lt;/p&gt;
&lt;p&gt;Once a content model becomes established, it&amp;rsquo;s hard to change, and it probably should be. In most implementations, there&amp;rsquo;s a lot riding on it.&lt;/p&gt;
&lt;p&gt;I remain unconvinced that reducing the barrier to change here will result in a better experience over the long term.&lt;/p&gt;</description>
      <pubDate>Sun, 7 Apr 2019 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/modeling-on-the-fly/</guid>
    </item>
    <item>
      <title>Words, Links, and Centrality: Evaluating 17 Years of Gadgetopia Content</title>
      <link>https://live.deanebarker.net/tech/blog/evaluating-gadgetopia-content/</link>
      <description>&lt;p&gt;I&amp;rsquo;ve been blogging at Gadgetopia for almost 17 years. Here&amp;rsquo;s &lt;a href="/tech/blog/gutenberg-project/"&gt;my first post from 2002&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve decided to do some clean-up.&lt;/p&gt;
&lt;p&gt;Some history &amp;ndash; &lt;/p&gt;
&lt;p&gt;Before Twitter, blogs and RSS &lt;em&gt;were&lt;/em&gt; Twitter, so a lot of my posts from 2003-2005 were very tweet-like &amp;ndash; they were very short, often less than 100 words, and just contained a single link. They were admittedly low-value. I was often just throwing out a link that my audience might find interesting, and adding some context around it (and, okay, I would often throw in an opinion or…12).&lt;/p&gt;
&lt;p&gt;And let you think the word &amp;ldquo;audience&amp;rdquo; is overstating things, know that back in the heady &amp;ldquo;blogosphere&amp;rdquo; days in the early Naughts, we did have defined audiences. RSS, comments, and pingbacks coalesced to form loose communities, much like social networks do now. I still know and interact with people who I first &amp;ldquo;met&amp;rdquo; in Gadgetopia comments 10-15 years ago. I&amp;rsquo;ve met several of them in-person.&lt;/p&gt;
&lt;p&gt;A big problem for Gadgetopia is that many of those old posts have broken links, and many times, &lt;em&gt;the link was the entire point of the post&lt;/em&gt;. This means that they&amp;rsquo;re a segment in a chain of link rot. Without the link, the post doesn&amp;rsquo;t make sense, and I&amp;rsquo;m just cluttering up the internet.&lt;/p&gt;
&lt;p&gt;So, it&amp;rsquo;s time for a purge. I&amp;rsquo;m determined to clean up old posts by removing them intelligently. I won&amp;rsquo;t &amp;ldquo;404 Not Found&amp;rdquo; them (yes, I used that as a verb) &amp;ndash; that status code means &amp;ldquo;Nothing was ever here.&amp;rdquo; Rather, I&amp;rsquo;ll &amp;ldquo;410 Gone&amp;rdquo; them, which means, &amp;ldquo;There &lt;em&gt;was&lt;/em&gt; something here, but it has been removed.&amp;rdquo; Additionally, I&amp;rsquo;ll provide contact information so if someone &lt;em&gt;really&lt;/em&gt; wants something, they can get in touch, and I&amp;rsquo;ll dig it out of the archives just for them.&lt;/p&gt;
&lt;p&gt;But here&amp;rsquo;s the thing &amp;ndash; &lt;/p&gt;
&lt;p&gt;When inventorying content, you cross an important line when you can no longer look at each piece of content individually. At some point, you can&amp;rsquo;t come to a determination through nuanced perception and analysis, because there&amp;rsquo;s just too much content.&lt;/p&gt;
&lt;p&gt;Gadgetopia has over 7,000 posts. Even if I reviewed 100 blog posts a day &amp;ndash; which is harder than you think &amp;ndash; it would still take me almost four straight months to sort through everything.&lt;/p&gt;
&lt;p&gt;So, what do you do when there&amp;rsquo;s too much?&lt;/p&gt;




&lt;table-of-contents title="Contents" selector="h2, h3, h4"&gt;&lt;/table-of-contents&gt;

&lt;h2&gt;Content Evaluation Rules&lt;/h2&gt;
&lt;p&gt;Back in 2009, I worked with &lt;a href="https://davidhobbsconsulting.com/"&gt;David Hobbs&lt;/a&gt; on a content migration for &lt;a href="http://cno.org/"&gt;The College of Nurses of Ontario&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;David is a consultant who specializes in migrations and large-scale site transformations. It was on this first consulting project together that he brought up the idea of &amp;ldquo;rules.&amp;rdquo;  David had the idea that we would score each piece of content according to a set of metrics, and our first pass of evaluation would be based on that numeric value.&lt;/p&gt;
&lt;p&gt;I remember thinking this was really…impersonal. I was convinced nothing could substitute for human-powered, individual evaluation. For me, a content inventory was an artisanal experience.&lt;/p&gt;
&lt;p&gt;Honestly, I don&amp;rsquo;t remember if we actually implemented rules on that project, but a few years later, David gave a great conference session on rule processing. He had a case study where he had done this for a client at scale. What he described there made more sense to me, because the client had a &lt;em&gt;lot&lt;/em&gt; of content. I started to come around, and the idea of a rule-based approach has stuck with me.&lt;/p&gt;
&lt;p&gt;David has gone on to create a &amp;ldquo;content exploration&amp;rdquo; tool called &lt;a href="https://chimera.davidhobbsconsulting.com/"&gt;Content Chimera&lt;/a&gt; &amp;ndash; currently in beta &amp;ndash; which allows for the slicing, dicing, scoring, and mass evaluation of content:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Content Exploration and Decision-Making At Scale&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That tagline is telling, and we&amp;rsquo;ll revisit it below.&lt;/p&gt;
&lt;p&gt;But, back to Gadgetopia &amp;ndash; the only way I can hope to get through all this content is to evaluate posts with the help of some set of rules or metrics. I&amp;rsquo;m still in the middle of this process, but I thought I&amp;rsquo;d share with you some of what I&amp;rsquo;ve learned, and some of the data I&amp;rsquo;m planning to use when scoring and evaluating Gadgetopia posts.&lt;/p&gt;
&lt;h2&gt;What Are The Goals of Your Content?&lt;/h2&gt;
&lt;p&gt;When you evaluate content, you invariably run into the question: what is the overall point of the content?&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s just no way to figure out whether something stays or goes without evaluating it against some yardstick of value. &amp;ldquo;Is this worth keeping?&amp;rdquo; can only be answered with some measure of &amp;ldquo;worth&amp;rdquo; in mind.&lt;/p&gt;
&lt;p&gt;For Gadgetopia, there are two goals to the content:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;To further the CMS industry, at whatever level is possible. I like to think that posts I&amp;rsquo;ve published have sparked discussions, decisions, or otherwise influenced behavior. (ex: someone told me the other day that their framing of &amp;ldquo;content operations&amp;rdquo; came from &lt;a href="/tech/blog/need-for-content-operations/"&gt;this post&lt;/a&gt;, which they credited as the seminal definition of the term &amp;ndash; I don&amp;rsquo;t know of this is actually true, but it made me feel pretty good)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To provide marketing value for my company, &lt;a href="http://blendinteractive.com/"&gt;Blend Interactive&lt;/a&gt;. Second only to our body of work itself, Gadgetopia is the largest collection of public evidence that we know what we&amp;rsquo;re doing (yes, even more than &lt;a href="http://flyingsquirrelbook.com/"&gt;my book&lt;/a&gt;). I often refer to Gadgetopia posts in proposals, and I send links to people to support a sales effort.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(Note that these are the goals of the content &lt;em&gt;today&lt;/em&gt;. As I&amp;rsquo;ve been going through old content, I was struck by how the goals of a site and its content change over time. Posts that seemed valuable a decade ago seem silly now, &lt;em&gt;and that&amp;rsquo;s okay&lt;/em&gt;. We all change. Even websites.)&lt;/p&gt;
&lt;p&gt;In articulating those goals, I&amp;rsquo;ve been careful to give myself permission to make decisions in flagrant violation of the rules when that decision would impede one the two goals above. (Which raises the question, why even have rules then? We&amp;rsquo;ll talk more about that in the conclusion below.)&lt;/p&gt;
&lt;p&gt;More helpfully, my goals help me define what I&amp;rsquo;m looking to keep: I want to keep content that somehow benefits the CMS industry with its availability, or helps market my company by demonstrating our competence and breadth of experience.&lt;/p&gt;
&lt;p&gt;Rules are helpful to me only to the extent that they assist me in identifying that content.&lt;/p&gt;
&lt;h2&gt;False Positives and Negatives&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s what I originally feared when David proposed using evaluation rules: &lt;em&gt;a rule might make a mistake&lt;/em&gt; &amp;ndash; it will somehow be applied to some outlier content that fits outside the norm, and that content will either  be:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Kept when it doesn&amp;rsquo;t advance a goal&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discarded when it &lt;em&gt;does&lt;/em&gt; advance a goal, or there&amp;rsquo;s some other intangible or tacit reason why it should be kept&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That latter freaks me out more than the former. A pointless post taking up space at some URL doesn&amp;rsquo;t bother me so much, but a good post that can&amp;rsquo;t be found anymore is specifically what I&amp;rsquo;m trying to avoid.&lt;/p&gt;
&lt;p&gt;Rules aren&amp;rsquo;t perfect, and they&amp;rsquo;re going to make mistakes. The two fears aren&amp;rsquo;t reasons to discard their use entirely, but we&amp;rsquo;ll talk more later about how to minimize the chance they&amp;rsquo;ll do real damage.&lt;/p&gt;
&lt;p&gt;David points out that your fear of rules is directly proportional to how permanent your changes are going to be. If you&amp;rsquo;re actually &lt;em&gt;deleting&lt;/em&gt;, well, that can be scary. But if you&amp;rsquo;re just archiving at some level, or perhaps just removing content from indices, then the ramifications of rules become a lot easier to live with.&lt;/p&gt;
&lt;p&gt;Finally, when looking at a content repository as large as this one, you need to ask: would a rule make more or fewer mistakes than a manual review?  Without assistance, I&amp;rsquo;d probably make a &lt;em&gt;ton&lt;/em&gt; of mistakes on my own. Worse, without rules to make it easier, I would never even do the evaluation, which might be the biggest mistake of them all.&lt;/p&gt;
&lt;h2&gt;Rule: Traffic&lt;/h2&gt;
&lt;p&gt;The first, and most obvious metric might be raw traffic, in the form of page views.&lt;/p&gt;
&lt;p&gt;I managed to pull the number of page views each post had gotten since January 1. I&amp;rsquo;d like to say this was graceful, but I just pulled a CSV from Google Analytics, and parsed it. I snapshotted this at a particular moment in time, but since it&amp;rsquo;s representative of larger period, it&amp;rsquo;s a valid metric.&lt;/p&gt;
&lt;p&gt;Of course, some posts were published &lt;em&gt;during&lt;/em&gt; this time period, so they would have less traffic, and other posts were published within the last year, so they have had less of a chance to develop a &amp;ldquo;Google presence.&amp;rdquo; However, this doesn&amp;rsquo;t matter, because all posts from the last couple of years will likely be retained, so the odds of a false positive based on low traffic is slim.&lt;/p&gt;
&lt;p&gt;Clearly, there&amp;rsquo;s a long tail of posts with zero page views. How long?  &lt;em&gt;About 90% of the site.&lt;/em&gt; Yes, it&amp;rsquo;s true &amp;ndash; over 6,500 posts have had &lt;em&gt;no views&lt;/em&gt; in the last three months. That statistic hurt a little to comprehend, but there you go.&lt;/p&gt;
&lt;p&gt;But, let&amp;rsquo;s go back to my two goals, and put this in perspective &amp;ndash; if a post fulfills one of those two goals, does it matter that it doesn&amp;rsquo;t have any traffic in the three-month span I was checking for?  No, it doesn&amp;rsquo;t.  Given my goals, even if a post has no page views, I still might send it out on a proposal once a year or so, and it&amp;rsquo;s critical for that. So lack of traffic to an otherwise good post isn&amp;rsquo;t the deciding factor.&lt;/p&gt;
&lt;p&gt;Consider this post: &lt;a href="/tech/blog/spanning-the-gap/"&gt;Spanning the Gap from Feature to Conversion: Are We Building the Right Bridges?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s gotten &lt;em&gt;zero&lt;/em&gt; traffic since January 1, but it&amp;rsquo;s a good post that makes a solid point. I wouldn&amp;rsquo;t get rid of it based purely on the work I put into it and my belief that it has some value to the broader industry. So, traffic or not, that one stays.&lt;/p&gt;
&lt;p&gt;What about the opposite &amp;ndash; what if an objectively &amp;ldquo;bad&amp;rdquo; post gets a ton of traffic? Should I keep it?  No &amp;ndash; it doesn&amp;rsquo;t really fulfill a goal for me and is probably just cluttering up the internet.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://archive.gadgetopia.com/post/5878"&gt;This post about the mathematical order of operations&lt;/a&gt; is consistently the highest-trafficked post on Gadgetopia due to a quirk of Google indexing (to the point where I put a note at the top directing people to the comments, where the answer to their question is probably located). Do I want to keep this? No. It has nothing to do with anything else on the site.&lt;/p&gt;
&lt;p&gt;Also worth noting &amp;ndash; I think I might be doing a disservice to the internet by keeping this post up. The search referrers make it obvious that it&amp;rsquo;s mainly found by kids doing homework, and there are far better resources than this to find the answer to the question. Removing this post would allow people to find the answer more directly.&lt;/p&gt;
&lt;p&gt;I actually 410&amp;rsquo;d a bunch of posts last year. Using the &lt;a href="https://en.wikipedia.org/wiki/Google_Search_Console"&gt;Google Search Console&lt;/a&gt;, I found all sorts of posts that were lodged in Google for strange reasons, and were attracting pointless, no-value traffic.&lt;/p&gt;
&lt;p&gt;For example, I had a post about some aspect of a mobile phone (I&amp;rsquo;m being intentionally vague to avoid being indexed for the phrase again). This was just a &amp;ldquo;pass-through&amp;rdquo; post &amp;ndash; I had a couple of sentences with a link to a news article I had found.&lt;/p&gt;
&lt;p&gt;This post got a &lt;em&gt;ton&lt;/em&gt; of traffic from Google, year after year. And it was pointless traffic from visitors that didn&amp;rsquo;t further any goal for me, and who really just needed to click the link in the post. But, they still often didn&amp;rsquo;t find what they were looking for, so they came back to my post, and filled up the comment with complaints.&lt;/p&gt;
&lt;p&gt;So, I wrote some code in WordPress to send back a 410 whenever the post was requested, and added this note to the page:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you&amp;rsquo;re looking for information on a [phrase that will not be written here], here is the link you want: [the link]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here, &lt;a href="http://archive.gadgetopia.com/post/5588"&gt;take a look for yourself&lt;/a&gt;. With the 410, Google eventually de-indexed it, and any vestigial traffic due to hard-coded links will find my note.&lt;/p&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;The linked post above has since been redirected to the archives, so that link no longer reflects what&amp;rsquo;s claimed here.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;Traffic is just not an absolute metric for me. It&amp;rsquo;s interesting to look at, and I might take it into account, but I wouldn&amp;rsquo;t remove or keep any post based solely on that number.&lt;/p&gt;
&lt;h2&gt;Rule: Size&lt;/h2&gt;
&lt;p&gt;The second metric is content size, specifically word count.  This matters because a lot of my earlier posts were really just tweets-in-disguise (Gadgetopia predates Twitter by six years). The longer a post, the more &amp;ldquo;meat&amp;rdquo; it had, and thus the greater potential for contributing toward one of my goals.&lt;/p&gt;
&lt;p&gt;I did a search for posts of less than 100 words. Result: 2,805 posts.  Most of these (about 1,700) have a single outbound link. There are so many small posts, in fact, that moving the threshold up to less than 300 words &lt;em&gt;still includes 88% of the posts&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;On the other end of the scale, here are the longest posts on Gadgetopia:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/content-management-is-emergent-skill/"&gt;Content Management is an Emergent Skill&lt;/a&gt;: 6,290 words&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://archive.gadgetopia.com/post/3606"&gt;Interview with Josh Clark&lt;/a&gt;: 5,070 words, but most of them not my own&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/truth-about-cms-form-builders/"&gt;The Truth About CMS Form Builders&lt;/a&gt;: 3,711 words&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/content-personalization-reality-check/"&gt;Content Personalization: A Reality Check&lt;/a&gt;: 3,596 words&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/multi-stage-transformation/"&gt;Multi-stage Templating as Progressive Denormalization&lt;/a&gt;: Tied at 3,470 words&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/points-of-differentiation-in-headless-cms/"&gt;Points of Differentiation in Headless CMS&lt;/a&gt;: Tied at 3,470 words&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Clearly, size seems to be very correlated with posts I would keep.&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t reviewed them all, but I can&amp;rsquo;t think of a single post less than 100 words that I would keep. On the other side, very long posts are likely to be something about CMS as that&amp;rsquo;s the topic I write most deeply about (the Josh Clark interview even relates &amp;ndash; at the time he was running &lt;a href="https://en.wikipedia.org/wiki/Big_Medium"&gt;Big Medium&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;A possible option here: correlate word count against some of the other, more advanced metrics below and determine the smallest size that could reasonably product a post of marketing or thought leadership value.&lt;/p&gt;
&lt;h2&gt;Rule: Link Integrity&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve decided to clean up because so many links are broken. So, the third rule I&amp;rsquo;m looking at is outbound link count and integrity &amp;ndash; what percentage of links in the post are broken?&lt;/p&gt;
&lt;p&gt;A common pattern for me years ago was posting simply as a method to share a link, so I searched for how many posts contained just a single link (3,385) and how many of those single-link posts were broken (2,264).&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s right: fully 67% of single-link posts are just broken segments in a chain. If someone got to them, they wouldn&amp;rsquo;t get any further.&lt;/p&gt;
&lt;p&gt;But what threshold do you set when just &lt;em&gt;some&lt;/em&gt; of the links are broken. When does that invalidate the entire post?&lt;/p&gt;
&lt;p&gt;Consider &lt;a href="http://archive.gadgetopia.com/post/2347"&gt;this post from 15 years ago&lt;/a&gt; where I discussed (and linked to) all the tools I use to do my job. There are 29 links in that post, and 24 of them are no longer valid. Clearly, this post needs to go.&lt;/p&gt;
&lt;p&gt;But what about &lt;a href="/tech/blog/thoughts-on-posts-and-articles/"&gt;this post from 16 years ago&lt;/a&gt; where I discuss the difference between ephemeral and permanent content (which is ironic in the context of this discussion). Of the 18 links, 5 of them are broken. That&amp;rsquo;s less than half, but still a lot.&lt;/p&gt;
&lt;p&gt;That post in particular is complicated because it&amp;rsquo;s on a topic I still ponder quite often today. Even though many of the links are bad, the topic is still valid, and I make some points worth preserving. If I decide to keep it, do I somehow call out that I know a lot of the links are broken, but I&amp;rsquo;m keeping it anyway?&lt;/p&gt;
&lt;p&gt;I actually did this with &lt;a href="http://archive.gadgetopia.com/post/3024"&gt;a post last year&lt;/a&gt;. I put a note and the top that said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sadly the serial number lookup system doesn&amp;rsquo;t seem to be in the same place any longer. The link no longer works, but the story and reasoning are still interesting, so I&amp;rsquo;m leaving the post up. Plus, the screencap link still works, so you can see how the system used to work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And here&amp;rsquo;s &lt;a href="http://archive.gadgetopia.com/post/6925"&gt;another&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The main link in this article no longer works (as of October 2016), but the quote stands on its own, so I&amp;rsquo;m leaving this post up.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;rsquo;ll probably end up removing these two posts for other reasons (they don&amp;rsquo;t contribute to either of my two goals), but what about situations like the older post listed earlier, where a critical mass of broken links still doesn&amp;rsquo;t invalidate the main thrust of the content?&lt;/p&gt;
&lt;p&gt;I could envision a script that periodically checked links and put a class on them that popped a message on mouseover that said, &amp;ldquo;Note: this link doesn&amp;rsquo;t work anymore,&amp;rdquo; and maybe a note at the top that warned the reader before they invested time.&lt;/p&gt;
&lt;p&gt;So, outbound link integrity is another brush stroke, but &amp;ndash; like the other rules &amp;ndash; not absolute.&lt;/p&gt;
&lt;h2&gt;Rule: Centrality&lt;/h2&gt;
&lt;p&gt;For years, I&amp;rsquo;ve kept track of intra-site links. When a post is published, I extract all the links to other posts on Gadgetopia. I store these in a database table, so at the bottom of every post, I can provide links to posts which link &lt;em&gt;into&lt;/em&gt; that post.&lt;/p&gt;
&lt;p&gt;This was an attempt to provide links to posts that were related, but didn&amp;rsquo;t exist at the time I was writing the first post. It&amp;rsquo;s worked reasonably well over the years, enabled readers to look &amp;ldquo;forward in time&amp;rdquo; to see how the post they&amp;rsquo;re reading was referenced later on.&lt;/p&gt;
&lt;p&gt;Using this data, I attempted to capture something else I&amp;rsquo;m been interested in for some time: &amp;ldquo;centrality.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;By centrality, I mean, how central is a post to the &amp;ldquo;network&amp;rdquo; of posts on Gadgetopia? Every post which has an outbound link &lt;em&gt;to&lt;/em&gt; another Gadgetopia post or an inbound link &lt;em&gt;from&lt;/em&gt; another post combine to form a network of posts. You can envision a map with cities and highways which connect those cities. Post A might link to Post B which might link to Post C and form something of a link chain. Mathematically, this is known as a &amp;ldquo;graph&amp;rdquo;, and we can do all sorts of analysis on it (there&amp;rsquo;s an entire science to it: &lt;a href="https://en.wikipedia.org/wiki/Graph_theory"&gt;Graph Theory&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I found a graphing library (&lt;a href="https://github.com/YaccConstructor/QuickGraph"&gt;QuickGraph&lt;/a&gt;), and calculated paths from one post to another. There were 1,286 posts with an inbound or outbound link (so they were considered part of the larger network/graph), which resulted in about 1.6 million theoretical paths.&lt;/p&gt;
&lt;p&gt;It turned out that only 20,944 could be calculated (if two posts were linked to each other but nothing else, they then formed a &amp;ldquo;link island&amp;rdquo; that didn&amp;rsquo;t connect to any of the other 1,284 posts). Each path was a series of &amp;ldquo;hops,&amp;rdquo; and I recorded every post that any hop passed through, then counted up the occurrences.&lt;/p&gt;
&lt;p&gt;This, it turns out, is called &amp;ldquo;&lt;a href="https://en.wikipedia.org/wiki/Betweenness_centrality"&gt;betweenness centrality&lt;/a&gt;.&amp;rdquo; I didn&amp;rsquo;t realize it was a known thing until a mathematician &lt;a href="https://math.stackexchange.com/questions/3162226/is-counting-the-frequency-a-vertex-appears-in-paths-between-all-vertexes-a-valid/3162286"&gt;responded to my question on the Math Stack Exchange&lt;/a&gt; to tell me that I had re-invented an algorithm. Yay!&lt;/p&gt;
&lt;p&gt;Here, then, are the five &amp;ldquo;most central&amp;rdquo; Gadgetopia posts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/what-makes-content-management-system/"&gt;What Makes a Content Management System&lt;/a&gt;: June 2007&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/content-publishing-models/"&gt;Content Publishing Models&lt;/a&gt;: June 2006&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/content-tree/"&gt;The Content Tree&lt;/a&gt;: August 2005&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/four-disciplines-of-content-management/"&gt;The Four Disciplines of Content Management&lt;/a&gt;: November 2007&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/middle-ground-content-management-using-static-html/"&gt;Middle Ground: Content Management using Static HTML&lt;/a&gt;: November 2005&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those are all very foundational posts. I wrote them all well over a decade ago, linked to them often in the years immediately after, and linked to posts &lt;em&gt;that linked to them&lt;/em&gt; in the many years since.&lt;/p&gt;
&lt;p&gt;Clearly, centrality is deeply affected by age, since the passing of time makes it more likely that a post will appear in a &amp;ldquo;link chain&amp;rdquo;…but that&amp;rsquo;s not wrong. This is a measure of how central something is, and age is naturally going to affect that.&lt;/p&gt;
&lt;p&gt;So, centrality has value. Looking at the list of posts from most central downwards, it absolutely correlates with high-value posts which meet my goals.&lt;/p&gt;
&lt;h2&gt;Rule: Keywords&lt;/h2&gt;
&lt;p&gt;The gold standard of a rule would be for it to understand what a post is about, and make a recommendation based on that.&lt;/p&gt;
&lt;p&gt;But this is an inherent human-powered concept (-ish; don&amp;rsquo;t @ me about AI and ML…). And remember that the inability to scale human evaluation is why we&amp;rsquo;re talking about rules in the first place.&lt;/p&gt;
&lt;p&gt;The next best option for automated processing is keyword analysis: what specific words/tokens appear together in content that fits a certain profile?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve identified some words that I feel like would signify a valuable post. Here is my first, rough pass at it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CMS
content management
editor
publishing
workflow
approval
scheduling
expiration
vendor
URL
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I started to write my own algorithm to find these words, when I realized was just re-writing a scoring search engine. So I rigged up a script using &lt;a href="https://lucenenet.apache.org/"&gt;Lucene.NET&lt;/a&gt; to index all the posts, then run a big query with all those terms concatenated with an OR operator, and then score the result, with the title of a post boosted to 1.2x.&lt;/p&gt;
&lt;p&gt;Based on the keyword list above (which is subject to change), here are the top posts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/what-makes-content-management-system/"&gt;What Makes a Content Management System&lt;/a&gt;: June 2007; Score: 1.53&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/content-publishing-models/"&gt;Content Publishing Models&lt;/a&gt;: June 2006; Score: 1.09&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/patterns-in-url-redirection-after-cms-migrations/"&gt;Patterns in URL Redirection After CMS Migrations&lt;/a&gt;: August 2016; Score 0.86&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/you-want-collaboration-not-workflow/"&gt;You Want Collaboration, Not Workflow&lt;/a&gt;: June 2014; Score 0.79&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/why-and-how-of-cms-vendor-partnerships/"&gt;The Why and How of CMS Vendor Partnerships&lt;/a&gt;: April 2009; Score: 0.76&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(Hilariously, when I publish this post, it will no-doubt acquire the highest score, since it literally contains a list of every single keyword, perfectly adjacent to each other.)&lt;/p&gt;
&lt;p&gt;This method is &lt;em&gt;very&lt;/em&gt; promising, because I&amp;rsquo;m scanning down the list of the top 100 posts by score, and there&amp;rsquo;s maybe &lt;em&gt;three&lt;/em&gt; posts I don&amp;rsquo;t think I would keep.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s also interesting is that my list of keywords keeps changing as I look through the results. It shows me posts that I absolutely know I plan to keep, and they help jog my memory of other keywords that might reveal other posts. So, this will take some time to evaluate, as I refine my list of words.&lt;/p&gt;
&lt;p&gt;(Yes yes &amp;ndash; this could be automated. I could find a set of posts I &lt;em&gt;know&lt;/em&gt; I will keep, then use &lt;a href="https://en.wikipedia.org/wiki/Vector_space_model"&gt;term vectoring&lt;/a&gt; to find other posts which are similar to them. And, again, don&amp;rsquo;t think I haven&amp;rsquo;t considered the AI/ML options, but I just don&amp;rsquo;t know enough about that field to make any good decisions around it)&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;After sifting through old posts for a week, and slicing and dicing them based on the metrics from above, I keep coming back to David&amp;rsquo;s tag line for &lt;a href="https://chimera.davidhobbsconsulting.com/"&gt;Content Chimera&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Content Exploration and Decision-Making At Scale&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&amp;rsquo;s really what this is: an &lt;em&gt;exploration&lt;/em&gt; of content.&lt;/p&gt;
&lt;p&gt;Rules are less of a final arbitrator, and more a rough tool that helps you explore a repository of content and make preliminary judgments with a relatively high degree of accuracy. I suspect I could select content (1) based purely on rules, or (2) based on pure manual evaluation, and realize that my results are 99% the same.&lt;/p&gt;
&lt;p&gt;Additionally, the definition and development of these rules has forced me to think critically about my content and figure out what particular metric signals that a piece of content is worth keeping. Or at least worth reviewing to determine if I should keep it.&lt;/p&gt;
&lt;p&gt;For me, I&amp;rsquo;m looking mainly for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Longer blog posts…&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;With a good keyword score…&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And some measure of centrality.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What I&amp;rsquo;m going to use my rules for is to &lt;em&gt;rule out content that has none of the above&lt;/em&gt;. Looking at those three metrics, I&amp;rsquo;m pretty sure I can strike out 90% of the site with confidence that I&amp;rsquo;m not removing anything of value. If something is less than, say, 800 words, with a low keyword score and no centrality to speak of, then it&amp;rsquo;s just gonna go.&lt;/p&gt;
&lt;p&gt;Note that I&amp;rsquo;m not going to delete it forever &amp;ndash; I&amp;rsquo;m just going to change the status and return a 410 with my contact information. If I see a lot of 410s for a particular piece of content, I can review on a case-by-case basis to see if I made a mistake.&lt;/p&gt;
&lt;p&gt;As for the remaining 700-800 posts, I&amp;rsquo;ll review link integrity as a second pass, then manually review from there. And as for traffic, I&amp;rsquo;ve decided not to pay attention to it, for reasons I explained above.&lt;/p&gt;
&lt;p&gt;And this gets to the zen of it all &amp;ndash; &lt;/p&gt;
&lt;p&gt;We need to acknowledge that content has goals and a purpose, and that purpose is different for every site and every creator. If you don&amp;rsquo;t know what the goals of your content are, you simply can&amp;rsquo;t make an informed decision about whether or not to keep it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Rules do not take the place of goals,&lt;/em&gt; and that was never their intention (apologies to David for my reaction to his plan in 2009). They only make you more efficient in finding content that fulfills the goals you&amp;rsquo;ve defined.&lt;/p&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;Special thanks to &lt;a href="https://davidhobbsconsulting.com/"&gt;David Hobbs&lt;/a&gt; for his help in writing this post.&lt;/p&gt;

&lt;/blockquote&gt;</description>
      <pubDate>Mon, 1 Apr 2019 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/evaluating-gadgetopia-content/</guid>
    </item>
    <item>
      <title>Problems, Patterns and Why Every CMS Thinks It Knows What You Need</title>
      <link>https://live.deanebarker.net/tech/blog/problems-and-patterns-in-cms/</link>
      <description>&lt;p&gt;Let&amp;rsquo;s start off with a premise &amp;ndash; &lt;/p&gt;
&lt;p&gt;Generally speaking, a CMS is a system to manage content that doesn&amp;rsquo;t exist yet and that it can&amp;rsquo;t know anything about at the time the CMS is designed and built.&lt;/p&gt;
&lt;p&gt;So, &lt;a href="http://episerver.com/"&gt;Episerver&lt;/a&gt; and &lt;a href="http://sitecore.com/"&gt;Sitecore&lt;/a&gt; and &lt;a href="http://drupal.org/"&gt;Drupal&lt;/a&gt; are all &amp;ldquo;solutions in theory,&amp;rdquo; designed and built to manage content and build websites &lt;em&gt;that do not exist at that time&lt;/em&gt;. In their unimplemented, unplanned state, every productized CMS is theoretical. It certainly &lt;em&gt;hopes&lt;/em&gt; that it can manage your content, but it doesn&amp;rsquo;t &lt;em&gt;know&lt;/em&gt; this, because it knows nothing about your content.&lt;/p&gt;
&lt;p&gt;Why am I talking about this?&lt;/p&gt;
&lt;p&gt;Because I&amp;rsquo;ve gone on-record before as opposing the building of custom CMSs for any reason:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/cms-from-scratch/"&gt;Why do too many developers love to build CMS from scratch?&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="/tech/blog/never-fall-for-custom-hosted-cms-ever/"&gt;Never Fall for a Custom, Hosted CMS. Ever.&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And then the other day, I tweeted &lt;a href="https://twitter.com/gadgetopia/status/1106154476568788992"&gt;a screencap of two slides of a deck&lt;/a&gt; I use when teaching &amp;ldquo;Introduction to Content Management&amp;rdquo; in the &lt;a href="https://www.fh-joanneum.at/content-strategie-und-digitale-kommunikation/master/en/programme/"&gt;content strategy program&lt;/a&gt; at &lt;a href="https://www.fh-joanneum.at/en/"&gt;FH Joanneum&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The lecture is on &amp;ldquo;Acquiring a CMS,&amp;rdquo; and it presents the four major models of how one gets a CMS. The fourth model is to &amp;ldquo;Build Your Own,&amp;rdquo; and the next slide just says &amp;ldquo;Don&amp;rsquo;t.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Yes, this is a pithy witticism (&amp;ldquo;Thank you, I&amp;rsquo;ll be here all week, tip your server&amp;rdquo;), but is it universal?  Meaning, are there some situations when you &lt;em&gt;should&lt;/em&gt; build your own CMS? (To be fair, a few slides later I do, in fact, list some reasons when it makes sense.)&lt;/p&gt;
&lt;p&gt;While most of the responses to this tweet were positive, &lt;a href="https://twitter.com/pjczech/status/1106238203860799490"&gt;someone did call me out on it&lt;/a&gt;. Pete Czech from &lt;a href="https://www.npgroup.net/"&gt;NP Group&lt;/a&gt; wrote:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Maybe WCMS but I can point you to a ton of use cases where custom makes sense. Maybe ya need to add some context to this claim…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And I felt badly about this. Because in addition to a &amp;ldquo;pithy witticism,&amp;rdquo; it was also a gross generalization, and I hate those. &lt;a href="https://www.linkedin.com/in/deane/"&gt;My LinkedIn profile&lt;/a&gt; literally reads: &amp;ldquo;I believe there are very few absolutes in this industry,&amp;rdquo; yet there I was tossing one out.&lt;/p&gt;
&lt;p&gt;And Pete isn&amp;rsquo;t wrong. There are use cases where building a custom CMS makes sense. I just think it&amp;rsquo;s exceedingly rare.&lt;/p&gt;
&lt;p&gt;Why? &lt;em&gt;Patterns.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Question: how can &lt;em&gt;any&lt;/em&gt; product fulfill your needs when it doesn&amp;rsquo;t know you? How can a coffee maker know how you want to make coffee?&lt;/p&gt;
&lt;p&gt;Because most everybody makes coffee the same way. Making coffee is a well-known thing &amp;ndash; you heat water and strain it through crushed coffee beans. This general process is so common that products can be created to automate it because a manufacturer can guess with a high degree of accuracy what you want to do. There are patterns to making coffee, and a coffee maker is just a codification of those patterns.&lt;/p&gt;
&lt;p&gt;Usage patterns have a range of variability, of course. People might make coffee a little differently. Maybe you use two scoops of grounds, and I use three. Perhaps you put hot water in the pot, and I start with cold water. But for making coffee, the range of patterns is pretty narrow, and coffee makers can handle this confined variability just fine.&lt;/p&gt;
&lt;p&gt;Sure, some people might like a french press or a pour over (weirdos), but coffee maker manufacturers have just decided that those people are outside the range of the patterns they want to support with their product. They might try to convince those people of the advantages of adapting to the more mainstream pattern (&amp;ldquo;It&amp;rsquo;s so much easier! People won&amp;rsquo;t call you a hipster!&amp;rdquo;), but they&amp;rsquo;ve otherwise accepted that the &amp;ldquo;pattern space&amp;rdquo; their coffee maker encompasses is enough to capture the share of the market they want.&lt;/p&gt;
&lt;p&gt;The management of content falls into patterns too.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Consider &lt;strong&gt;content modeling&lt;/strong&gt;: we generally divide out content into &lt;em&gt;types&lt;/em&gt;, and those types have &lt;em&gt;properties&lt;/em&gt;, and those properties have &lt;em&gt;data types&lt;/em&gt; (ex: our &lt;em&gt;news article&lt;/em&gt; has a &lt;em&gt;publication date&lt;/em&gt; which is a &lt;em&gt;datetime&lt;/em&gt; value).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consider &lt;strong&gt;approvals&lt;/strong&gt;: they&amp;rsquo;re usually always linear, and each step can either be assigned to a single person, or a group of people, one approval from which is enough to move it to the next step (ex: we need the &lt;em&gt;managing editor&lt;/em&gt; to approve this, then &lt;em&gt;one person from Legal&lt;/em&gt;…)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consider &lt;strong&gt;URL management&lt;/strong&gt;: each content object usually has am individual URL segment, which is combined with other segments based on spatial or type context (ex: the full URL of an object is the concatenation of all of its ancestors from the root object towards it)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Patterns are just problems that became so common we developed generally useful methods of solving them, to the point where those methods became accepted by the larger industry &amp;ndash; people got sick of re-solving them, so someone rolled them together into a solution, combined it with solutions to other common problems, then bundled all that up as a commercial product. It&amp;rsquo;s kind of like evolution: some solution worked and got carried forward.&lt;/p&gt;
&lt;p&gt;To be absurdly general: software is just a bundle of solutions to problems that people often have.&lt;/p&gt;
&lt;p&gt;This means that no existing piece of software was created to solve &lt;em&gt;your&lt;/em&gt; problem. How could it? When it was built, the creators didn&amp;rsquo;t know about &lt;em&gt;your&lt;/em&gt; problem. But they knew about problems &lt;em&gt;like&lt;/em&gt; yours, and they&amp;rsquo;re assuming that other people in the future will have the same problems, which is what rolled forward into you having a problem and this software magically solving it.&lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re considering the &amp;ldquo;fit&amp;rdquo; between your problems and existing software, what you&amp;rsquo;re necessarily doing is forming a mental &lt;a href="https://en.wikipedia.org/wiki/Venn_diagram"&gt;Venn diagram&lt;/a&gt; and determining how well the packaged software overlaps with your problem set. There are a few outcomes to this analysis, from positive to negative:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The system solves your exact problem, as produced. Your problem is so common as to be considered a pattern, and it&amp;rsquo;s already been addressed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The system cannot solve your problem as-produced, but it could be modified or configured to solve your problem. This is where extensibility, APIs, and add-ons are helpful. More open, &amp;ldquo;platform-y&amp;rdquo; systems can pivot in various directions to solve more problems. (This is also where pure SaaS systems can be problematic.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The system cannot solve your problem as-produced, but your underlying need is a little flexible, and perhaps you could modify that need a little (ex: through an organizational or process change) and then the system can solve your problem.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The system cannot &lt;em&gt;ever&lt;/em&gt; solve your problem but this doesn&amp;rsquo;t matter because your problem is (a) actually not that relevant, or (b) its relative importance doesn&amp;rsquo;t rise to the level where it should outweigh the other advantages of the system.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The system cannot &lt;em&gt;ever&lt;/em&gt; solve your problem, and your problem is real, relevant, and significant.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;I talked about this more in-depth in another post: &lt;a href="/tech/blog/checking-the-box/"&gt;Checking the Box: How CMS Feature Support Is Not a Binary Question&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;Clearly, what any vendor is trying to avoid is #5. When it comes to your problem, every vendor is going to claim their system already solves it as a pattern (#1) or can solve it with some small and routine tweaks (#2), or that your problem can be solved some other way (#3) or that it&amp;rsquo;s just not a big problem to start with (#4).&lt;/p&gt;
&lt;p&gt;If the vendor is stuck at #5, then they have a strategic decision to make: is this problem a pattern that we expand to solve in the future? Is your pattern common enough that they need to care about it to secure future business?&lt;/p&gt;
&lt;p&gt;The answer to this question changes over time &amp;ndash; lots of patterns that are addressed in the current generation of products started as weird problems that became less weird as potential customers brought them up again and again, often in response to changes in their market and business environment. Being aware of these trends and making decisions about what problems are evolving into patterns is fundamentally what the discipline of &amp;ldquo;&lt;a href="https://en.wikipedia.org/wiki/Product_management"&gt;product management&lt;/a&gt;&amp;rdquo; is all about.&lt;/p&gt;
&lt;p&gt;Other vendors are happy to walk at #5. They say principled things like, &amp;ldquo;We&amp;rsquo;re not trying to make everyone happy&amp;rdquo; and &amp;ldquo;We have a narrow scope,&amp;rdquo; and they just pass on the sale.&lt;/p&gt;
&lt;p&gt;This works, to a point. But, eventually, they might find themselves walking away from too many sales, at which point they&amp;rsquo;ll expand their &amp;ldquo;pattern coverage&amp;rdquo; through new features or though an acquisition (increasingly the latter).&lt;/p&gt;
&lt;p&gt;Which brings me back to a custom CMS. Should you do it?&lt;/p&gt;
&lt;p&gt;My non-flippant answer is this: only if you can demonstrably prove that your usage patterns are so specific that they&amp;rsquo;re not adequately covered by existing products (and, by usage patterns, I also mean non-usage stuff, like budget, licensing, hosting, etc).&lt;/p&gt;
&lt;p&gt;If you walk away from known solutions to patterns, you need to acknowledge that you&amp;rsquo;re losing a lot of accumulated wisdom. An existing CMS is a massive pile of experience with a UI. Most any CMS has evolved around the solving of patterns that came up again and again, to the point where bundling a solution to them was helpful.&lt;/p&gt;
&lt;p&gt;Also worth noting is that, in the world of CMS, the word &amp;ldquo;custom&amp;rdquo; is loaded. There&amp;rsquo;s a spectrum along which a CMS can be custom. How often is something &lt;em&gt;totally&lt;/em&gt; custom, and how often is it a custom solution built around an existing framework? I suspect the latter is far more common.&lt;/p&gt;
&lt;p&gt;For instance, if you have some odd delivery requirements (&amp;ldquo;We want to send content to little projectors strapped to the bellies of mosquitoes!&amp;rdquo;), that doesn&amp;rsquo;t mean you have to re-invent the entire technology stack. Just because one part of your requirements falls outside any known pattern, doesn&amp;rsquo;t mean they all do.&lt;/p&gt;
&lt;p&gt;The content delivered by those projector-laden mosquitoes is still going to have to be managed somewhere, with modeling and workflow requirements that likely fall solidly within the known pattern space. Thus, start with a headless CMS that patterns the things you &lt;em&gt;do&lt;/em&gt; share with the rest of the world, but keeps its nose (proboscis?) out of the things you don&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;(Speaking of headless, patterns are why I think the market for headless CMS will change remarkably as it matures. Right now, people are rolling their own delivery layers. But, eventually, they&amp;rsquo;re going to start writing their own delivery solutions over and over to the point where they think, &amp;ldquo;Hey, I&amp;rsquo;ve done this enough times that I think I know enough to turn this into a product,&amp;rdquo; and thus launch the Website Builder Era of headless CMS. How many times do you solve a problem, before you think, &amp;ldquo;Hey…I&amp;rsquo;ve seen this before. &lt;em&gt;This might be a pattern!&lt;/em&gt;&amp;rdquo;)&lt;/p&gt;
&lt;p&gt;(Don&amp;rsquo;t look now, but the Headless Website Builder Era might already be here: &lt;a href="https://www.netgenlabs.com/What-we-do/Netgen-Layouts"&gt;Netgen Layouts&lt;/a&gt;, &lt;a href="https://contentpepper.com/"&gt;ContentPepper&lt;/a&gt;, and others, I&amp;rsquo;m sure…)&lt;/p&gt;
&lt;p&gt;So, to Pete and anyone else that was annoyed with my absolutist take on custom CMS &amp;ndash; sure, I&amp;rsquo;ll take that criticism.&lt;/p&gt;
&lt;p&gt;I hereby state, for the record, that there are &lt;em&gt;some&lt;/em&gt; situations where custom solutions work, but in those situations: (1) you need to have a real outlier in terms of usage patterns, and (2) you need to understand that the &amp;ldquo;custom&amp;rdquo; parts are likely only going to be where you usage diverts from known patterns, and therefore we have to place the word &amp;ldquo;custom&amp;rdquo; on some kind of spectrum.&lt;/p&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;I showed a draft of this post to Pete, and he responded by writing his own post: &lt;a href="https://www.npgroup.net/blog/making-case-custom-built-cms/"&gt;Making the Case for a Custom-built CMS&lt;/a&gt;. It&amp;rsquo;s a good post, and he has a number of interesting case studies in there. He wraps up with this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I want to reiterate that I know the reasons for a custom CMS are on the fringes. That&amp;rsquo;s the precise reason why it&amp;rsquo;s important to recognize as developers and digital professionals that the custom CMS has a place in our arsenal. The fringes are typically where the fun stuff happens &amp;ndash; I think most developers would agree.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I can&amp;rsquo;t argue with that point.&lt;/p&gt;

&lt;/blockquote&gt;</description>
      <pubDate>Tue, 19 Mar 2019 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/problems-and-patterns-in-cms/</guid>
    </item>
    <item>
      <title>Breaking the Fourth Wall of Content</title>
      <link>https://live.deanebarker.net/tech/blog/breaking-the-fourth-wall-of-content/</link>
      <description>&lt;p&gt;I&amp;rsquo;ve seen every episode of &lt;em&gt;Friends&lt;/em&gt; at least three times. If you haven&amp;rsquo;t seen it &lt;em&gt;(what?!)&lt;/em&gt;, it&amp;rsquo;s a classic &lt;a href="https://en.wikipedia.org/wiki/Multiple-camera_setup"&gt;four-camera sitcom&lt;/a&gt;, where all the sets are open on one side. There&amp;rsquo;s an implied &amp;ldquo;fourth wall&amp;rdquo; that the cameras see &amp;ldquo;through&amp;rdquo; to film the actors on-set.&lt;/p&gt;
&lt;p&gt;Sitcoms have been filmed this way for years, though &lt;a href="https://en.wikipedia.org/wiki/List_of_single-camera_situation_comedies"&gt;single-camera shows&lt;/a&gt; are becoming more common. As far I know, you saw the fourth wall in only one episode of &lt;em&gt;Friends&lt;/em&gt;, &lt;a href="https://twitter.com/gadgetopia/status/936786314082508802"&gt;when Joey and Chandler were trying to break into Monica&amp;rsquo;s secret closet&lt;/a&gt;. It was painted purple.&lt;/p&gt;
&lt;p&gt;(Also common to the four-camera setup: &lt;a href="https://en.wikipedia.org/wiki/Laugh_track"&gt;a laugh track&lt;/a&gt;, which is slowly dying out as well. If your comedy doesn&amp;rsquo;t have a laugh track, it&amp;rsquo;s probably a single camera set-up.)&lt;/p&gt;
&lt;p&gt;The phrase &amp;ldquo;&lt;a href="https://io9.gizmodo.com/a-history-of-meta-storytelling-on-television-1045718169"&gt;breaking the fourth wall&lt;/a&gt;&amp;rdquo; refers to when a show acknowledges that it&amp;rsquo;s, well, a show; when the characters somehow admit that they&amp;rsquo;re actually actors in front of a camera. In doing so, they would &amp;ldquo;break through&amp;rdquo; the fourth wall. They usually do this as a form of meta-comedy, and it can be really smart and funny when it&amp;rsquo;s done well.&lt;/p&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;To my knowledge, this never happened in &lt;em&gt;Friends&lt;/em&gt;. In other shows it was more common and even celebrated &amp;ndash; &lt;em&gt;&lt;a href="https://www.vulture.com/2013/05/arrested-developments-20-meta-moments.html"&gt;Arrested Development&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href="https://www.youtube.com/watch?v=2ieKjVKtOi4"&gt;Moonlighting&lt;/a&gt;&lt;/em&gt; were known for it. More recently, Kevin Spacey&amp;rsquo;s character would often talk directly to the camera in &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/House_of_Cards_(American_TV_series)"&gt;House of Cards&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;Most performance art involves a tacit agreement, sometimes called &lt;a href="https://en.wikipedia.org/wiki/Suspension_of_disbelief"&gt;Suspension of Disbelief&lt;/a&gt;. We &amp;ldquo;agree&amp;rdquo; to believe that two 20-something women lived in this relatively palatial Manhattan apartment along with their quirky-yet-relatable friends. This is the fantasy, and we&amp;rsquo;re not supposed to question it. The fourth wall needs to stay intact or the performance doesn&amp;rsquo;t work.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s the same with theater. The frame in which you behold the stage is known as the &lt;a href="https://en.wikipedia.org/wiki/Proscenium"&gt;proscenium&lt;/a&gt;. All action takes place through this lens. You could, of course, run up on stage and look through the wings and see the costumes and the actors waiting for their cue, but you&amp;rsquo;re not supposed to do this. You&amp;rsquo;re supposed to play by the rules and constrain yourself to the gallery to view a fantasy world where &lt;a href="http://www.slate.com/blogs/browbeat/2015/09/24/hamilton_s_hip_hop_references_all_the_rap_and_r_b_allusions_in_lin_manuel.html"&gt;the founding fathers were black and they broke into hip hop songs all the time&lt;/a&gt;. This is the contract you implicitly agree to.&lt;/p&gt;




&lt;table-of-contents title="Contents" selector="h2, h3, h4"&gt;&lt;/table-of-contents&gt;

&lt;h2&gt;The Fourth Wall of Content&lt;/h2&gt;
&lt;p&gt;What are we supposed to believe about the origins of the content we consume? Are we supposed to believe that this content just exists, suspended in some fantasy world, waiting to be magically cast out to our browsers, all Harry Potter-like? Or are we always aware that there&amp;rsquo;s a more raw, less refined version of the content somewhere else that was transformed into something more palatable for us to consume it?&lt;/p&gt;
&lt;p&gt;Consider a templated page of highly-structured content (e.g. &amp;ndash; an employee profile in a directory). We show this to the world as a single page of HTML, with content and template values inter-mixed so that an uninterrupted string of HTML is produced and appears on our screens as an integrated document. But do we expect our visitors to actually … believe this? Do they actually think someone typed this all manually?&lt;/p&gt;
&lt;p&gt;Or, do we accept that they know there&amp;rsquo;s some structured content &amp;ldquo;back there&amp;rdquo; somewhere? Just like someone in a theater audience knows that the actors break character as soon as they&amp;rsquo;re out of view of the audience, do our visitors know that there&amp;rsquo;s a content type in the background, and that some values on the page are part of that content while others are part of something called a &amp;ldquo;template&amp;rdquo; that gets applied to all content, and that there&amp;rsquo;s a set of rules we made to organize the content in the site? To what extent do our visitors &amp;ldquo;lift the curtain&amp;rdquo; on our content?&lt;/p&gt;
&lt;p&gt;I started word processing back in the early 90s, in college. Back then, Microsoft Word wasn&amp;rsquo;t common &amp;ndash; all the cool kids were using WordPerfect.&lt;/p&gt;
&lt;p&gt;I used the DOS version for a while, then graduated to the Windows version, which was a revelation. The DOS version had to represent different formatting with colors &amp;ndash; something was &amp;ldquo;bright white,&amp;rdquo; for instance when it was bolded. To see what something &lt;em&gt;really&lt;/em&gt; looked like, you needed to go to Print Preview.&lt;/p&gt;
&lt;p&gt;But in Windows, you had this great feature called &amp;ldquo;Reveal Codes.&amp;rdquo; This would show you a little pane at the bottom of your text &lt;em&gt;and the formatting codes&lt;/em&gt;. So you could see &amp;ldquo;bold&amp;rdquo; codes surrounding text which was bolded (a lot like HTML tags, really). This was my first introduction to the concept of markup.&lt;/p&gt;
&lt;p&gt;I loved it. With this, I could peer behind the scenes. I could lift the curtain and see how the sausage was made. Everything was suddenly clear to me, and weird formatting issues suddenly made sense and were easily resolved. I felt like I was seeing the document for what it really was, rather than the homogenized version that was intended for the unenlightened masses. I had a privileged view while &amp;ldquo;they&amp;rdquo; did not &amp;ndash; they merely saw the manufactured result of it; a PDF, or a printed page.&lt;/p&gt;
&lt;p&gt;This dichotomy has never left me, and it&amp;rsquo;s paralleled in the larger content industry: &lt;em&gt;we spent a lot of time trying to hide the things we do from the end user&lt;/em&gt;. We want them to see the result, but not how it happened. We want to maintain some … mystique (?), and there&amp;rsquo;s a strange intimacy to the extent that we reveal to them what we&amp;rsquo;re actually doing, both technically and logically.&lt;/p&gt;
&lt;h2&gt;We&amp;rsquo;re All In This Together&lt;/h2&gt;
&lt;p&gt;Indulge me with this gross generalization, but in a public website scenario, there are two types of people:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Editors&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Visitors&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Editors make the content and are the ones who understand how it&amp;rsquo;s formed: the structure, the organization, the nomenclature. Editors understand the very subtle difference between why a News Article is not a Blog Post, and how putting multiple content objects in the same folder will cause the left navigation to change.&lt;/p&gt;
&lt;p&gt;A visitor just consumes the content. They can&amp;rsquo;t &amp;ldquo;Reveal Codes.&amp;rdquo; They can&amp;rsquo;t see behind the curtain and understand how the content comes together. They can&amp;rsquo;t tell a News Article from a Blog Post, and they have no understanding of the underlying IA that makes it all go. Visitors only understand what we reveal to them. Things that are blatantly obvious to us are hidden from them. They are led to believe that are content sprang magically forth from the ether in a perfectly consumable form.&lt;/p&gt;
&lt;p&gt;To understand this better, let&amp;rsquo;s turn it on its head, by discussing intranets &amp;ndash; the internal, employee-focused information systems used within a company.&lt;/p&gt;
&lt;p&gt;The editor/visitor segregation breaks down a little when some visitors are editors, and editors are also sometimes visitors, and everyone works for the same organization. That organizational co-mingling breaks the dichotomy of &amp;ldquo;us vs them.&amp;rdquo; When the visitors are employees and they know there&amp;rsquo;s a Corporate Comms department, we suddenly drop the pretense that we have to &amp;ldquo;fool&amp;rdquo; them.&lt;/p&gt;
&lt;p&gt;When &lt;a href="/books/"&gt;my first book&lt;/a&gt; came out last year, intranet expert &lt;a href="http://intranetfocus.com/"&gt;Martin White&lt;/a&gt; wrote &lt;a href="http://intranetfocus.com/web-content-management-deane-barker/"&gt;a great review of it&lt;/a&gt;. Martin and I had met a couple of time over the years, and we exchanged some emails about it. Martin said there needed to be a chapter on intranets. What followed was a discussion about whether intranets were &amp;ldquo;web content management&amp;rdquo; in the traditional form.&lt;/p&gt;
&lt;p&gt;I made this case:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;With [SharePoint, and ECM in general], there&amp;rsquo;s very little &amp;ldquo;hidden.&amp;rdquo; With something like Episerver or Drupal, you have an admin/editorial side, and then a public side, and the latter is a very disguised version of the former. Put another way, you have admins/editors, and you have visitors/consumers, and the two are not meant to share the same view.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With SP, intranets, and ECM, you really have differing gradients of the same class: &amp;ldquo;user.&amp;rdquo; You have users only consume, and users that are allowed to also contribute, and users that are allowed edit and create content. The views are largely the same, and vary simply by degrees and permissions.&lt;/p&gt;
&lt;p&gt;For instance, a particular document library in an ECM system might look the roughly same for everyone, some users just have a few more links and options than others. There&amp;rsquo;s little need or desire to &amp;ldquo;project&amp;rdquo; the library as something completely different, visually and functionally. Whereas with a public website, the raw document library would be the administrative view, and it would be viewed by the public through a facade that made it look like something not resembling a document library at all.&lt;/p&gt;
&lt;p&gt;Unlike the traditional theater where the audience sits in the gallery and views the stage through the proscenium, intranets are like theater-in-the-round or &amp;ldquo;participatory theater,&amp;rdquo; where the stage is surrounded, there&amp;rsquo;s little place to hide, and actors come walking in through the aisles among the audience. The audience is &amp;ldquo;in&amp;rdquo; the performance. Other people are doing the acting, but the lines between &amp;ldquo;us&amp;rdquo; and &amp;ldquo;them&amp;rdquo; get blurrier and in some performances, actors come and sit in the audience and maybe even pull us up on stage. When this happens, we&amp;rsquo;re not voyeurs anymore; rather, we become part of the performance.&lt;/p&gt;
&lt;p&gt;With intranets, we often have to be explicitly trained in how our intranet works. Someone will teach us the secrets of what a &amp;ldquo;section&amp;rdquo; is, and they&amp;rsquo;ll give names to things like &amp;ldquo;local navigation.&amp;rdquo; We understand that the content on the intranet isn&amp;rsquo;t magic, it&amp;rsquo;s simply the result of pieces of information interacting with each other through a set of rules. We interact with our intranet every single day, so we begin to reverse-engineer the patterns.&lt;/p&gt;
&lt;p&gt;Just like you start to notice little ticks and details of TV shows you watch over and over, we begin to figure out what&amp;rsquo;s happening behind-the-scenes of websites we&amp;rsquo;re exposed to every day. We learn the rules and dispel the magic &amp;ndash; we slowly break through the fourth wall.&lt;/p&gt;
&lt;h2&gt;Shadows on the Wall&lt;/h2&gt;
&lt;p&gt;The idea of teaching our visitors how things were built seems bizarre. Contemporary usage of a CMS is as a form of &amp;ldquo;projection.&amp;rdquo; We take content and project it into something else, &lt;em&gt;and then try to pretend that the original thing never existed in the first place&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m thinking now of &lt;a href="https://en.wikipedia.org/wiki/Allegory_of_the_Cave"&gt;Plato&amp;rsquo;s Cave&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Plato has Socrates describe a group of people who have lived chained to the wall of a cave all of their lives, facing a blank wall. The people watch shadows projected on the wall from objects passing in front of a fire behind them, and give names to these shadows. The shadows are the prisoners&amp;rsquo; reality. Socrates explains how the philosopher is like a prisoner who is freed from the cave and comes to understand that the shadows on the wall are not reality at all, for he can perceive the true form of reality rather than the manufactured reality that is the shadows seen by the prisoners.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The content that visitors see are really just shadows on the wall.&lt;/p&gt;
&lt;p&gt;But when you need to draw users deeper into content, perhaps it makes sense to reveal the underlying structure a little more?&lt;/p&gt;
&lt;p&gt;For a brochureware site, there&amp;rsquo;s no point &amp;ndash; the user is ephemeral. They will consume, then not return, so any training or indoctrination about the content is wasted. Brochureware is the one-night stand of CMS.&lt;/p&gt;
&lt;p&gt;As mentioned, intranets are the polar opposite, but what about something in the middle &amp;ndash; a reference site, or a content-based web app, where users will return again and again. How do you decide when to enlighten them with IA and content model &amp;ndash; the &amp;ldquo;insider information&amp;rdquo; to help them understand better?&lt;/p&gt;
&lt;p&gt;How could we make the source of the shadows more explicit? Consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Could we have a link in the footer that says &amp;ldquo;Show me the content model of this page.&amp;rdquo; Clicking that link would reveals the raw, untemplated content structure. What would be the point of this? Well, as I said before, it probably matters more as intimacy with the site increases &amp;ndash; for brochureware, no one cares. But for more content-focused sites, there might be value here (consider that Wikipedia essentially lets you do this).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Could we have a &amp;ldquo;Explain this Page&amp;rdquo; link and revealed a bunch of pop-up menus that explain how the page and the site worked? Like, it would label the left nav and explain why those links appear (&amp;ldquo;All these pages are in the same section, entitled &amp;lsquo;About Us&amp;rsquo;.&amp;rdquo;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Do those options seem weird to you? Probably. But why? Why is there some reluctance about letting visitors turn their heads toward the light that casts the shadows?&lt;/p&gt;
&lt;p&gt;Actually, we&amp;rsquo;re at a weird inflection point right now where we&amp;rsquo;re revealing more than ever before. Front-end development and single-page applications (SPA) &amp;ndash; the so-called &amp;ldquo;&lt;a href="https://jamstack.org/"&gt;JAMStack&lt;/a&gt;&amp;rdquo; &amp;ndash; can&amp;rsquo;t really hide what they do. Network calls can be monitored, and JSON isn&amp;rsquo;t hard to read. If you want to reverse engineer how a SPA works, it&amp;rsquo;s all there for you to understand.&lt;/p&gt;
&lt;p&gt;There used to be a clear delineation between client and server, and the server was a &amp;ldquo;magic box&amp;rdquo; from which stuff sprang forth. The stuff was generated on the server from … what? Some more pure data, we assumed. But the visitor didn&amp;rsquo;t really know what happened on the server. They could have no knowledge of what CMS or server architecture was being used, except what they might glean from artifacts in the HTTP headers. HTML was ejected from the server post-transformation.&lt;/p&gt;
&lt;p&gt;But now you can monitor all traffic between your browser and the web server, and some of that traffic might be extremely detailed API calls (see &lt;a href="http://graphql.org/"&gt;GraphQL&lt;/a&gt;), complete with internal labels and names for logical concepts that might be presented to the end user in a completely different context. I realize the data we send might not be our &lt;em&gt;exact&lt;/em&gt; content model, but it&amp;rsquo;s probably a lot closer than the shadows the visitor sees rendered in their browser.&lt;/p&gt;
&lt;p&gt;Monitoring network traffic might be like running up on stage and peering into the wings. You&amp;rsquo;re seeing the backstage of the production &amp;ndash; breaking the fantasy contract &amp;ndash; and you might be shocked to find out the same dude plays four different parts in the background.&lt;/p&gt;
&lt;h2&gt;Us vs Them&lt;/h2&gt;
&lt;p&gt;The web as it stands today has grown up with an idea of an &amp;ldquo;us vs. them&amp;rdquo; mentality. The traditional paradigm has been one of a thin-client talking to the mothership. Strange things happened inside the mothership &amp;ndash; both logically and technically &amp;ndash; and we weren&amp;rsquo;t privy to them. We didn&amp;rsquo;t know how the content was generated, and to some extent, we didn&amp;rsquo;t know how it was organized. In fact, the goal was for a generation and organization process so unknowable that content just seemed to magically appear out of the ether.&lt;/p&gt;
&lt;p&gt;This has inculcated us to the idea that visitors should be ignorant of the wizard behind the curtain. But is that limiting? I think the answer depends on your particular website and use case, but I can easily imagine situations where letting users understand your core definitions and architecture of content &amp;ndash; not just your templated end product &amp;ndash; might be the exact right thing to do.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m tempted to end this with some specific advice, but I can&amp;rsquo;t get behind anything in particular.&lt;/p&gt;
&lt;p&gt;However, I just can&amp;rsquo;t shake the idea of &amp;ldquo;projection&amp;rdquo; in CMS, and how the very idea of content created for an audience is deeply imbued with the idea of &amp;ldquo;them&amp;rdquo; and &amp;ldquo;us.&amp;rdquo; &lt;em&gt;We&lt;/em&gt; (us) create, manage, transform, and deliver. &lt;em&gt;They&lt;/em&gt; consume.&lt;/p&gt;
&lt;p&gt;As a mildly prolific content creator for more than a decade, I can tell you that &amp;ldquo;their&amp;rdquo; role is much shorter and simpler than ours, and I suppose that&amp;rsquo;s the basis of performance art in general. Actors rehearse and rehearse for a performance we consume in a couple of hours.&lt;/p&gt;
&lt;p&gt;I think the basis of performance art &amp;ndash; and of content &amp;ndash; is that we hold our cards close to the vest, by design. We attempt to curate an image of spontaneous, miraculous conception. Our joy is in the visitor not even conceiving that it took work to deliver the end result. We try to be effortless and unseen, like shadows projected on a wall to an audience that never turns their heads.&lt;/p&gt;</description>
      <pubDate>Wed, 27 Feb 2019 00:00:00 -0600</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/breaking-the-fourth-wall-of-content/</guid>
    </item>
    <item>
      <title>Squirrel Notes: The First Year</title>
      <link>https://live.deanebarker.net/tech/blog/squirrel-notes-the-first-year/</link>
      <description>&lt;p&gt;I just sent the last Squirrel Notes of 2018 &amp;ndash; Issue #20 &amp;ndash; which concludes the first full year.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re not familiar with &lt;a href="/squirrel-notes/"&gt;Squirrel Notes&lt;/a&gt;, it&amp;rsquo;s an email newsletter about content management that I publish about twice a month. Each issue has five &amp;ldquo;notes,&amp;rdquo; which are just random things of interest that I&amp;rsquo;ve picked up from the world of CMS.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a little self-examination about why I started this, and where it&amp;rsquo;s going.&lt;/p&gt;




&lt;table-of-contents title="Contents" selector="h2, h3, h4"&gt;&lt;/table-of-contents&gt;

&lt;h2&gt;The Reasons&lt;/h2&gt;
&lt;p&gt;An email newsletter seems like such a step backwards. But there were a few things that struck me last year &amp;ndash; &lt;/p&gt;
&lt;p&gt;I subscribed to a newsletter called &lt;a href="http://recomendo.com/"&gt;Recommendo&lt;/a&gt;, which is nothing more than six personal recommendations and tips from a group of editors. It&amp;rsquo;s quirky, and idiosyncratic, and it directly represents nothing more than the genuine opinions of actual humans. I love getting the newsletter &amp;ndash; meaning, &lt;em&gt;I literally smile&lt;/em&gt; when I see it in my inbox. I wanted to do something that would (hopefully, fingers crossed) give someone else that same feeling.&lt;/p&gt;
&lt;p&gt;Just as much as Recommendo, I love the car videos of Doug DeMuro. He has &lt;a href="https://www.youtube.com/channel/UCsqjHFMB_JYTaEnf_vmTNqg"&gt;a YouTube channel&lt;/a&gt; with millions of subscribers, and he reviews cars &amp;ndash; new cars, old cars, all cars. His videos are about 25 minutes, and they&amp;rsquo;re not…corporate. When Doug reviews a car, he concentrates on what he calls the &amp;ldquo;quirks and features&amp;rdquo; of the car (he says that so much, in fact, there&amp;rsquo;s actually &lt;a href="https://shortshift.co/the-doug-demuro-drinking-game/"&gt;a drinking game&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;One day, while watching a video, I realized this is what I identified with &amp;ndash; the weirdness, the intricacy, and the specific oddness of what sets one car apart from another. Doug makes car content for weird car people, not normal people. He talks about random, odd things that only occur to people who &lt;em&gt;really&lt;/em&gt; love cars, and I started wondering if I could capture this same vibe for people who love CMS.&lt;/p&gt;
&lt;p&gt;(I think the word for this is &amp;ldquo;&lt;a href="https://www.dictionary.com/browse/wonk"&gt;wonk&lt;/a&gt;.&amp;rdquo;  A wonk is someone who geeks out on the esoteric, intricacies of stuff, sometimes with little practical application. &lt;a href="https://www.sarawb.com/"&gt;Sara Wachter-Boettcher&lt;/a&gt; once called me a &amp;ldquo;CMS wonk&amp;rdquo; at a conference in Helsinki.  I&amp;rsquo;ll own that.)&lt;/p&gt;
&lt;p&gt;Also this year, I was traveling a lot and talking to a lot of people about CMS. I love it when two people who enjoy CMS start rambling about it, and topics just start falling from the sky. This person knows that person, and this system is going in that direction, and this trend is about to become the Next Big Thing. There&amp;rsquo;s so much information that just drifts by, and I wanted some way to call it out for people who are as weirdly interested in it as me.&lt;/p&gt;
&lt;p&gt;So, I had started taking notes on random tidbits I picked up on the road (read: &amp;ldquo;notes&amp;rdquo;), and then this collided with my aforementioned love for Recommendo, and…&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t know at what exact point I took the actual plunge, but &lt;a href="https://twitter.com/gadgetopia/status/950450963898339330"&gt;this tweet&lt;/a&gt; is from January 8th.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have this urge to create a monthly email newsletter about CMS. I have no idea why I want to do this so much.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I put together a trial issue and then ended up writing another 5-6 in advance. I was actually sitting in a CMS selection process next to &lt;a href="https://karenmcgrane.com/"&gt;Karen McGrane&lt;/a&gt; in NYC, and during breaks, I would send her test emails of various issues. She encouraged me to forge ahead with it.&lt;/p&gt;
&lt;p&gt;The only name I ever considered was Squirrel Notes. My book has a squirrel, and I was emailing my notes, so….well, there you go. The entire idea is literally &lt;em&gt;notes&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I announced my planned newsletter in &lt;a href="https://twitter.com/gadgetopia/status/951771258013802503"&gt;a tweet on January 12th&lt;/a&gt;, and I got about 100 subscribers in 48 hours. I sent &lt;a href="/squirrel-notes/001/"&gt;Issue #1&lt;/a&gt; on January 18th, and off we went.&lt;/p&gt;
&lt;h2&gt;The List&lt;/h2&gt;
&lt;p&gt;I made a couple decisions up-front.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I wouldn&amp;rsquo;t ask for any information other than email. I have no plans to market to the list, so I didn&amp;rsquo;t need any other demographics &amp;ndash; hell, I&amp;rsquo;m just happy you&amp;rsquo;re here. An email address often reveals identity and employer, but subscribers are otherwise anonymous.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I would try to grow the list slowly and organically. I don&amp;rsquo;t want anyone on the list that doesn&amp;rsquo;t &lt;em&gt;really&lt;/em&gt; want to be on it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As of this writing, the list is just over 300 subscribers. And I&amp;rsquo;m proud that only about 5% of people who have ever subscribed have unsubscribed. So, only about one person in 20 thinks, &amp;ldquo;Nah, I don&amp;rsquo;t want to read this after all.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;(That math, BTW,  is: &lt;code&gt;total unsubscribers / current subscribers + total unsubscribers&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t done any marketing outside of some Twitter posts and a LinkedIn post or two. All the growth has been word of mouth. I&amp;rsquo;m hesitant to do a big marketing push because I don&amp;rsquo;t want someone to subscribe who isn&amp;rsquo;t genuinely interested. Also, the newsletter doesn&amp;rsquo;t really have much of a commercial point to it. I&amp;rsquo;m sure there&amp;rsquo;s some incidentally marketing benefit to me and &lt;a href="http://blendinteractive.com/"&gt;Blend&lt;/a&gt;, but that&amp;rsquo;s nothing you can calculate the ROI of a marketing campaign around.&lt;/p&gt;
&lt;p&gt;(That said, if you want to mention Squirrel Notes to other people you think would be interested, please do.)&lt;/p&gt;
&lt;p&gt;To let people know what they&amp;rsquo;d be getting, I have &lt;a href="/squirrel-notes/"&gt;a public archive of most all issues&lt;/a&gt;. I hold the latest two back (otherwise, why would you subscribe?), but at any given time, you can see any other issues. I&amp;rsquo;d rather a potential subscriber look through some issues and make an educated decision to subscribe, rather than subscribe blindly, get an issue or two, and decide it&amp;rsquo;s not what they wanted.&lt;/p&gt;
&lt;p&gt;(This just happened the other day. A guy subscribed, got one issue, then unsubscribed, which sadly inflates the stat I mentioned above. This annoys me.)&lt;/p&gt;
&lt;p&gt;My feeling is this: there are only X number of people in the world that would be interested in this over the long term. What is that number? 500? 1,000? It&amp;rsquo;s certainly not much &amp;ndash; of the emails I recognize, I can tell you that the list is basically consultants and vendors; so &amp;ldquo;industry insiders,&amp;rdquo; to some extent (&amp;ldquo;wonks&amp;rdquo;!). That&amp;rsquo;s a fairly small group, and I don&amp;rsquo;t think a contrived, artificial list of 20,000 vaguely interested people is going to do me much good.&lt;/p&gt;
&lt;p&gt;I monitor bounces carefully. Curiously, it tells me a bit about comings and goings in the industry. I see a bounce which strikes me as odd because I recognize the email, and then I&amp;rsquo;ll see a notification that the person has switched jobs.&lt;/p&gt;
&lt;p&gt;Also, it&amp;rsquo;s very gratifying to see that person resubscribe under their new email or their personal email account, which tells me that they want to make sure they keep receiving the newsletter (in that case, I &lt;em&gt;delete&lt;/em&gt; their old email from the list, so it&amp;rsquo;s not technically an unsubscribe).&lt;/p&gt;
&lt;p&gt;I sweat the open rate. MailChimp tracks how many people open the email (as best it can, given privacy settings). The list currently has an open rate of over 50%, which is very good, and there&amp;rsquo;s likely another 30% of people who prevent their email clients from registering the open (and this is likely even more common among my tech-savvy subscriber base). I&amp;rsquo;m reasonably confident that 80% or 90% of subscribers read each issue.&lt;/p&gt;
&lt;p&gt;If the open rate were to drop precipitously, then I&amp;rsquo;d have to give serious thought about whether to continue, for this simple reason: if it&amp;rsquo;s not a thing someone wants to see in their inbox, what&amp;rsquo;s the point?&lt;/p&gt;
&lt;h2&gt;The Content&lt;/h2&gt;
&lt;p&gt;Every issue after the first two has five notes. Those first couple had six, because I had no plan and I was just throwing in all sorts of stuff. I quickly settled on five as the standard.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m pretty ruthless about word counts. Very few issues will have over 600 words. A college-educated adult can read about 350 words per minute, and skim much faster. My goal is to make Notes a two-minute read at most. If an issue is &amp;ldquo;heavy,&amp;rdquo; I will trim pretty ruthlessly &amp;ndash; delete entire paragraphs, remove wordy clauses, or just nip and tuck everywhere.&lt;/p&gt;
&lt;p&gt;I saturate each Note with links. My goal is for you to click &lt;em&gt;something&lt;/em&gt; &amp;ndash; I want you to see something interesting and investigate it. My mission is basically to write teasers to get you interested in other content. I want to &amp;ldquo;incite exploration,&amp;rdquo; to put a dramatic phrase on it.&lt;/p&gt;
&lt;p&gt;I stay pretty close to CMS, but I edge into content technology in general. Really, I&amp;rsquo;m interested in anything related to CMS that would broaden the perspective of somebody who works with this software for a living.&lt;/p&gt;
&lt;p&gt;I used to put the content in categories &amp;ndash; things like &amp;ldquo;theory,&amp;rdquo; &amp;ldquo;events,&amp;rdquo; etc. When I was sending her test issues, Karen told me to dump the categories as they didn&amp;rsquo;t matter. But I was smitten with them, so they stayed…only to get dumped a few issues in, when they got tedious. She was right &amp;ndash; you can categorize them in your own head; you don&amp;rsquo;t need me to tell you where they fit in.&lt;/p&gt;
&lt;p&gt;Also, I used to show teasers at the bottom &amp;ndash; &amp;ldquo;In the next issue of Notes…&amp;rdquo; I did this because I often had the next issue partially written as the current issue was being sent…but not always. It got to be a bit of a pain, and I was often thrashing the next issue together just to have the previews. So, I&amp;rsquo;ve dropped this for now. It might come back.&lt;/p&gt;
&lt;p&gt;I try to get one issue out every two weeks, but not always, and I&amp;rsquo;m okay with that. For Notes to have longevity, it needs to not be stressful. So if I&amp;rsquo;m busy on a given week, I just wait until the next week. I decided early on that I wasn&amp;rsquo;t going to stress about it. I know you&amp;rsquo;re not staring at your inbox waiting for Notes to arrive, and a self-imposed schedule was just going to make me resent it.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve never put any effort into the timing of delivery days or times. I send it whenever it gets done. If it&amp;rsquo;s outside working hours in North America, I might schedule it for the next morning, but I&amp;rsquo;m all over the map here.&lt;/p&gt;
&lt;h2&gt;The Process&lt;/h2&gt;
&lt;p&gt;I wrote &lt;a href="https://www.amazon.com/_/dp/1491908122"&gt;a book on CMS&lt;/a&gt;, so you know the technical process behind each issue of Notes is stone-cold dialed in to the best possible industry practices. Woot! Woot!&lt;/p&gt;
&lt;p&gt;Uh, no.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not even content-managed. I write each issue as a delimited Markdown file. The files are sitting in Dropbox (where they are versioned), in folders by issue number (&amp;ldquo;001&amp;rdquo;, &amp;ldquo;002&amp;rdquo;, etc.). Each folder has a &amp;ldquo;notes.md&amp;rdquo; file, and a &amp;ldquo;header.md&amp;rdquo; and &amp;ldquo;footer.md&amp;rdquo; file if I have anything special for the header and footer of that issue.&lt;/p&gt;
&lt;p&gt;I have a C# script that I run directly out of &lt;a href="https://www.linqpad.net/"&gt;LinqPad&lt;/a&gt; to create the email. All the files are parsed and passed to a &lt;a href="http://dotliquidmarkup.org/"&gt;DotLiquid&lt;/a&gt; template. That template generates HTML which is pushed into &lt;a href="https://mailchimp.com/"&gt;MailChimp&lt;/a&gt; via their API (I have never used the actual MailChimp editor for Notes).&lt;/p&gt;
&lt;p&gt;When MailChimp is updated for the first time (so, when the campaign is created), the script writes an &amp;ldquo;issue.meta&amp;rdquo; file in the same folder which contains the campaign ID (so I can update it in future executions). After the campaign is actually sent, I run the script once again to get the number of emails sent and the date they were sent on, which get written to the same file. This is the the metadata that powers &lt;a href="/squirrel-notes/"&gt;the archive&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The script also generates a flat HTML file for the archive, which is written to a private &amp;ldquo;server&amp;rdquo; (in quotes because it&amp;rsquo;s actually the computer sitting under my desk in my office). The website (which is out on Azure) calls to it for an issue it doesn&amp;rsquo;t have, then holds the issue in cache. When the script runs, the last thing it does is call an endpoint on the server to clear that cache, so any new requests will get re-fetched.&lt;/p&gt;
&lt;p&gt;Therefore, my &amp;ldquo;process&amp;rdquo; is simply this: I write, execute, review, write, execute, review, and so on. It&amp;rsquo;s awfully low-tech, considering what I do for a living.&lt;/p&gt;
&lt;p&gt;But I have no plans to change the process, just the output. I&amp;rsquo;ll always compose the Notes in a Markdown file, but I&amp;rsquo;d like to eventually push them into a hosted repository of some sort, for reasons I&amp;rsquo;ll explain below.&lt;/p&gt;
&lt;p&gt;The technical part of Notes has been really fun. It&amp;rsquo;s low-tech, but it&amp;rsquo;s not hacked up. The code is solid, and I actually haven&amp;rsquo;t touched the script or the template in months. It works beautifully.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also a neat example of doing something &amp;ldquo;exploratorily.&amp;rdquo; I had no idea what I was going to do originally, so I didn&amp;rsquo;t want to put a lot of effort into it. I figured I&amp;rsquo;d screw around and see what happened. I had the following luxuries:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I&amp;rsquo;m the only editor&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I&amp;rsquo;m technical, and comfortable in Markdown&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I could template them myself&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delivery is decoupled &amp;ndash; MailChimp and static HTML are my delivery channels&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When I do finally decide to model them for a repository, I&amp;rsquo;ll be in a great position because I&amp;rsquo;ve been tinkering with the process and format for a year, so it will be nicely established by then.&lt;/p&gt;
&lt;p&gt;Note that I surely wouldn&amp;rsquo;t do any of this for a client, but for a hobby, I&amp;rsquo;m having a blast with it.&lt;/p&gt;
&lt;h2&gt;The Future&lt;/h2&gt;
&lt;p&gt;As I mentioned, one goal is 2019 is to move the individual Notes into a content repository of some kind. Through 20 issues, there&amp;rsquo;s just over 100 of them now (not &lt;em&gt;exactly&lt;/em&gt; 100, because of those pesky six-note issues in the beginning).&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to enhance the archive. Right now, you can scroll through issues, and view a full issue. This list is getting longer, and it&amp;rsquo;s eventually going to have to paginate, which gets weirder with flat files.&lt;/p&gt;
&lt;p&gt;Additionally, I&amp;rsquo;d like to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Give each note it&amp;rsquo;s own permanent URL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the archive searchable&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tag posts, to group them by subject/concept&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be able to link posts back to each other&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That last one is important. This last issue, for example, I made an addendum to a Note from the prior email. I&amp;rsquo;d like to refer to that prior Note, but I need a URL to do it, so they&amp;rsquo;re eventually going to need permalinks.&lt;/p&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;I did eventually archive all issues and notes on this site: &lt;a href="/squirrel-notes/"&gt;Squirrel Notes&lt;/a&gt; (though I still don&amp;rsquo;t run it out of a CMS).&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;Additionally, the tagging would enable me to track &amp;ldquo;conversations&amp;rdquo; that develop over time. I remember this need from my blogging heyday &amp;ndash; I&amp;rsquo;d do multiple posts on the same theme, and I wanted a &amp;ldquo;topic page&amp;rdquo; that recorded that particular conversation.&lt;/p&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;Here&amp;rsquo;s a semi-cringey post about this same idea from 2005: &lt;a href="/tech/blog/coming-soon-guided-content-maps/"&gt;Coming Soon: Guided Content Maps&lt;/a&gt;. I never did do it, though.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;Finally, one other thing I need to do is modify the subject lines. Right now the subject is just &amp;ldquo;Squirrel Notes #20&amp;rdquo; or something. I&amp;rsquo;d like it to still have that standard, but perhaps have a slug from the lead Note to give you an idea what it&amp;rsquo;s about. I hope this would increase open rates, but there&amp;rsquo;s a chance they might get worse (what if the slug isn&amp;rsquo;t something you&amp;rsquo;re interested in?).&lt;/p&gt;
&lt;p&gt;So, that&amp;rsquo;s it. I&amp;rsquo;m one year and 20 issues in, and I hope to continue it for as long as possible. I hope you enjoy seeing it in your inbox every couple of weeks.&lt;/p&gt;</description>
      <pubDate>Thu, 20 Dec 2018 00:00:00 -0600</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/squirrel-notes-the-first-year/</guid>
    </item>
    <item>
      <title>The Technical Basis for Content Experience</title>
      <link>https://live.deanebarker.net/tech/blog/technical-basis-for-content-experience/</link>
      <description>&lt;p&gt;In Jonathan Haidt&amp;rsquo;s 2012 book, &amp;ldquo;&lt;a href="https://www.amazon.com/Righteous-Mind-Divided-Politics-Religion/dp/0307455777"&gt;The Righteous Mind: Why Good People Are Divided by Politics and Religion&lt;/a&gt;,&amp;rdquo; he mentions a study where subjects were shown pictures of a furnished room and asked to describe it.&lt;/p&gt;
&lt;p&gt;Subjects from capitalist countries tended to describe the individual items in the room (&amp;ldquo;there&amp;rsquo;s a couch and a lamp&amp;rdquo;) while subjects from more socialist countries tended to describe the entire room (&amp;ldquo;it&amp;rsquo;s a living room&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;One group of subjects was perceiving the objects. The other group was perceiving the larger whole which emerged from the combination of the objects.&lt;/p&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;I&amp;rsquo;m describing this from memory. I don&amp;rsquo;t doubt I might be a bit off here. I did make a couple attempts to re-find this anecdote to no avail.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;The point was that our concept of the role government should play in our life is deeply rooted in our conception of individuality opposed to the aggregation of people into a community. Or vice-versa, I suppose &amp;ndash; one&amp;rsquo;s experience with government probably influences how we see everything else.&lt;/p&gt;
&lt;p&gt;But, the point remains &amp;ndash; do we perceive objects, or aggregations of objects? And does the appearance of an object with another object change the nature of both?&lt;/p&gt;
&lt;p&gt;I know, this is a bizarre start to a post about CMS, but stick with me &amp;ndash; &lt;/p&gt;
&lt;p&gt;What is that ineffable quality that makes a CMS? We&amp;rsquo;ve been structuring and recording information for millennia. We&amp;rsquo;ve had relational databases for decades. But what is it that makes a data repository a CMS?&lt;/p&gt;
&lt;p&gt;I think &lt;a href="http://flyingsquirrelbook.com/glossary/term/coupling-model"&gt;headless CMS&lt;/a&gt; has forced some soul-searching onto the larger CMS landscape. It&amp;rsquo;s driving a discussion of what a &amp;ldquo;CMS&amp;rdquo; even is. How big is that umbrella, and where is the boundary between what is a CMS and what isn&amp;rsquo;t?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been wrestling with this question for over a decade. See &amp;ldquo;&lt;a href="/tech/blog/what-makes-content-management-system/"&gt;What Makes a Content Management System&lt;/a&gt;&amp;rdquo; from June 2007. In that post, I took a feature-based approach to the question &amp;ndash; what is and isn&amp;rsquo;t a CMS is just a super-set of features above a relational database.&lt;/p&gt;
&lt;p&gt;But, lately, I think it&amp;rsquo;s more subtle than that.&lt;/p&gt;
&lt;p&gt;I think the soul of a CMS lies in its ability to reason about abstractions. A CMS can interpret and respond to an abstracted, intentional request &amp;ndash; don&amp;rsquo;t just give me a specific content object, but rather here is my &lt;em&gt;need&lt;/em&gt;, and respond with the bundle of content structured in such a way that meets that need.&lt;/p&gt;
&lt;p&gt;(I&amp;rsquo;m reminded of my wife, who is a kindergarten teacher. My wife &lt;em&gt;gets&lt;/em&gt; kids like no one else. She understands that a child actually says, of course, but more importantly, she understands what a child &lt;em&gt;doesn&amp;rsquo;t say&lt;/em&gt;. My wife can evaluate a child and understand their &lt;em&gt;need&lt;/em&gt;, which is far above what they can merely articulate in verbal form.)&lt;/p&gt;
&lt;p&gt;I hate to use the word &amp;ldquo;experience,&amp;rdquo; I really do. First, it&amp;rsquo;s hopelessly over-used. Second, it&amp;rsquo;s conflated with specific features. Third, it cracks open the gaping abyss of marketing hyperbole into which we might get sucked for all eternity.&lt;/p&gt;
&lt;p&gt;But it fits.&lt;/p&gt;
&lt;p&gt;Remember that &lt;em&gt;a visitor knows nothing of your content model or objects&lt;/em&gt;. They don&amp;rsquo;t know a Text Page from an Article Page, or what Content Object #234 looks like.&lt;/p&gt;
&lt;p&gt;And the products page of your website is not &lt;em&gt;content&lt;/em&gt;. It&amp;rsquo;s really an experience. It&amp;rsquo;s made up of content, for sure. But the request for it is an intention that needs to be interpreted and formed into a &amp;ldquo;payload&amp;rdquo; of content to provide an effective response.&lt;/p&gt;
&lt;p&gt;Put another way, when a visitor requests &lt;code&gt;/products&lt;/code&gt;, they&amp;rsquo;re not saying &amp;ldquo;Give me Content Object #234.&amp;rdquo; Rather, they&amp;rsquo;re saying, &amp;ldquo;I have a content need. Give me an experience that fulfills it.&amp;rdquo; Visitors don&amp;rsquo;t perceive &lt;em&gt;actual&lt;/em&gt; content; they perceive the &lt;em&gt;experience&lt;/em&gt; of content.&lt;/p&gt;
&lt;p&gt;I gave the developer keynote at &lt;a href="https://symposium.sitecore.com/"&gt;Sitecore Symposium&lt;/a&gt; this past October. In that talk, I set forth a five-layer model for what constitutes a &amp;ldquo;CMS.&amp;rdquo; It looked like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modeling and Aggregation:&lt;/strong&gt; this the ability to describe content, relate it to one other, and organize it into structure that provide value&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Editorial Tools:&lt;/strong&gt; these are the tools that allow editors to work with content &amp;ndash; so, the editorial UI at the most basic level, plus other tools like versioning, workflow, preview, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Response Logic:&lt;/strong&gt; hold this thought &amp;ndash; we&amp;rsquo;ll come back to this below&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Delivery and Presentation:&lt;/strong&gt; the ability to transform raw content into a form suitable for consumption, and inject it into a consumption channel&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimization:&lt;/strong&gt; the ability to impact the performance of content post-publication &amp;ndash; things like personalization, A/B testing, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I grouped the first two layers &amp;ndash; Modeling and Aggregation and Editorial Tools &amp;ndash; under the label of &amp;ldquo;repository services.&amp;rdquo; These two things are needed to provide the ability for editors to work with content. They need some sort of UI to manipulate it, and they need the rules and storage mechanisms to hold onto it.&lt;/p&gt;
&lt;p&gt;These repository services are all that a headless CMS aspires to be, almost universally. In fact, the entire pitch of headless right now seems to be, &amp;ldquo;We do only this thing, and we do it well, so you can fill in the other layers however you see fit.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;At Symposium, I made the case that this makes it tough to even call these systems a &amp;ldquo;CMS.&amp;rdquo; True, that term is applicable in a purely semantic sense: a headless CMS is a &lt;em&gt;system&lt;/em&gt; that allows you to &lt;em&gt;manage&lt;/em&gt; your &lt;em&gt;content&lt;/em&gt;. But, in the years since &amp;ldquo;CMS&amp;rdquo; became a term, it&amp;rsquo;s become a colloquial shorthand for a system that provides all the layers (with #5 being more recent, and more common in the commercial space).&lt;/p&gt;
&lt;p&gt;I argued that a headless CMS should really be called an &amp;ldquo;HCR,&amp;rdquo; or a &amp;ldquo;headless content repository.&amp;rdquo; Honestly, the &amp;ldquo;headless&amp;rdquo; qualifier is perhaps redundant. In their most pure form, these systems are simply content repositories.&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t interpret this as a pejorative term or a value judgment. Content repositories are critical, and they&amp;rsquo;re the technical basis for everything we do with content. A good repository is a wonderful thing.&lt;/p&gt;
&lt;p&gt;But remember, repositories are about &lt;em&gt;content&lt;/em&gt;, not about experiences.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m beginning to think the line of differentiation between repository and CMS is layer #3 from my model above: what I&amp;rsquo;m calling &amp;ldquo;response logic.&amp;rdquo; With a traditional CMS, there&amp;rsquo;s a layer of logic that can interpret intentions and choreograph a response of multiple content objects, organized into a larger structure, to provide an experience.&lt;/p&gt;
&lt;p&gt;Digging deeper, let&amp;rsquo;s take a second to establish a couple precepts &amp;ndash; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First, every CMS responds to requests. At one level a CMS is simply a database. We make a request of it &amp;ndash; either a URL is requested, or an API is invoked &amp;ndash; and the CMS responds by providing content.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Second, requests can be for one of two things: (1) specific content, which is common from an API (&amp;ldquo;give me content ID #234&amp;rdquo;), or (2) some abstracted representation of a &lt;em&gt;payload&lt;/em&gt; of content (&amp;ldquo;I want the URL &lt;code&gt;/products&lt;/code&gt;&amp;rdquo;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Response logic, then, are the rules and processing a CMS uses to respond to a request. We can further sub-divide this logic into two parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transactional response logic,&lt;/strong&gt; which simply manages the transactional details of providing a piece of content&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Abstraction response logic,&lt;/strong&gt; which interprets request abstraction and determines what specific content should fulfill it&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For a specific content object (ID #234, in our example), transactional response logic performs these steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access Control Checking:&lt;/strong&gt; is this security context allowed to view this content?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Publication Status Checking:&lt;/strong&gt; is this content assigned a state that allows viewing?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Version Selection:&lt;/strong&gt; which version of this content is the published version?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Variation Selection:&lt;/strong&gt; is this content being personalized or multivariate tested, and, if so, what combination of variations should be presented?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is where headless systems really stop. Headless CMS requires you to manually identify or query content, much like SQL against a database, so that&amp;rsquo;s what they do.&lt;/p&gt;
&lt;p&gt;But that isn&amp;rsquo;t the interesting part.&lt;/p&gt;
&lt;p&gt;Abstraction logic can interpret a non-specific content request (&lt;code&gt;/products&lt;/code&gt;, in our example), and do this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Abstraction mapping:&lt;/strong&gt; in WCM, the abstraction &amp;ldquo;name&amp;rdquo; would be a URL, so the CMS has to map the URL to a specific content object in the repository. Generally, speaking abstractions link to specific content objects, but that object might be nothing more than a query that aggregates more content (a view from &lt;a href="https://www.drupal.org/project/views"&gt;Drupal Views&lt;/a&gt;, for example)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Contextual content association:&lt;/strong&gt; the CMS needs to then gather all the content of the response payload, and it needs to run all the transactional rules on each&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So when someone requests &lt;code&gt;/products&lt;/code&gt;, our CMS has to figure out what content represents that view (likely a &amp;ldquo;Text Page&amp;rdquo; called &amp;ldquo;Products&amp;rdquo;), then determine everything else that needs to be rendered with it: content to form the menus, crumbtrails, header media, related content, etc.&lt;/p&gt;
&lt;p&gt;All this content together is the &amp;ldquo;response payload.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;And this is where we cross the line into what I would call a &amp;ldquo;CMS&amp;rdquo;: something that has the ability to respond to abstracted content requests. It has a layer of knowledge of just what needs to happen when someone wants &lt;code&gt;/products&lt;/code&gt;, or when they&amp;rsquo;re looking at the home screen of your app, or all the content necessary to fully-render your white paper into a PDF.&lt;/p&gt;
&lt;p&gt;A traditional CMS has always played the role of ringleader &amp;ndash; it was the dispatcher that translated the intention of abstraction requests into the actual content required to fulfill it. A system that exchanged intention for experience.&lt;/p&gt;
&lt;p&gt;With a content channel based on a headless system, where is this response abstraction logic? As we&amp;rsquo;ve established, it&amp;rsquo;s not in the repository. It&amp;rsquo;s either baked directly into the delivery layer, or it&amp;rsquo;s something between the delivery layer and the repository.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You might have URL queries embedded in PHP code that directly executes on request&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You might have a .NET framework that maps abstractions to backend queries via a BFF&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You might have a React component that makes queries for specific objects to form an aggregated display&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Something, somewhere, has to choreograph a response payload. Regardless of where you put this or how you codify the rules, &lt;em&gt;this is response logic&lt;/em&gt;. A traditional CMS has it built-in, while the current slate of headless CMS requires you to bring it with you.&lt;/p&gt;
&lt;p&gt;This tacit ability for a CMS to choreograph an intentional request into a coordinated response of content is, in some senses, the &amp;ldquo;soul&amp;rdquo; of a CMS. It&amp;rsquo;s the thing that makes a CMS more than just a database. It&amp;rsquo;s what makes a CMS a CMS.&lt;/p&gt;
&lt;p&gt;An interesting aspect of response logic that we can use to speculate on the future of headless is that &lt;em&gt;response logic embraces convention&lt;/em&gt;. Indeed, response logic &lt;em&gt;is&lt;/em&gt; convention. It&amp;rsquo;s some larger framework for converting a request abstract into a response payload.&lt;/p&gt;
&lt;p&gt;I promise that if you build response logic enough times, you&amp;rsquo;ll come up with common rules and practices for mapping request abstractions into content payloads. You&amp;rsquo;ll do the same things over and over again until patterns emerge. You&amp;rsquo;ll eventually codify those patterns, and before you know it, you&amp;rsquo;ll have developed a response logic layer.&lt;/p&gt;
&lt;p&gt;And this is what I think we&amp;rsquo;ll see in the headless space: commoditized response logic. Someone, somewhere, will come up with a framework to add response logic to a particular headless CMS. They&amp;rsquo;ll package this into a system and sell it or release it to open-source. Then, that headless CMS will have some new remote API abstraction &amp;ldquo;on top&amp;rdquo; of their existing API. The abstraction API will take some shorthand request (like &lt;code&gt;/products&lt;/code&gt;), translate it to all the calls required to form the response payload, then assemble it and send it back.&lt;/p&gt;
&lt;p&gt;So, you won&amp;rsquo;t build stuff directly with &lt;a href="http://contentful.com/"&gt;Contentful&lt;/a&gt; or &lt;a href="https://kenticocloud.com/"&gt;Kentico Cloud&lt;/a&gt;. You&amp;rsquo;ll build something with &amp;ldquo;The Headless Whizbang Experience Manager 5000&amp;rdquo;, and some headless repository will be abstracted behind it. (And just watch &amp;ndash; they&amp;rsquo;ll be interchangeable, so you can use Whizbang with a plethora of backing repositories.)&lt;/p&gt;
&lt;p&gt;(This could most easily happen with some MVC framework. Even now, an MVC framework is a form of response logic &amp;ndash; it converts an inbound request abstraction into executable code. Someone, very soon, will release some code that maps models in an MVC framework to content objects in a headless content repository.)&lt;/p&gt;
&lt;p&gt;Could headless systems build response logic in? Well, yes, of course, but their marketing message has always been a rejection of it, so they&amp;rsquo;ll likely leave it to other software (or build it themselves as a separate product).&lt;/p&gt;
&lt;p&gt;But the easiest way do start down this road is to allow URL rewriting/aliasing on the inbound request.&lt;/p&gt;
&lt;p&gt;I mean, wouldn&amp;rsquo;t it be handy if we could alias this…&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://headless-cms.com/my-account/recent-posts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Into this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://headless-cms.com/
my-account/
items/
?select=id,title,summary
&amp;amp;type=blog-post
&amp;amp;sortby=date
&amp;amp;sortdirection=desc
&amp;amp;limit=3
&amp;amp;auth=[key]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Even something as simple as that moves us from content to experience. The former is an intention (&amp;ldquo;tell me what&amp;rsquo;s new in your world&amp;rdquo;), the response to which constitutes an experience. The latter is simply the mechanics that gets us there.&lt;/p&gt;
&lt;p&gt;Abstractions like this would be helpful to centralize logic. If you have your app installed on 10,000 devices and one day you decide you want to show the top &lt;em&gt;four&lt;/em&gt; blog posts instead of the top three, wouldn&amp;rsquo;t it be handy to be able to change the backing querystring for the &lt;code&gt;/recent_posts&lt;/code&gt; URL? Wouldn&amp;rsquo;t it be nice to have some cushy layer of configurable logic rather than just fielding raw queries all day?&lt;/p&gt;
&lt;p&gt;(What? You already do this via a BFF or proxy? Well congratulations, you just wrote some response logic.)&lt;/p&gt;
&lt;p&gt;The pitch of headless always fixates on templating and rendering. &amp;ldquo;You can use React!&amp;rdquo; or &amp;ldquo;Angular!&amp;rdquo; or whatever else! It&amp;rsquo;s as if the last mile of concatenating a string of HTML is the single biggest problem we have to solve.&lt;/p&gt;
&lt;p&gt;It isn&amp;rsquo;t. Templating is actually the easy part.&lt;/p&gt;
&lt;p&gt;Rather, I think that the headless CMS category has been defined by an explicit rejection of response logic, and, by extension, a rejection of experience in favor of raw content.&lt;/p&gt;
&lt;p&gt;The current spate of headless systems are trying to be super-content-databases that just respond to raw queries without any regard to the experience that a choreographed response is meant to represent. You need to bring your own experience manager.&lt;/p&gt;
&lt;p&gt;And, to be fair, this is the point. They&amp;rsquo;re not ignorant of experience, they just trust you to handle it yourself.&lt;/p&gt;
&lt;p&gt;But at some point, &lt;em&gt;I think we&amp;rsquo;re gonna miss this&lt;/em&gt;. We&amp;rsquo;re going to find ourselves re-implementing it enough that we realize there are patterns there, and how can we develop some commoditization around it?&lt;/p&gt;
&lt;p&gt;And this might be the next step for headless: how do we allow our customers to develop response logic at the repository level? How do we move headless systems from just managing content and responding to requests, and rather start managing an experience of content at the perceptual level?&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;ll be interesting to see if they go in this direction.&lt;/p&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;After this post was written, Kentico released &lt;a href="https://webspotlight.kontent.ai/"&gt;Web Spotlight&lt;/a&gt; which is a web content management system built on top of their &lt;a href="https://kontent.ai/"&gt;Kentico Kontent&lt;/a&gt; headless product.&lt;/p&gt;

&lt;/blockquote&gt;</description>
      <pubDate>Fri, 16 Nov 2018 00:00:00 -0600</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/technical-basis-for-content-experience/</guid>
    </item>
    <item>
      <title>Points of Differentiation in Headless CMS</title>
      <link>https://live.deanebarker.net/tech/blog/points-of-differentiation-in-headless-cms/</link>
      <description>&lt;p&gt;When was the last time a project failed on selection of the database server?&lt;/p&gt;
&lt;p&gt;Have you ever heard, &amp;ldquo;This project would have worked if we had used Postgres rather than MySQL.&amp;rdquo; Or SQL Server rather than Firebird. Etc.&lt;/p&gt;
&lt;p&gt;You don&amp;rsquo;t hear this because we just don&amp;rsquo;t expect much from database servers. They have a wide range of functionality, but what do we use?  Tables, columns, keys, and maybe stored procs or views? (Truth: I don&amp;rsquo;t remember the last time I wrote a stored proc. I&amp;rsquo;ve actually written &lt;a href="/tech/blog/why-i-hate-stored-procedures-manifesto/"&gt;a manifesto against them&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;When was the last time you used a feature of a database server that isn&amp;rsquo;t available in a competing product? Not something that&amp;rsquo;s just done differently, but a feature that &lt;em&gt;literally doesn&amp;rsquo;t exist&lt;/em&gt; in anything other than the database server you selected for your project?&lt;/p&gt;
&lt;p&gt;The way we use them, database servers are largely fungible, which means:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Something that is exchangeable or substitutable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Assuming we can connect, we can usually swap one for another. This is why &lt;a href="https://en.wikipedia.org/wiki/Database_abstraction_layer"&gt;database abstraction layers&lt;/a&gt; exist.&lt;/p&gt;
&lt;p&gt;Our usage patterns of database servers are very narrow. We just don&amp;rsquo;t ask a lot from them, generally. If you&amp;rsquo;re a Windows developer, you&amp;rsquo;re probably always gonna use SQL Server because it&amp;rsquo;s just fine, and you wouldn&amp;rsquo;t think to question that.&lt;/p&gt;
&lt;p&gt;When usage patterns are narrow, software is easily substituted. As usage patterns get wider &amp;ndash; as you start doing more interesting, varied, and complex things with the software &amp;ndash; it gets harder to substitute because you start to wiggle your way into places that only a subset of the products support.&lt;/p&gt;
&lt;p&gt;Now, consider headless CMS.&lt;/p&gt;
&lt;p&gt;Right now, the usage patterns for headless are narrow. These products are still young, so mostly they&amp;rsquo;re being used for remote management and access to a structured repository of content…full stop. If you can model your content, manage it, and access it over REST, you&amp;rsquo;re good. We&amp;rsquo;re just not asking for much right now.&lt;/p&gt;
&lt;p&gt;This is one of the selling points of headless: don&amp;rsquo;t buy a bunch of stuff you don&amp;rsquo;t need. Indeed, this was the original point. The value prop &amp;ndash; implicitly or explicitly &amp;ndash; is, &amp;ldquo;We&amp;rsquo;re stripped down to the core essentials.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Given this, how are headless vendors competing? How are the individual vendors setting themselves apart from each other to avoid fungibility?  How are they proclaiming &amp;ldquo;This is the thing we offer that no one else does that will help with your project!&amp;rdquo;&lt;/p&gt;
&lt;p&gt;In short: why should a customer pick one headless CMS over another?&lt;/p&gt;
&lt;p&gt;Here are some thoughts.&lt;/p&gt;




&lt;table-of-contents title="Contents" selector="h2, h3, h4"&gt;&lt;/table-of-contents&gt;

&lt;h2&gt;Content Modeling&lt;/h2&gt;
&lt;p&gt;The most basic thing a CMS needs to do is to allow you to accurately represent a logical domain of content in a structured, reusable, and manageable way. This means creating content types, properties, and relationships to describe what your content is and how it should be managed.&lt;/p&gt;
&lt;p&gt;There are three sub-disciplines here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Discrete Modeling:&lt;/strong&gt; This is describing a content object unto itself, meaning the properties that are specific to that content object and wholly contained with it. &amp;ldquo;Title,&amp;rdquo; for example.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Relational Modeling:&lt;/strong&gt; This is describing how a content object relates to other content objects. For instance, our &amp;ldquo;Article&amp;rdquo; type should have a property called &amp;ldquo;Author&amp;rdquo; which is actually a link over to a separate content object of the &amp;ldquo;Author&amp;rdquo; type (trivia: I stumbled on the phrase &amp;ldquo;relational content modeling&amp;rdquo; &lt;a href="/tech/blog/discrete-vs-relational-content-modeling/"&gt;12 years ago&lt;/a&gt;.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Organizational Modeling:&lt;/strong&gt; This is the grouping of content into aggregations (I&amp;rsquo;ve called these &amp;ldquo;&lt;a href="/tech/blog/content-assembly/"&gt;assemblies&lt;/a&gt;&amp;rdquo; in the past). A content tree is a core type of content organization (which I&amp;rsquo;ve called &amp;ldquo;&lt;a href="/tech/blog/content-geography/"&gt;geographies&lt;/a&gt;&amp;rdquo; in the past). So are things like categories, taxonomies, lists, and menus. Given sufficiently advanced relational modeling, you can usually rig up organizational models (you can create a content type for &amp;ldquo;Taxonomy Term,&amp;rdquo; for example), but some systems have specific subsystems for common organizational schemes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most headless systems are doing well on the first two items here &amp;ndash; discrete and relational modeling. You can create different content types, and specify reference properties to link them together.&lt;/p&gt;
&lt;p&gt;However, there&amp;rsquo;s still a dearth of organizational modeling. Some systems have categorization and tagging, but it&amp;rsquo;s sporadic.  I do know of one vendor with a fabulously visual graph database, where every entity is related to every other entity &amp;ndash; and &lt;em&gt;everything&lt;/em&gt; in the installation is an entity, from the folder the content lives in, the editor who created it, each individual tag assigned to it, etc.&lt;/p&gt;
&lt;p&gt;Weirdly, content trees are conspicuously absent. &amp;ldquo;That&amp;rsquo;s web-centric,&amp;rdquo; one vendor told me &amp;ndash; a point with which I &lt;em&gt;strenuously&lt;/em&gt; disagree. I feel like parent-child relationships are a natural way to model all sorts of content, but the tide of headless vendors is clearly against me on this.&lt;/p&gt;
&lt;h2&gt;UI Usability&lt;/h2&gt;
&lt;p&gt;The editorial UI is what editors interact with to create content. This includes the interfaces they navigate through, as well the the editing widgets themselves. Some of this piggy backs on the content model, since widget selection very much depends on the underlying datatype of the property (a date-picker for &amp;ldquo;Published Date&amp;rdquo;, for example).&lt;/p&gt;
&lt;p&gt;Headless systems benefit greatly from a coincident of their timing &amp;ndash; they were born into the Era of the Big Client. Most all headless systems have come into being after mature JavaScript frameworks have taken over page rendering.&lt;/p&gt;
&lt;p&gt;And, since they allow remote access to content, many editorial UIs are simply Single Page Applications (SPAs) making REST calls using the same querying API available to their customers. Indeed, a headless CMS that used more traditional HTML via server-side rendering would seem highly out of place.&lt;/p&gt;
&lt;p&gt;And, given their age and purposefully-limited featureset, headless vendors don&amp;rsquo;t have legacy UI elements to support, and their interfaces tend to be very clean and content-centered (indeed, what else is there to do?).&lt;/p&gt;
&lt;h2&gt;Editorial Tools&lt;/h2&gt;
&lt;p&gt;These are the tools that editors use to actually manage content, apart from the actual UI. Things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://flyingsquirrelbook.com/glossary/term/workflow"&gt;Workflow&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://flyingsquirrelbook.com/glossary/term/approval"&gt;Approvals&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://flyingsquirrelbook.com/glossary/term/permission"&gt;Permissions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://flyingsquirrelbook.com/glossary/term/preview"&gt;Preview&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://flyingsquirrelbook.com/glossary/term/versioning"&gt;Versioning&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://flyingsquirrelbook.com/glossary/term/version-control"&gt;Version Control&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://flyingsquirrelbook.com/glossary/term/publication"&gt;Publication Labels&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://flyingsquirrelbook.com/glossary/term/archival"&gt;Archival&lt;/a&gt; (&lt;a href="/tech/blog/archiving-in-cms/"&gt;ill-defined&lt;/a&gt; as that is)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;Shameless plug: all terms linked to entries in &lt;a href="http://flyingsquirrelbook.com/glossary"&gt;the web content management glossary&lt;/a&gt;.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;These are the…boring (?) tools that editors use to get content created, edited, managed, published, unpublished, archived, and deleted. These tools are unglamorous, but necessary.&lt;/p&gt;
&lt;p&gt;While grouped under what I&amp;rsquo;d call &amp;ldquo;repository services,&amp;rdquo; these tools are often the last in line to get developed. In many cases, their absence just doesn&amp;rsquo;t stick out enough during demos, because few vendors proactively demo them (how exciting is it to watch something get archived?), and many users take them for granted so they don&amp;rsquo;t think to ask for them (&amp;ldquo;Of course it allows for approvals! What CMS wouldn&amp;rsquo;t…?&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;These are tools that get developed later in a CMS&amp;rsquo;s lifetime, when the user base has gotten large enough that enough customers are asking for them. In a new market, when vendors are scrambling to show of exciting, highly-visible stuff, these tools fall through the cracks.&lt;/p&gt;
&lt;h2&gt;Performance Scalability&lt;/h2&gt;
&lt;p&gt;A big selling point in headless is its ability to serve a massive throughput of data &amp;ndash; so-called &amp;ldquo;hard&amp;rdquo; scalability, or raw requests-per-second. Most headless systems do this by publishing into a Content Delivery Network (CDN). So, when you request content from your headless CMS, you&amp;rsquo;re actually requesting content from Cloudfront or Fastly or something.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;cache-ability&amp;rdquo; of your content will differ greatly depending on architecture and level of personalization. Additionally, you can implement your own caching schemes &amp;ndash; my book website, for example, has made just six requests to its headless CMS in the last 15 days, as it caches everything at the web server (not a typo: &lt;em&gt;six&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;But there are situations &amp;ndash; mobile, for instance, when you might literally have millions of clients in people&amp;rsquo;s pockets, each making live requests all the time &amp;ndash; you need massive scalability.&lt;/p&gt;
&lt;h2&gt;Dev Ops Integration and Scalability&lt;/h2&gt;
&lt;p&gt;The headless market is still decidedly developer-centric. As such, many headless systems are building deep integration into dev ops tools.&lt;/p&gt;
&lt;p&gt;For instance, having to create your content model from a UI is not something a developer usually wants to see. They want to define a content model in a file (I&amp;rsquo;ve said before that files are &amp;ldquo;&lt;a href="/tech/blog/files-are-the-currency-of-web-development/"&gt;the currency of web development&lt;/a&gt;&amp;rdquo;), check it into source control, and have content model changes happen directly from a branch. Additionally, they want to be able to clone environments, change their models, and generate diff files to propagate to other environments. They want to be able to manage everything from a command line, and have hooks to continuous integration platforms, unit testing suites, and other deployment workflows.&lt;/p&gt;
&lt;p&gt;For some developers, even logging into the UI would be considered a failure. They want to manage their headless CMS like just another one of the hundreds of database instances they have in their organization. They want it to bend to their process, not the other way around.&lt;/p&gt;
&lt;p&gt;Many headless vendors are seeking to become &amp;ldquo;content infrastructure.&amp;rdquo; The last thing a vendor wants is to become a speed bump to a development shop&amp;rsquo;s process. The goal is to fade into the background like the network itself &amp;ndash; something you don&amp;rsquo;t think about much, but you always know is there and that you&amp;rsquo;d be helpless without it.&lt;/p&gt;
&lt;h2&gt;Remote Event Hooks&lt;/h2&gt;
&lt;p&gt;Headless CMSs are built around their APIs, so the ability to manipulate content remotely is just table stakes. But what&amp;rsquo;s trickier is event-based programming. Since you can&amp;rsquo;t program inside a SaaS CMS, when something changes inside the repository, it&amp;rsquo;s often necessary to notify an external process.&lt;/p&gt;
&lt;p&gt;Example: above I mentioned how my book site caches all the content in the web server process, and those rarely ever talks to its headless CMS. However, when something &lt;em&gt;does&lt;/em&gt; change, my headless CMS calls a URL on the site and tells it to clear the cache. On the next inbound request, the site retrieves the updated content.&lt;/p&gt;
&lt;p&gt;This is commonly called a &amp;ldquo;webhook&amp;rdquo; (15 years ago, I came &lt;em&gt;thisclose&lt;/em&gt; to &lt;a href="/tech/blog/extending-movable-type-using-pinged-script/"&gt;naming them&lt;/a&gt;…). There have been &lt;a href="http://www.webhooks.org/"&gt;attempts at standards&lt;/a&gt; around this, but, to my knowledge, it&amp;rsquo;s a wide-open space. Some systems just send an empty HTTP request, while others will actually POST the changed content. Some allow for authentication, some allow for customization of the HTTP request (custom headers and such), etc.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to add other integration hooks here, but I&amp;rsquo;m not sure there are many. Since you can&amp;rsquo;t code logic into a SaaS-based CMS, and the core &lt;a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete"&gt;CRUD&lt;/a&gt; API is a given…what else is there? Webhooks are the main conduit by which these systems communicate with the outside world about events occurring within the system.&lt;/p&gt;
&lt;h2&gt;SDKs, Code, and Query Language Support&lt;/h2&gt;
&lt;p&gt;Every headless CMS offers some form of remote access and querying, so every headless CMS can &amp;ldquo;fall back&amp;rdquo; to &lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer"&gt;REST&lt;/a&gt; over HTTP, usually delivering JSON.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;existence&lt;/em&gt; of the ability to search the repository via URL-based queries is clearly binary and required, but the actual capabilities are on a spectrum. Most systems offer full-text support, but there are vagaries in the querying models that might make a difference (for example: are relational properties two-way? Given an Article, you can get the Author, but given an Author, can you find all their Articles?).&lt;/p&gt;
&lt;p&gt;Some particular subsystem architectures, protocols, and standards are desirable for specific developers and scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Authentication schemes like &lt;a href="https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language"&gt;SAML&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/OAuth"&gt;OAuth&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Query languages like &lt;a href="https://en.wikipedia.org/wiki/GraphQL"&gt;GraphQL&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security protocols and standards like SOC 1/2, &lt;a href="https://en.wikipedia.org/wiki/Payment_Card_Industry_Data_Security_Standard"&gt;PCI DSS,&lt;/a&gt; or &lt;a href="https://www.dhs.gov/fisma"&gt;FISMA&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Privacy protocols like &lt;a href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation"&gt;GDPR&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, some systems have abstraction libraries for specific languages (Software Development Kits, or SDKs), so you can get pre-built code that &amp;ldquo;wires up&amp;rdquo; some of the backend stuff and makes querying easier.&lt;/p&gt;
&lt;h2&gt;Delivery Channel Features&lt;/h2&gt;
&lt;p&gt;This one might seem weird, because the rejection of &amp;ldquo;channel awareness&amp;rdquo; is &lt;em&gt;de rigueur&lt;/em&gt; in headless &amp;ndash; &amp;ldquo;We manage content, not pages!&amp;rdquo; The whole idea is that they don&amp;rsquo;t do &lt;em&gt;anything&lt;/em&gt; in the delivery channel.&lt;/p&gt;
&lt;p&gt;However, some vendors are making concessions to common channels &amp;ndash; particularly the web &amp;ndash; and offering specific features for them. (In fact, I like that name for this phenomenon: &amp;ldquo;Channel Concessions,&amp;rdquo; which means, &amp;ldquo;We&amp;rsquo;re headless, but we &lt;em&gt;concede&lt;/em&gt; that we can do something to help this specific channel, so we&amp;rsquo;re going to do that.&amp;rdquo;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Some vendors have JavaScript libraries that give &amp;ldquo;click to edit&amp;rdquo; functionality in HTML&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;At least one vendor is offering a &amp;ldquo;landing page builder&amp;rdquo; to allow for the spatial organization of content on a page surface&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some vendors have preview functionality which will load specific preview URLs in the editorial interface, which allows HTML-based preview&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One vendor has a &amp;ldquo;Synchronization API,&amp;rdquo; which allows you to make a query with a date, and effectively say &amp;ldquo;Give me all the content that has changed since this date.&amp;rdquo; This is particularly helpful for mobile, when you might need to refresh a local content repository.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I&amp;rsquo;ve seen analytics usage tracking, where a channel can callback to the repository to register the view of a piece of content. While this is channel agnostic, the most obvious usage would be web tracking.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s going to be interesting to see where this goes. I feel we&amp;rsquo;re going to increasingly see vendors offering features for specific channels, either in the core or in packaged add-ons that we might implement or &amp;ldquo;activate&amp;rdquo; for a project involving that channel. Like those I&amp;rsquo;ve detailed above, we&amp;rsquo;ll see tools that only make sense in the web channel, or the mobile channel, or whatever.&lt;/p&gt;
&lt;p&gt;Taking this to an extreme conclusion, we might find vendors eventually offering full-blown &amp;ldquo;website builders&amp;rdquo; that allow all the same tools as a traditional, coupled CMS…just using their headless system as a repository. At that point, they&amp;rsquo;ll have basically created an entirely separate product.&lt;/p&gt;
&lt;p&gt;(Watch some of the traditional vendors that are starting to offer separate headless functionality &amp;ndash; &lt;a href="https://www.dnnsoftware.com/products/evoq-content"&gt;Evoq&lt;/a&gt;, &lt;a href="http://kentico.com/"&gt;Kentico&lt;/a&gt;, etc. One day, they may just swap in their headless system as the backend repository for their core CMS, and won&amp;rsquo;t that be interesting?)&lt;/p&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;After this post was written, Kentico released &lt;a href="https://webspotlight.kontent.ai/"&gt;Web Spotlight&lt;/a&gt; which is a web content management system built on top of their &lt;a href="https://kontent.ai/"&gt;Kentico Kontent&lt;/a&gt; headless product. (Confusingly, they also still have their &lt;a href="https://www.kentico.com/"&gt;existing DXP product&lt;/a&gt;.)&lt;/p&gt;

&lt;/blockquote&gt;

&lt;h2&gt;Pricing and Licensing Models&lt;/h2&gt;
&lt;p&gt;While this criteria is true for any CMS (any software package at all, really), it has some uniqueness around headless CMS, for two reasons &amp;ndash; &lt;/p&gt;
&lt;p&gt;First, the headless market is dominated by &lt;a href="http://flyingsquirrelbook.com/glossary/term/subscription-model"&gt;SaaS&lt;/a&gt; models. There&amp;rsquo;s probably no genre of content software more specific to a SaaS licensing model than headless. Almost all systems are subscription, and pricing varies significantly.&lt;/p&gt;
&lt;p&gt;Additionally, the &lt;em&gt;axes&lt;/em&gt; on which subscription pricing turns are vastly different. Some systems charge by users, some don&amp;rsquo;t. Others allow a certain volume of content, others are unlimited. Almost all have some limitations around API requests, but some differentiate between retrieval requests serviced by the CDN and requests that query the repository (uncached requests, or update/create/delete requests).&lt;/p&gt;
&lt;p&gt;Second, despite the dominance of SaaS, some headless systems can be on-premise. There are a few open-source options, and some commercial systems allow for on-premise installations. While the overwhelming majority of customers simply subscribe, some organizations demand a on-premise system. If so, the list of available options pares down very quickly.&lt;/p&gt;
&lt;h2&gt;Vendor Reputation and Stability&lt;/h2&gt;
&lt;p&gt;Like the prior section, this is true of any CMS selection, but it takes on added significance with headless because the market is so young and is tilted towards SaaS, which means the barrier to entry is low.&lt;/p&gt;
&lt;p&gt;Right now, new headless CMSs are entering the market every single month. I&amp;rsquo;ve tried to keep up, but there&amp;rsquo;s just no way to stay on top of all the new releases.&lt;/p&gt;
&lt;p&gt;This is due to the fact that a headless CMS is easier to build than a traditional CMS, because large parts of the traditional CMS featureset have been omitted. There&amp;rsquo;s no need for templating or response logic, no need for advanced editorial tools (at least to start), and many systems are basically just glorified database management systems (you heard it here first: &lt;a href="https://www.phpmyadmin.net/"&gt;phpMyAdmin&lt;/a&gt; was the first headless CMS…)&lt;/p&gt;
&lt;p&gt;Additionally, since most systems are SaaS and grid computing architectures are so easy to scale, it&amp;rsquo;s just not that hard for someone to create a new system, call it a &amp;ldquo;headless CMS&amp;rdquo; and release it onto the market.&lt;/p&gt;
&lt;p&gt;As a buyer, separating the wheat from the chaff can be tough. How do you know if this is a company that&amp;rsquo;s going to stick around, or if it&amp;rsquo;s just two guys in a basement somewhere? If the latter, there&amp;rsquo;s always a chance they&amp;rsquo;ll be the next Apple, but the odds are long and your content hangs in the balance.&lt;/p&gt;
&lt;h2&gt;Vendor Signaling&lt;/h2&gt;
&lt;p&gt;Like any other software segment, headless vendors &amp;ldquo;signal&amp;rdquo; the type of customer they&amp;rsquo;re interested in via technical architectures and pricing/licensing models.&lt;/p&gt;
&lt;p&gt;There are several headless vendors, for example, that have significant ramp-up time and technical hoops you need to jump through to get them productive.  This is in service of larger goals like scalability, performance, security, and stability, but for a single-person front-end dev shop, this is overkill.&lt;/p&gt;
&lt;p&gt;For smaller use cases, there are vendors that signal in the opposite direction, promising simplicity, speed, and reduced ramp-up type, presumably at the sacrifice of industrial strength attributes unnecessary for that type of project. They assume a simpler project, are designed to provide the bare minimum of features and stay out of the way as much as possible.&lt;/p&gt;
&lt;p&gt;Documentation matters too. I just spoke to a customer who preferred one vendor over another because &amp;ldquo;their documentation was focused on editors, while [the other vendor&amp;rsquo;s documentation] was focused on developers.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve mentioned that headless is very developer-centric, but some more so than others. Many offer free accounts and API sandboxes to get you moving quickly. On the other side, one vendor requires you to load their command line tools via &lt;a href="https://en.wikipedia.org/wiki/Npm_(software)"&gt;npm&lt;/a&gt; just to create a trial account, because their system has no multi-tenant UI &amp;ndash; it&amp;rsquo;s managed mainly from the command prompt. (Once you&amp;rsquo;ve done that, you can run your own UI, also installed via npm and run in your local Node.js environment.)&lt;/p&gt;
&lt;p&gt;In short, headless vendors have a &amp;ldquo;tone.&amp;rdquo; You can label the two ends of the scale as &amp;ldquo;industrial&amp;rdquo; and &amp;ldquo;friendly,&amp;rdquo; or targeted to developers or editors. Pretty much every customer intuitively knows what end of that scale they gravitate toward, whether they explicitly acknowledge it or not.&lt;/p&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t doubt that I missed some categories above. But if an omission sticks out for you, understand that it might be because there&amp;rsquo;s little difference between that aspect of headless and the same thing on the coupled side.&lt;/p&gt;
&lt;p&gt;Community and ecosystem is a good example. Trust me, I know this is important &amp;ndash; &lt;a href="/tech/blog/an-oft-overlooked-cms-feature-the-community/"&gt;I wrote at length about it, six years ago&lt;/a&gt; &amp;ndash; but I just don&amp;rsquo;t think this is much different for headless than for any other type of CMS.&lt;/p&gt;
&lt;p&gt;Clearly, the range of features for a headless CMS is more narrow than for a traditional, coupled CMS &amp;ndash; by design. This means that a headless CMS has that much less room to maneuver against their competition.&lt;/p&gt;
&lt;p&gt;A headless CMS can&amp;rsquo;t really trot out a bunch of delivery-channel marketing features which is where most other CMS segments are competing these days. &lt;a href="http://episerver.com"&gt;Episerver&lt;/a&gt; and &lt;a href="http://sitecore.com/"&gt;Sitecore&lt;/a&gt;, for example, aren&amp;rsquo;t launching any marketing campaigns around their content modeling.&lt;/p&gt;
&lt;p&gt;Right now it doesn&amp;rsquo;t feel like there&amp;rsquo;s a dramatic, expansive featureset where a vendor can spread their wings, redefine the segment, and put considerable distance between themselves and the competition. To some extent, headless vendors are locked in a knife fight inside a phone booth.&lt;/p&gt;
&lt;p&gt;Years ago, I made &lt;a href="http://archive.gadgetopia.com/post/248"&gt;a series&lt;/a&gt; &lt;a href="http://archive.gadgetopia.com/post/5419"&gt;of posts&lt;/a&gt; &lt;a href="http://archive.gadgetopia.com/post/4011"&gt;about WS_FTP&lt;/a&gt;, which was a very mature FTP client. They kept pushing it out the door with new features, year after year. Some were interesting (automatic image thumbnailing), and others were ridiculous (custom skins). But what choice did they have? The only way to keep selling is to release new versions with new features (&lt;a href="https://www.joelonsoftware.com/2006/12/09/simplicity/"&gt;ask Joel Splosky about this&lt;/a&gt;), so they kept pushing functionality into the product.&lt;/p&gt;
&lt;p&gt;But FTP will only do so much, and FTP clients are highly fungible. So, despite all their efforts, features, and bloat, WS_FTP was still pretty much like any other FTP client.&lt;/p&gt;
&lt;p&gt;Now, I know that the headless market still has a lot of room to grow, but eventually headless vendors will reach feature parity on lots of stuff. Is there much new ground to break in content modeling, for instance? When that happens, then what?&lt;/p&gt;
&lt;p&gt;So, my question is this: what&amp;rsquo;s the &amp;ldquo;&lt;a href="https://en.wikipedia.org/wiki/Killer_application"&gt;killer app&lt;/a&gt;&amp;rdquo; of headless CMS?  What is the thing that a particular vendor might obtain or introduce that would set them apart from everyone else, while still allowing them to fit into the standard definition of a headless CMS? Can you imagine what that thing might be? Into what realm will a vendor &amp;ldquo;spill over&amp;rdquo; into when features become too similar?&lt;/p&gt;
&lt;p&gt;I can&amp;rsquo;t think of anything, but this is why they pay product managers. One of them is going to get trapped against the glass ceiling of the segment, and they&amp;rsquo;re going break through it. I look forward to seeing what they come up with.&lt;/p&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;Thanks to several headless vendors who discussed this post with me. Note that they didn&amp;rsquo;t necessarily agree with the core premise of reduced differentiation, but they were gracious enough to review and provide feedback nonetheless: &lt;a href="http://contentful.com/"&gt;Contentful&lt;/a&gt;, &lt;a href="https://buttercms.com/"&gt;ButterCMS&lt;/a&gt;, &lt;a href="https://kenticocloud.com/"&gt;Kentico Cloud&lt;/a&gt;, &lt;a href="https://www.cloudcms.com/"&gt;Cloud CMS&lt;/a&gt;, and &lt;a href="https://www.contentstack.com/"&gt;Contentstack&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And thanks to &lt;a href="https://www.bailie.com/"&gt;Rahel Bailie&lt;/a&gt; for asking me the questions that prompted me to write all this down.&lt;/p&gt;

&lt;/blockquote&gt;</description>
      <pubDate>Tue, 16 Oct 2018 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/points-of-differentiation-in-headless-cms/</guid>
    </item>
    <item>
      <title>Multi-stage Templating as Progressive Denormalization</title>
      <link>https://live.deanebarker.net/tech/blog/multi-stage-transformation/</link>
      <description>&lt;p&gt;One of the perennial rallying cries of content management has always been that &amp;ldquo;content is separate from presentation.&amp;rdquo; We store content in a raw, pure form then when it comes out, we muck it all up with templating. This is the standard paradigm.&lt;/p&gt;
&lt;p&gt;But is all templating equal?&lt;/p&gt;
&lt;p&gt;We usually think of templating as the final step to create HTML out of content. In our heads, content makes the jump from &amp;ldquo;raw&amp;rdquo; to &amp;ldquo;presentation&amp;rdquo; in one step &amp;ndash; it&amp;rsquo;s raw content then…&lt;em&gt;BOOM&lt;/em&gt;…it becomes presentation-ready content in the blink of an eye.&lt;/p&gt;
&lt;p&gt;But perhaps we need to expand this definition to include a layer of &amp;ldquo;transformation&amp;rdquo; at the repository level? Furthermore, maybe we need to look at the journey from raw to presentation as a series of progressive denormalization.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m borrowing the word &amp;ldquo;transformation&amp;rdquo; from XSLT. That technology was intended to turn XML &lt;em&gt;into other XML formats&lt;/em&gt; to use for different purposes (or, more commonly, &lt;a href="https://en.wikipedia.org/wiki/XML_pipeline"&gt;as part of a pipeline&lt;/a&gt;). Since no one reads raw XML, the assumption was that the XML would eventually get &amp;ldquo;templated&amp;rdquo; into a consumable form. (Of course, then we all started &amp;ldquo;transforming&amp;rdquo; XML directly into XHTML, which wasn&amp;rsquo;t the original plan, but whatever…)&lt;/p&gt;
&lt;p&gt;Transformation might start earlier in the process than you think, and it ends up looking like a pipeline &amp;ndash; content is thrown down the pipe and refined until it finally comes out the other end. From another perspective, templating might resemble a tree where content starts at the top, gets subdivided into multiple other formats, which are then further templated into end-user consumable formats.&lt;/p&gt;
&lt;p&gt;We tend to take this for granted, but the surge of headless CMS systems has suddenly thrown this back into play, especially &amp;ndash; and sometimes only &amp;ndash; when we start pushing to multiple channels. Without any ability to transform at the repository, developers are having to write their own templating layers, which often means duplicate templating code and logic in multiple consuming channels.&lt;/p&gt;
&lt;p&gt;Frustratingly, most headless vendors refuse to concede to transformation closer to the repository. Multi-stage refinement &amp;ndash; early-stage transformation, then later-stage templating &amp;ndash; is not well-supported in the current crop of headless CMS.&lt;/p&gt;
&lt;p&gt;Herein, I&amp;rsquo;ll make the case of why this needs to change.&lt;/p&gt;




&lt;table-of-contents title="Contents" selector="h2, h3, h4"&gt;&lt;/table-of-contents&gt;

&lt;h2&gt;Content Transformation as a Drivetrain&lt;/h2&gt;
&lt;p&gt;The drivetrain of a car is complicated as does a lot of stuff. Let&amp;rsquo;s consider the engine as the raw content stored in the repository, and the point where the tires touch the pavement is the final step in presentation to our audience.&lt;/p&gt;
&lt;p&gt;The relationship of the power that comes off the engine and the rotational force applied to the ground through the tires is complicated and takes a lot of work to sort out.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You can&amp;rsquo;t hook the wheels directly up to the crankshaft of the engine. The engine has to constantly turn, and if the wheels were connected directly, they&amp;rsquo;d have to turn around about 500 times per minute at idle. To fix this, we have clutches and torque converters to disconnect the engine so it can run while the car isn&amp;rsquo;t moving.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In many cases, the crankshaft of the engine is a single rotational device turning on a north-south axis, while there are (at least) two drive wheels turning east-west. This is why we have differentials &amp;ndash; they&amp;rsquo;re a series of gears with let the power of the engine turn 90-degrees and split into two outputs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Engines can rev from 500 rpm to sometimes 10,000 rpm, but they make peak power in a more narrow range called the &amp;ldquo;powerband.&amp;rdquo; Thus, we have transmissions which match the speed of the car to the powerband, so the engine stays as efficient as possible.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is even a simplified analysis &amp;ndash; we didn&amp;rsquo;t even talk about flywheels, transfer cases, driveshafts, and wheel bearings. A lot of stuff has to happen to get a single horsepower at the crankshaft to do anything productive at the wheels. Remember, in its pure form, an internal combustion engine makes pretty useless power. It has to keep running, it only turns one way, and it gets irritated when you try to put load on it outside a particular RPM range. So the drivetrain of an engine is a mechanical pipeline that &amp;ldquo;fixes&amp;rdquo; a series of problems along the way, and what comes out at the end &amp;ndash; tire on pavement &amp;ndash; is useful power.&lt;/p&gt;
&lt;p&gt;Is your content the same way? Is the raw content stored in your CMS of the same value as the content that ends up in the hands of the consumer?&lt;/p&gt;
&lt;p&gt;What the drivetrain of the car is designed to do &amp;ndash; much like transformation and templating &amp;ndash; is &lt;em&gt;progressively refine&lt;/em&gt; (there&amp;rsquo;s that phrase again) the power of the engine until it&amp;rsquo;s an appropriate form to be applied to the pavement through the tires.&lt;/p&gt;
&lt;p&gt;And here&amp;rsquo;s the point to remember: there&amp;rsquo;s &lt;em&gt;one&lt;/em&gt; drivetrain that powers all the wheels. Each wheel doesn&amp;rsquo;t have its own transmission. We&amp;rsquo;ll come back to this in a second.&lt;/p&gt;
&lt;p&gt;A CMS needs the ability to transform content prior to delivery to a consuming application where it will be further templated. This means transforming content as close to the &amp;ldquo;engine&amp;rdquo; (the repository) as possible so that all &amp;ldquo;tires&amp;rdquo; (consuming channels) benefit from it. This is in opposition to delivering nothing but raw content and expecting the consuming channels to bear all of the templating workload.&lt;/p&gt;
&lt;p&gt;The problem with leaving all templating to the consuming channels is two-fold:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Latency:&lt;/strong&gt; some transformation is complex and involves considerable computational power and perhaps external resources. Doing this on every read can be painful.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiple channels/platforms/languages:&lt;/strong&gt; if we&amp;rsquo;re pushing this content into multiple channels, there&amp;rsquo;s some basic transformation that we simply don&amp;rsquo;t want to repeat in every channel.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Put another way, having content in its raw form might be less than helpful (remember our useless raw horsepower). Here are some real-life examples:&lt;/p&gt;
&lt;h2&gt;Example: Domain Specific Languages (DSL)&lt;/h2&gt;
&lt;p&gt;A health system had 900 clinics, each of which had to maintain their hours online. This meant storing open and close times for seven days of the week, and occasionally there was a clinic that was open for separate time periods in the same day &amp;ndash; for example, from 8 a.m. to noon, then again from 2 p.m. to 5 p.m.&lt;/p&gt;
&lt;p&gt;This was a painful interface to model. At a minimum, you&amp;rsquo;re looking at 14 different properties (open and close times for seven days of the week), or more when you consider the odd exceptions. Additionally, it was tedious. Time selectors generally suck, and editors were faced with 14 of them. It wasn&amp;rsquo;t pretty.&lt;/p&gt;
&lt;p&gt;So what we did was allow (and train) editors on a simple domain-specific language, like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;M-F: 8-5
Sa: 8-noon
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;M: 8-noon, 2-5
T-Th: 8-5
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;*: 8-3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We wrote a parser to turn this into a strongly typed object, which could then be turned into JSON or XML (and subsequently cached). The logic to do this parsing was complex and took considerable debugging to work out. Additionally, it wasn&amp;rsquo;t computationally cheap. But it worked &lt;em&gt;beautifully&lt;/em&gt;, and with about five minutes of training, it made perfect sense to the editors.&lt;/p&gt;
&lt;p&gt;(For a more common example, consider &lt;a href="https://en.wikipedia.org/wiki/Markdown"&gt;Markdown&lt;/a&gt;, That&amp;rsquo;s a perfect example of a DSL designed to simplify the generation of HTML.)&lt;/p&gt;
&lt;h2&gt;Example: Markup Macros&lt;/h2&gt;
&lt;p&gt;In many CMSs, editors can insert &amp;ldquo;macros&amp;rdquo; in rich text. These are text shortcuts which &amp;ldquo;expand&amp;rdquo; to larger text constructs &amp;ndash; usually HTML, but they could theoretically be anything.&lt;/p&gt;
&lt;p&gt;For example, &lt;a href="http://flyingsquirrelbook.com/"&gt;the site for my book&lt;/a&gt; has a &lt;a href="http://flyingsquirrelbook.com/glossary"&gt;glossary&lt;/a&gt; with wiki-like links between pages. This is what they look like in the editor (from the entry for &amp;ldquo;&lt;a href="http://flyingsquirrelbook.com/glossary/term/version-control"&gt;version control&lt;/a&gt;&amp;rdquo;):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{%{
A version label is a designation applied to any particular
version. For example, a version might be labeled
&amp;quot;{{publication|Published}}&amp;quot; or &amp;quot;{{Draft}}&amp;quot;. By versioning
content, the {{CMS}} retains a history of all the changes 
to a piece of content over time allowing {{editor|+s}} to 
rollback to prior versions if necessary or audit changes 
to content for security or regulatory purposes.
}%}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See those words in double brackets? Those are wiki-ish links that map to other terms based on ID slug and may display different text &amp;ndash; different words entirely, or modified versions of the source word (i.e. &amp;ndash; &amp;ldquo;editor|+s&amp;rdquo; links to &amp;ldquo;editor&amp;rdquo; but displays &amp;ldquo;editor&lt;em&gt;s&lt;/em&gt;&amp;rdquo;).I&amp;rsquo;ve written a parser to &amp;ldquo;expand&amp;rdquo; all these &amp;ldquo;macros&amp;rdquo; &amp;ndash; to find the correct term, modify the source word, and add the hyperlink.&lt;/p&gt;
&lt;p&gt;(And it&amp;rsquo;s not just me: Drupal has an entire architecture of &amp;ldquo;&lt;a href="https://www.drupal.org/node/213156"&gt;text filters&lt;/a&gt;,&amp;rdquo; and WordPress has a very popular system for handling &amp;ldquo;&lt;a href="https://en.support.wordpress.com/shortcodes/"&gt;shortcodes&lt;/a&gt;&amp;rdquo; &amp;ndash; I&amp;rsquo;ve used a couple in this very blog post, in fact. A more advanced version might be &lt;a href="http://episerver.com/"&gt;Episerver&amp;rsquo;s&lt;/a&gt; re-usable block elements that can be dragged into rich text fields.)&lt;/p&gt;
&lt;h2&gt;Example: Volume and Consistency&lt;/h2&gt;
&lt;p&gt;A law firm has 48 separate web properties. They all run on different platforms (some WordPress, some Sitecore, some hand-coded on non-executing environments like S3). They also have a series of blog posts, which they want to be able to insert into different sites (perhaps through a macro system, as described above).&lt;/p&gt;
&lt;p&gt;However, they want the &lt;em&gt;exact same format&lt;/em&gt; for the blog posts. They want a title, date, site name, preview, and link. They have a common HTML construct which can be styled for the individual property. What they don&amp;rsquo;t want is for each potential environment to &amp;ldquo;roll their own&amp;rdquo; templating code and form HTML from raw content. They want these all to appear the same way, in addition to the problem of some environments not being able to execute at all.&lt;/p&gt;
&lt;p&gt;What they need, then, is transformation at the repository (the &amp;ldquo;drivetrain&amp;rdquo;). So each blog post has all its raw, editorial content, but it also contains an HTML representation of the last time it was saved which can be rendered to the page, unaltered, in any language, on any platform. This is a problem if the only thing the consuming platforms can get is the raw content to templating separately. They don&amp;rsquo;t need that &amp;ndash; they need a bundle of content and rendering logic, cached to a string.&lt;/p&gt;
&lt;p&gt;(Could these posts be pre-rendered and cached as HTML in some central location? Sure, but then you lose a couple things &amp;ndash; searchability and any vendor-provided CDN or caching functionality &amp;ndash; which we&amp;rsquo;ll discuss more below.)&lt;/p&gt;
&lt;h2&gt;The Need for Repository-Centric Transformation&lt;/h2&gt;
&lt;p&gt;These three examples both lead me to the same conclusion: &lt;em&gt;I only want to do this early-stage transformation once.&lt;/em&gt; Here&amp;rsquo;s why:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The end result of these two situations doesn&amp;rsquo;t change post-publish. (Markdown renders to HTML, full stop.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It&amp;rsquo;s relatively painful to do, computationally.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It would be a lot of work to re-implement and maintain this logic for more than one language or platform. (What if it depends on a library that doesn&amp;rsquo;t exist for a particular platform?)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Beyond the sheer workload, I really only want &lt;em&gt;one&lt;/em&gt; canonical instance of this logic. (Markdown has many flavors. I don&amp;rsquo;t want developers applying their own preferred flavor to my source content.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Think back to our car analogy &amp;ndash; this is way up at the transmission level, right after power leaves in the engine. Late-stage templating is way back at the wheels. And once we start pushing content to multiple channels, this becomes a real problem. Remember: &lt;em&gt;Each wheel on the car doesn&amp;rsquo;t have its own transmission.&lt;/em&gt; There&amp;rsquo;s one transmission, which all the wheels benefit from, just like there is content transformation we don&amp;rsquo;t want to repeat in each consuming channel.&lt;/p&gt;
&lt;p&gt;(Consider the content from &lt;a href="http://flyingsquirrelbook.com/glossary/"&gt;my glossary site&lt;/a&gt;. If I wanted to use that here, on Gadgetopia, I would have to rewrite all that wiki link parsing and expansion logic in PHP (it&amp;rsquo;s in .NET right now). Believe me when I tell you that I don&amp;rsquo;t want to do this.)&lt;/p&gt;
&lt;h2&gt;&amp;ldquo;Back End for Front End&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;All the issues above aren&amp;rsquo;t problems if we own the entire content publishing apparatus, from start to finish. However, with the new crop of headless CMS, we often don&amp;rsquo;t. These are often SaaS systems, with which we interact through web APIs alone.&lt;/p&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;See &lt;a href="/tech/blog/state-of-the-headless-cms-market/"&gt;The State of the Headless CMS Market&lt;/a&gt; for more on this.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;Additionally, the vendors are frustratingly dogmatic in their desire to stay away from &lt;em&gt;any&lt;/em&gt; templating, including &amp;ldquo;drivetrain&amp;rdquo; transformation. They refuse to touch it on principle, priding themselves on only managing raw content and leaving it up to the consuming services to template.&lt;/p&gt;
&lt;p&gt;I was bouncing these issues off of a handful of vendors, and a couple mentioned that I should use a &amp;ldquo;&lt;a href="http://samnewman.io/patterns/architectural/bff/"&gt;backend for frontend&lt;/a&gt;,&amp;rdquo; or &amp;ldquo;BFF&amp;rdquo; as some are calling it. This would be my own infrastructure basically acting as middleware &amp;ndash; it stands between the headless CMS and my website (or whatever). My website communicates only with my BFF, and it&amp;rsquo;s the only thing that talks to the CMS.&lt;/p&gt;
&lt;p&gt;In this way, my BFF becomes my drivetrain. Consuming channels pull from the BFF and complete their late-stage templating individually.&lt;/p&gt;
&lt;p&gt;This solves some problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We can implement our own endpoints in the BFF.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can manage the transformation pipeline, doing some transformation in the BFF. (In the glossary example above, I could render and cache the wiki link functionality at the BFF level. A request for that rendered content would never even need to go further &amp;ldquo;back&amp;rdquo; to the CMS.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But there are disadvantages too.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The vendor often has elaborate caching systems in place to support massive loads, and &lt;em&gt;you&amp;rsquo;re paying for this&lt;/em&gt; &amp;ndash; this is often a huge selling point in the value proposition. In these cases, you lose all of that, and now have to re-implement caching in your BFF.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In addition to caching, you lose all the benefits of the vendor&amp;rsquo;s API, most painfully the query logic. You effectively now have to re-implement their API, including the ability to search everything, and avoiding this might have been the reason to decided to go headless in the first place.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For the vendor, it whittles away their value proposition, and may even reduce their product to a glorified database UI. This is a perilous place to be. Data storage and related admin interfaces are not that hard to replicate, and if your value proposition dwindles, so might the reasons for keeping you around.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m not saying a BFF isn&amp;rsquo;t valuable and appropriate in some places, but when a vendor immediately punts to that &amp;ldquo;solution,&amp;rdquo; they&amp;rsquo;re basically saying: &amp;ldquo;You&amp;rsquo;ve pointed out a valid problem, and the solution we&amp;rsquo;re recommending neutralizes a bunch of huge advantages to our product that we sold you on. So fix that yourself…but continue to pay us.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Clearly, this isn&amp;rsquo;t a panacea.&lt;/p&gt;
&lt;h2&gt;Possible Solutions&lt;/h2&gt;
&lt;p&gt;Support for early-stage transformation is not prevalent in the current marketplace, but some of this can be chalked up to the fact that the market is immature. &amp;ldquo;Headless&amp;rdquo; is an idea that has just lit up in the last few years, and most of these platforms are still under heavy development as they adapt to what customers want.&lt;/p&gt;
&lt;p&gt;Most platforms will support some event-driven processing via webhooks. When content is published, some of these systems will POST the entire contents of the published item to a specified URL, which can then take actions either on external systems or on the originating system via its API (the second case study &lt;a href="/tech/blog/case-studies-of-cms-to-sql-decoupled-publishing/"&gt;in this post&lt;/a&gt; describes how &lt;a href="http://contentful.com/"&gt;Contentful&lt;/a&gt; does this and provides sample code for receiving a webhook call).&lt;/p&gt;
&lt;p&gt;Using these frameworks, we could transform an object. When News Article X is saved, a webhook could receive that request and expand the macros in it…but then what? What does the webhook do with the resulting data?&lt;/p&gt;
&lt;p&gt;Ideally, we would push our result back into the content object itself, perhaps in a &amp;ldquo;hidden&amp;rdquo; field which editors can&amp;rsquo;t manage from the interface. With this, a content object might have a &amp;ldquo;Body&amp;rdquo; field and a &amp;ldquo;Processed Body&amp;rdquo; or &amp;ldquo;HTML&amp;rdquo; field. Consuming channels could use either as they needed.&lt;/p&gt;
&lt;p&gt;Pretty quickly, however, we&amp;rsquo;re going to run into a couple annoying problems: (1) webhook recursion and (2) version proliferation. If I was to save this data in a field and republish, I might trigger the same webhook again. Additionally, I now get two versions of every content object when I publish, which can confuse auditing and governance processes.&lt;/p&gt;
&lt;p&gt;What I&amp;rsquo;m not seeing in the market right now are either of these two options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&amp;ldquo;Silent&amp;rdquo; saving/publish capability, which means the ability to save/publish and explicitly avoid triggering events like webhook calls. In the absence of this, I&amp;rsquo;d like to at least some explicit nod toward managing webhook recursion &amp;ndash; some method of identifying when something has been published by the very webhook it&amp;rsquo;s about to call again.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An ability to save into the current version. Otherwise, you&amp;rsquo;re going to end up with an extra version every time you publish.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Clearly, both these situations are exceptions, but in the circumstances we&amp;rsquo;re describing, they&amp;rsquo;re exactly what they need. (Consider too that they exist in many other, more traditional CMS, so they&amp;rsquo;re part of the mainstream &amp;ldquo;CMS development toolkit,&amp;rdquo; so to speak.)&lt;/p&gt;
&lt;p&gt;Barring this option, there&amp;rsquo;s a solution, which might be a little hack-ish &amp;ndash; &lt;/p&gt;
&lt;p&gt;We could update a &amp;ldquo;companion&amp;rdquo; content object. Meaning, we might have a &amp;ldquo;News Article&amp;rdquo; type and a &amp;ldquo;Published News Article&amp;rdquo; type. The latter would contain some extra fields to store the transformed result. When I save a version of the former, a webhook or event actually copies its content &amp;ndash; along with some post-transformation data &amp;ndash; to its &amp;ldquo;twin.&amp;rdquo; Consuming channels would only be allowed to access the companion object &amp;ndash; the &amp;ldquo;Published News Article,&amp;rdquo; in our example.&lt;/p&gt;
&lt;p&gt;What we&amp;rsquo;re doing here is sort of phantom decoupling. We&amp;rsquo;re pushing pure content into a separate location (really a separate object) from which we&amp;rsquo;ll allow delivery. (There&amp;rsquo;s some precedent here in ECM. Many of those systems have a concept of &amp;ldquo;workspaces,&amp;rdquo; and when content is published, it&amp;rsquo;s often pushed from one workspace to another.)&lt;/p&gt;
&lt;p&gt;Another feature I&amp;rsquo;m waiting for a vendor to embrace is publishing &amp;ldquo;filters&amp;rdquo; which can transform content from management to delivery layer. The secret of headless CMS is that most of them are actually &lt;em&gt;decoupled&lt;/em&gt;. You manage the content in one environment, and when you publish, it&amp;rsquo;s being pushed to another environment which is optimized for mass delivery. This usually means a separate environment on the vendor&amp;rsquo;s infrastructure, or in many cases, a full-blown CDN. So your content object is actually &amp;ldquo;set free&amp;rdquo; into a larger environment when you publish (I&amp;rsquo;ve measured in this Contentful &amp;ndash; it takes a couple seconds to proliferate around the world into &lt;a href="https://www.fastly.com/"&gt;Fastly&lt;/a&gt; and &lt;a href="https://aws.amazon.com/cloudfront/"&gt;CloudFront&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;With this architecture, I&amp;rsquo;d like to see a publish webhook &lt;em&gt;which allows me to affect what gets pushed into the delivery CDN&lt;/em&gt;. So when I publish content from the management environment, a webhook is called, from which I can return modified data. &lt;em&gt;That data&lt;/em&gt; is what gets published. To use a terrible metaphor: published content is &amp;ldquo;bounced&amp;rdquo; off a webhook, and the CDN catches the rebound.&lt;/p&gt;
&lt;p&gt;This would allow me to do some content transformation (adding expanded content to an extra field, for example), and publish the transformed version while maintaining the purity of the original.&lt;/p&gt;
&lt;p&gt;I had some discussions with vendors around these points, and made a little progress when making my case:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://getdirectus.com"&gt;Directus&lt;/a&gt; actually implemented a publish event hook for me (and sent me &lt;a href="https://github.com/directus/directus/commit/f825c8c9e870b57c8fbf870c186b5b1a9fe6bb5d"&gt;the commit&lt;/a&gt; to prove it). So you can now run a transform event when content is requested, but before it&amp;rsquo;s given back. My reading of their code (&lt;a href="https://github.com/directus/directus"&gt;it&amp;rsquo;s open-source&lt;/a&gt;, remember) tells me that you could implement early stage templating through an event hook. That doesn&amp;rsquo;t necessarily cache, but it&amp;rsquo;s a step in the right direction.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One of the developers working on Contentful engaged with me in a running discussion about the idea of &amp;ldquo;metadata&amp;rdquo; on a content object. This is, simply, additional data that&amp;rsquo;s tacked onto content. It&amp;rsquo;s not versioned, you can&amp;rsquo;t manage it from the interface, and it&amp;rsquo;s not &amp;ldquo;first order&amp;rdquo; content, but you could use it to transform content and &amp;ldquo;attach&amp;rdquo; the result (for instance, the result of a transform) to be delivered with the content. This idea is just a discussion at the moment, but I like where it&amp;rsquo;s going.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The new version of &lt;a href="http://www.dnnsoftware.com/products/evoq-content"&gt;Evoq&lt;/a&gt;(which will be &amp;ldquo;hybrid headless&amp;rdquo;) has a concept of &amp;ldquo;visualizers&amp;rdquo; which are methods to template content prior to delivery via an API. This means you can get the raw content, but also a repository-centric transformation of it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At the core of these solutions is a desire to avoid the BFF we discussed in the previous section. If I can just do a transformation and &lt;em&gt;get the transformed result somehow back onto the content itself&lt;/em&gt; then I get to keep two things which are critical to the entire headless value proposition: (1) the performance of their delivery environment (which I&amp;rsquo;m paying for whether I use it or not), and (2) their native search API.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Headless CMS wholeheartedly embraced the paradigm of &amp;ldquo;separate content from presentation.&amp;rdquo; I don&amp;rsquo;t fault them for this, but this can get destructively dogmatic in some ways. The leap from raw to presentation isn&amp;rsquo;t necessarily a one-step process. Rather, we should look at this as a pipeline or a drivetrain that refines content through a series of steps.&lt;/p&gt;
&lt;p&gt;There is value in transforming content close to the repository, or progressively denormalizing content in such a way to increase manageability, performance, and consistency in the consuming channels. Headless vendors need to take some steps in this direction.&lt;/p&gt;</description>
      <pubDate>Tue, 21 Mar 2017 00:00:00 -0500</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/multi-stage-transformation/</guid>
    </item>
    <item>
      <title>An Unofficial Guide to Whatever-as-a-Service</title>
      <link>https://live.deanebarker.net/tech/blog/whatever-as-service/</link>
      <description>&lt;p&gt;If there&amp;rsquo;s one overwhelming trend in IT in the last decade it&amp;rsquo;s that no one wants to &lt;em&gt;sell&lt;/em&gt; you anything anymore, they just want to &lt;em&gt;rent&lt;/em&gt; it to you. Consequently, almost anything will run &amp;ldquo;-as-a-service&amp;rdquo; these days.&lt;/p&gt;
&lt;p&gt;SaaS is commonplace as a term, but it&amp;rsquo;s been over-used to apply to basically anything you do &amp;ldquo;in the cloud.&amp;rdquo; In the last few years, other variations on the phrase have been creeping in: namely PaaS and IaaS, but there are many, many others, and some other variations that &lt;em&gt;should&lt;/em&gt; exist, but don&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;The basics are simple. But, like anything, nothing stays basic and there are…complications.&lt;/p&gt;




&lt;table-of-contents title="Contents" selector="h2, h3, h4"&gt;&lt;/table-of-contents&gt;

&lt;h2&gt;The Big Three: IaaS, PaaS, and SaaS&lt;/h2&gt;
&lt;p&gt;First, let&amp;rsquo;s talk about the Big Three, which actually have &lt;a href="http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-145.pdf"&gt;official recognition from the National Institute of Standards and Technology (PDF)&lt;/a&gt; (NIST).  Here they are, in increasing level of refinement/abstraction.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;IaaS: Infrastructure as a Service.&lt;/strong&gt; This is raw infrastructure &amp;ndash; unadorned servers, load balancers, routers, firewalls, storage networks, etc. When you just fire up a fresh virtual server with nothing but an operating system, this is infrastructure. (And how do you pronounce this gem?  The consensus seems to be &amp;ldquo;eye-azz&amp;rdquo; because the alternative is really awkward.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PaaS: Platform as a Service.&lt;/strong&gt; This is an environment pre-configured and intended to assist you in building a known thing. For instance, a company might advertise &amp;ldquo;CMS X Hosting,&amp;rdquo; with a preconfigured environment, ready with database services, all the right ports open, and a build job ready to deploy your stuff from source and produce an installation of CMS X.  This is a &lt;em&gt;platform&lt;/em&gt;, designed to let you build on it. The key is that you don&amp;rsquo;t need to care about the &lt;em&gt;infrastructure&lt;/em&gt; &amp;ndash; in many cases, you know nothing about the actual servers and storage that make it possible.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SaaS: Software as a Service.&lt;/strong&gt;  This is a vendor that delivers you the services of a piece of software. The most interaction you&amp;rsquo;ll likely have with it is to log into a web interface and do some configuration and maybe a little uploading. You interact with the software and know nothing about either the &lt;em&gt;infrastructure&lt;/em&gt; or the &lt;em&gt;platform.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Do you notice how those three definitions build on each other? Each level assumes the levels before it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;With &lt;strong&gt;IaaS&lt;/strong&gt;, you&amp;rsquo;re the closest to the metal &amp;ndash; you know about everything, and probably manually configured all of it (you nerd).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;PaaS&lt;/strong&gt; environment certainly has infrastructure underneath it, but you&amp;rsquo;re abstracted away from all of it. You have all the tools to build the thing you want to build &amp;ndash; whether it be an ASP.NET app, a Node app, an Episerver-powered website, whatever &amp;ndash; but you don&amp;rsquo;t know the specifics of how that environment happens.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;SaaS&lt;/strong&gt; environment is another level removed: you don&amp;rsquo;t even know how this magic software happens. There&amp;rsquo;s infrastructure, and a programming platform and environment, but you&amp;rsquo;re happily oblivious and you usually just click around an interface to achieve some goal.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In a conversation this week, &lt;a href="http://content.lionbridge.com/category/cto-corner/"&gt;Seth Gottlieb from Lionbridge&lt;/a&gt; helped put it in context like this.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A sysadmin can immediately relate to &lt;strong&gt;IaaS&lt;/strong&gt;. They see the value and can be productive using it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A programmer can immediately relate to &lt;strong&gt;PaaS&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A power user can immediately relate to &lt;strong&gt;SaaS&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At each level, the prior levels become like your parents&amp;rsquo; sex life &amp;ndash; you grudgingly concede that it exists in some form, but you really don&amp;rsquo;t want to know anything else about it and &lt;em&gt;you would gladly pay money to not have to ever think about it&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Complication: Confusion of PaaS and SaaS&lt;/h2&gt;
&lt;p&gt;In the web development world, some of the stuff we refer to as &amp;ldquo;SaaS,&amp;rdquo; as actually &amp;ldquo;PaaS.&amp;rdquo; In general, we overuse the &amp;ldquo;SaaS&amp;rdquo; moniker.&lt;/p&gt;
&lt;p&gt;The major push from vendors in the last few years is to get your websites in their environments, which means you build, but they host in a incubated environment designed specifically for their software. This is a &lt;em&gt;platform on which you build stuff&lt;/em&gt;. These platforms have little or no value in their unadorned state.&lt;/p&gt;
&lt;p&gt;There is SaaS in the CMS world, but it&amp;rsquo;s limited to systems that literally let you log in and interact with the environment as a &lt;em&gt;software service&lt;/em&gt;. I&amp;rsquo;m thinking about systems like &lt;a href="http://squarespace.com/"&gt;Squarespace&lt;/a&gt; and &lt;a href="http://wix.com/"&gt;Wix&lt;/a&gt;. You don&amp;rsquo;t &lt;em&gt;build&lt;/em&gt; in these environments. You simply &lt;em&gt;use&lt;/em&gt; them.&lt;/p&gt;
&lt;p&gt;And I&amp;rsquo;m wondering if this is the dividing line for PaaS and SaaS &amp;ndash; do you build in it?  The P in PaaS is &amp;ldquo;platform,&amp;rdquo; and a platform is a thing that supports another thing. If nothing ever sat on a platform, you&amp;rsquo;d wonder what it was for. So, if something is an environment in which we build, then it&amp;rsquo;s a platform.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example of climbing up this ladder with Drupal:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;IaaS:&lt;/strong&gt; If you want a Drupal site, there&amp;rsquo;s nothing stopping you from getting a server at Amazon Web Services (AWS) and loading up Apache, MySQL, PHP, and whatever else you need, changing DNS and launching. You are now running on IaaS. AWS has provided the infrastructure, but you turned it into a platform and you loaded the software.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PaaS:&lt;/strong&gt; Alternately, you could call up Acquia. They provide a platform called &lt;a href="https://www.acquia.com/products-services/acquia-cloud"&gt;Acquia Cloud&lt;/a&gt;. This is a bunch of servers at AWS (you don&amp;rsquo;t care about the specific servers, remember, you just trust that there&amp;rsquo;s a bunch of them up there), and they&amp;rsquo;ve set them all up to run Drupal with a bunch of value-added stuff like search and really good dev ops and deployment models, which, with Drupal, can be tricky.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SaaS:&lt;/strong&gt; Finally, if we step back in time a year, you could have used the now-defunct &lt;a href="https://www.drupalgardens.com/"&gt;Drupal Gardens&lt;/a&gt;. These were preconfigured Drupal instances you could get by just creating an account and providing a credit card number. Naturally, there was a limited number of things you could do with them (they only had a handful of the most popular modules), and you couldn&amp;rsquo;t deploy any of your own code, but they were simple and quick.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(Related to this: Nasdaq just announced &lt;a href="http://business.nasdaq.com/intel/ir-management/communication-and-compliance/ir-websites"&gt;customized investor relation sites&lt;/a&gt; for its listed companies. Sign up for the service, and they&amp;rsquo;ll generate a custom, Acquia-hosted Drupal install, just for you. In effect, they have a SaaS product that stamps out PaaS environments which is recursive as hell.)&lt;/p&gt;
&lt;p&gt;Finally, &lt;a href="http://www.episerver.com/about-us/Episerver-Contacts/Episerver-Management/james-norwood/"&gt;James Norwood from Episerver&lt;/a&gt; helpfully pointed out that differentiation between PaaS and SaaS it might come down to questions of tenancy: do you share your system with anyone else? If you don&amp;rsquo;t, then this is likely IaaS or PaaS.  If you do, then it&amp;rsquo;s almost always SaaS.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s tough to share a building platform with anyone else because it&amp;rsquo;s easy to make a mistake and jack the environment up for everyone. Eventually, the vendor starts to segregate more and more, and the end of that line might be a completely sandbox, interfaced system which becomes multi-tenant SaaS.&lt;/p&gt;
&lt;h2&gt;Complication: Differentiating Between IaaS and PaaS&lt;/h2&gt;
&lt;p&gt;The big challenge for a lot of PaaS vendors is getting customers to understand the different between IaaS and their PaaS offerings. People are still in the mode of thinking about &amp;ldquo;hosting.&amp;rdquo; Basic hosting is infrastructure. But vendors are now &amp;ldquo;wrapping&amp;rdquo; hosting in a plethora of value-added services, which ostensibly bumps them up a notch to become a platform.&lt;/p&gt;
&lt;p&gt;I talked to &lt;a href="https://www.acquia.com/about-us/team/david-aponovich"&gt;David Aponovich from Acquia&lt;/a&gt;, and he said this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We see organizations investigating Drupal and Cloud and they&amp;rsquo;ll talk with Acquia and say, &amp;ldquo;So, we&amp;rsquo;ve decided to use Drupal over Sitecore and Adobe, but why do I need Acquia when I can just do a DIY on Amazon AWS?&amp;rdquo; And we say, well what about this, this and this, and they realize, &amp;ldquo;Oh, this isn&amp;rsquo;t just AWS infrastructure-as-a-service, there&amp;rsquo;s a lot more services and automation here &amp;ndash; it&amp;rsquo;s a platform-as-a-service for my Drupal applications, not just services for infrastructure and hosting.&amp;rdquo; The development and a management services such as provisioning, deployment staging, and security are important.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Episerver has a PaaS product call the &lt;a href="http://world.episerver.com/digital-experience-cloud-service/"&gt;Digital Experience Cloud Service&lt;/a&gt;. Norwood articulates the benefits of it above and beyond &amp;ldquo;just&amp;rdquo; the IaaS that Azure offers:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;At the end of the day, anyone can host a virtual machine on anyone&amp;rsquo;s public cloud (AWS, Azure, etc), and it will run, but it&amp;rsquo;s sort of just hosting in the old sense of the word. Episerver and many of our partners can sell you a license and then host and/or manage it for you on a public cloud, but that&amp;rsquo;s it.&lt;/p&gt;
&lt;p&gt;With the approach Episerver invested in over two years ago now, we elected to go deep into the Microsoft Azure PaaS so we could unlock the benefits of the platform for customers as well, such benefits include elastic scalability, pay for use consumption, and application level SLAs above the infrastructure SLA. If your bet is to support every public cloud, as a vendor you get more reach, but if you go deep into the PaaS layer it&amp;rsquo;s the customer who benefits too.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That &amp;ldquo;crossing of the threshold&amp;rdquo; between IaaS and PaaS is something that vendors are having to sell people on, every day. Many people are still programmed to think in terms of simple hosting. It remains to be seen how well that definition changes.&lt;/p&gt;
&lt;p&gt;As an integrator, I get a little annoyed with the &amp;ldquo;cloud&amp;rdquo; moniker, because it doesn&amp;rsquo;t mean anything, colloquially. In a strictly technical sense, &amp;ldquo;cloud computing&amp;rdquo; has a NIST definition (same link as above), but for most people, &amp;ldquo;cloud&amp;rdquo; just means &amp;ldquo;not my problem.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;At &lt;a href="http://blendinteractive.com/"&gt;Blend&lt;/a&gt;, we host for lots of our clients. In this sense, we are as &amp;ldquo;cloud&amp;rdquo; as anything else because we make all their hosting problems go away.  We host on infrastructure that we rent from AWS &amp;ndash; pure infrastructure. But if we wrapped all that stuff in a bunch of Blend propriety stuff and created a gorgeous little incubator in which a website could thrive and grow, well, now we&amp;rsquo;re moving to a &amp;ldquo;platform.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;If you have &amp;ldquo;managed hosting,&amp;rdquo; that means someone else babysits it. Is that someone else the final value-add of the &amp;ldquo;platform&amp;rdquo;?  Hosting yourself would be at the infrastructure level, but if someone else manages it for you and provides value-add on top of that (and you would hope they did, or else what would be the point), does the combination become a &amp;ldquo;platform&amp;rdquo;?&lt;/p&gt;
&lt;p&gt;(There&amp;rsquo;s a much larger post here about how vendor PaaS platforms have encroached considerably on integrator&amp;rsquo;s service offerings, and there are some bad feelings as a result. But we&amp;rsquo;ll tackle that on another day.)&lt;/p&gt;
&lt;p&gt;More fundamental to this particular complication is where we draw the line between infrastructure and platform. I remember getting servers back in the day with &lt;a href="https://www.plesk.com/"&gt;Plesk&lt;/a&gt; or &lt;a href="https://cpanel.com/"&gt;CPanel&lt;/a&gt; loaded on them. These control panels managed dozens of other services on the machine &amp;ndash; everything from FTP to SMTP. In this sense, did we have a platform?&lt;/p&gt;
&lt;p&gt;Coming back to the idea of value-added services as the thing which moves us from infrastructure to platform, was all the stuff offered by CPanel- or Plesk-enabled servers enough to say we made that leap? They seem to think so &amp;ndash; both their websites refer to their offerings as a &amp;ldquo;platform.&amp;rdquo;&lt;/p&gt;
&lt;h2&gt;Complication: Wedged Between PaaS and SaaS…Framework-as-a-Service?&lt;/h2&gt;
&lt;p&gt;Of course, you knew this would get blurry because it always does &amp;ndash; &lt;/p&gt;
&lt;p&gt;We build on platforms, but &amp;ldquo;building&amp;rdquo; is a vague term. We tend to think of building as having a completely self-contained codebase which we then push up to another environment. We even run these things locally, and when they&amp;rsquo;re running to go, we deploy them to some parallel environment.&lt;/p&gt;
&lt;p&gt;But there are SaaS-ish (there&amp;rsquo;s always an &amp;ldquo;-ish&amp;rdquo;) systems that allow a limited amount of &amp;ldquo;building.&amp;rdquo; Take &lt;a href="https://www.coredna.com/"&gt;Coredna&lt;/a&gt; for example (yes, the capitalization is weird &amp;ndash; it&amp;rsquo;s &amp;ldquo;Core D-N-A&amp;rdquo;). This is an ostensibly SaaS CMS system. I got a demo last week and I genuinely enjoyed what I saw.&lt;/p&gt;
&lt;p&gt;Here was the best part &amp;ndash; &lt;/p&gt;
&lt;p&gt;Templating is not by configuration. This is not a &amp;ldquo;drag stuff around&amp;rdquo; system, like Squarespace or a Wix. In Coredna, you legitimately get &lt;em&gt;templates&lt;/em&gt; written in &lt;a href="http://www.smarty.net/"&gt;Smarty&lt;/a&gt;, and you can use these to power your site. You can even point Coredna at your Git repo, and it will pull your templates from there, so you can work in an honest-to-goodness IDE.&lt;/p&gt;
&lt;p&gt;This was refreshing to see, and I commend them for it.&lt;/p&gt;
&lt;p&gt;More to the point: with an architecture like this, you get some form of pseudo-development or &amp;ldquo;building.&amp;rdquo; Smarty, for its part, supports &lt;a href="http://www.smarty.net/docs/en/language.function.foreach.tpl"&gt;looping&lt;/a&gt; and &lt;a href="http://www.smarty.net/docs/en/language.function.if.tpl"&gt;conditionals&lt;/a&gt;, which are two of the hallmarks of a logically complete language.  Furthermore, Smarty knows if you&amp;rsquo;re fielding &lt;a href="http://www.smarty.net/docs/en/language.variables.smarty.tpl#idp32462272"&gt;a GET or POST request&lt;/a&gt;, which means you could conceivably post forms back and do stuff accordingly.&lt;/p&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;Back in 2005, I discussed &lt;a href="/tech/blog/smarty-as-sub-language/"&gt;Smarty as a sub-language&lt;/a&gt;, &amp;ldquo;under&amp;rdquo; PHP. How prophetic.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;At this level, we&amp;rsquo;re clearly &amp;ldquo;building&amp;rdquo; something. We&amp;rsquo;re working with code. We&amp;rsquo;re looping and we&amp;rsquo;re evaluating conditionals and we&amp;rsquo;re probably pushing the boundaries of a front-end developer and actual involving some server-side development logic. In some senses, this isn&amp;rsquo;t even &amp;ldquo;templating&amp;rdquo; anymore.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re building on Coredna in this sense, are we SaaS or PaaS? Clearly, Coredna exists as a discrete piece of software into which we authenticate and do stuff, but it also depends on a significant amount of code-building which we do outside the system.&lt;/p&gt;
&lt;p&gt;I asked &lt;a href="https://www.coredna.com/about-us#management"&gt;Sam Saltis, the founder of Coredna&lt;/a&gt; where he saw the system fitting in:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I see it as a SaaS platform. For me a PaaS still means that every site is a unique instance of business logic, sharing a common infrastructure. With Coredna we we have a common infrastructure like PaaS but we also have a common pre-built software layer that everyone uses.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In some senses, an argument could be made that this is PaaS, and &lt;em&gt;Coredna is simply the top of the stack&lt;/em&gt;. It&amp;rsquo;s the thing that sits above Apache on the stack. It&amp;rsquo;s the final step in the &amp;ldquo;platform,&amp;rdquo; much like someone could argue that the ASP.NET MVC assemblies sit above IIS in a .NET platform. You have to ask the question, &amp;ldquo;how far do you have to develop the stack for the system to &amp;lsquo;graduate&amp;rsquo; from PaaS to SaaS?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;(Beyond templating, I&amp;rsquo;m wondering when a SaaS system will take a deeper leap into scripting. There&amp;rsquo;s sandboxed JavaScript capabilities that are just begging to be put to use in allowing &lt;a href="/tech/blog/editorial-scripting-in-cms/"&gt;editorially scripted&lt;/a&gt; responses to events. I&amp;rsquo;ve even written one editorial scripting language &amp;ndash;  &lt;a href="http://denina.org/"&gt;Denina&lt;/a&gt;  &amp;ndash; though it&amp;rsquo;s purely output-focused.)&lt;/p&gt;
&lt;p&gt;And this is where we get to definitional bias: who decides where we draw the lines between the (1) infrastructure, (2) platform, and (2) software? Who decides where the &amp;ldquo;platform&amp;rdquo; ends?&lt;/p&gt;
&lt;p&gt;There are a lot of systems that are easy to classify as SaaS, but are useless without a significant amount of site-building that looks an awful lot like programming. In these situations, the line between what&amp;rsquo;s the platform and what&amp;rsquo;s the software get blurry. Where do you draw the line between a piece of software and a code library?&lt;/p&gt;
&lt;p&gt;In the end, something like Coredna sits in a weird space: it&amp;rsquo;s either &amp;ldquo;flexible SaaS&amp;rdquo; or &amp;ldquo;rigid PaaS.&amp;rdquo;  How about something new &amp;ndash; Framework-as-a-Service (FaaS)?&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s clearly more constrained than a platform, but more configurable than simply software. Into this category, we might put other systems which support pseudo-development, like &lt;a href="https://products.office.com/en-us/sharepoint/sharepoint-online-collaboration-software"&gt;SharePoint Online&lt;/a&gt; (especially when combined with a development toolkit like &lt;a href="http://akumina.com./"&gt;Akumina&lt;/a&gt;) and &lt;a href="http://shopify.com/"&gt;Shopify&lt;/a&gt;, which you can manually template much like Coredna.&lt;/p&gt;
&lt;h2&gt;Complication: Component-as-a-Service&lt;/h2&gt;
&lt;p&gt;As the &amp;ldquo;as-a-service&amp;rdquo; suffix began to gain steam, we suddenly had vendors coming out of the woodwork laying claim to the model. I&amp;rsquo;ve seen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Content-as-a-Service&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Search-as-a-Service&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Information-as-a-Service&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Business-Process-as-a-Service&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;ldquo;As-a-service&amp;rdquo; has become a moniker for &amp;ldquo;anything you don&amp;rsquo;t own but you pay a subscription fee for.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Many of these are things you might use in the building of something else. In this sense, they invert the above models. Instead of the subscription target being something you build &amp;ldquo;in&amp;rdquo; or &amp;ldquo;on,&amp;rdquo; the subscription target becomes a smaller component of a larger conceptual thing you&amp;rsquo;re building elsewhere.&lt;/p&gt;
&lt;p&gt;Rather than a subscription being the over-arching framework, the subscription becomes a cog in a larger machine. Generically, we might call these things &amp;ldquo;Component-as-a-Service&amp;rdquo; (CaaS; because &amp;ldquo;Service-as-a-Service&amp;rdquo; sounds weird).&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s consider &amp;ldquo;Content-as-a-Service.&amp;rdquo; This is a suffix to which &lt;a href="/tech/blog/state-of-the-headless-cms-market/"&gt;a number of headless CMS vendors&lt;/a&gt; are trying to lay claim. The idea is that content is a smaller part of a larger application, and you can abstract that away to a service.&lt;/p&gt;
&lt;p&gt;I asked Artas Bartas over at &lt;a href="http://contentful.com/"&gt;Contentful&lt;/a&gt; if they considered themselves SaaS or PaaS, and this was his response:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&amp;rsquo;d say Contentful is a SaaS offering. The way I see it, PaaS is a use-case agnostic platform that allows you build a wide range of applications without worrying about managing dependencies. Dev-focused SaaS platforms, on the other hand, are more selective in the types of use-cases they support and therefore, limit the range of applications you can build on top.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And this might be where we dip into the burgeoning world of &amp;ldquo;micro-services,&amp;rdquo; which is a paradigm of development whereby you divide your monolithic application into a bevy of tiny services, each doing one thing. Once you begin &lt;em&gt;subscribing&lt;/em&gt; to these services, rather than building them, then you start looking around for &amp;ldquo;whatever-as-a-service.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;With Component-as-a-Service, we might be closer to fulfilling &amp;ndash; on a grand scale &amp;ndash; &lt;a href="https://en.wikipedia.org/wiki/Eric_S._Raymond"&gt;Eric Raymond&amp;rsquo;s&lt;/a&gt; dream of the Rule of Modularity from &lt;a href="https://www.amazon.com/UNIX-Programming-Addison-Wesley-Professional-Computng/dp/0131429019"&gt;The Art of Unix Programming&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Developers should build a program out of simple parts connected by well-defined interfaces, so problems are local, and parts of the program can be replaced in future versions to support new features.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;For many years, a guy named &lt;a href="https://en.wikipedia.org/wiki/Shiva_Ayyadurai"&gt;Shiva Ayyadurai&lt;/a&gt; (who&amp;rsquo;s &lt;a href="http://people.com/celebrity/first-look-see-fran-dreschers-official-wedding-photo/"&gt;married to Fran Drescher&lt;/a&gt;, weirdly) has claimed that &lt;a href="http://www.inventorofemail.com/"&gt;he invented email&lt;/a&gt;. In fact, he sued Gawker Media and &lt;a href="http://gizmodo.com/internet-pioneers-slam-750-000-settlement-for-the-man-1788503950"&gt;won a sizable settlement&lt;/a&gt; because Gizmodo said that he didn&amp;rsquo;t. However, many people feel that the recently departed &lt;a href="https://en.wikipedia.org/wiki/Ray_Tomlinson"&gt;Roy Tomlinson&lt;/a&gt; invented email. The debate rages.&lt;/p&gt;
&lt;p&gt;But here&amp;rsquo;s the thing: to decide who &amp;ldquo;invented email,&amp;rdquo; &lt;em&gt;you have to decide what email is&lt;/em&gt;. The argument becomes one of &lt;em&gt;definitions&lt;/em&gt;, not necessarily actions.&lt;/p&gt;
&lt;p&gt;The concept of &amp;ldquo;email&amp;rdquo; exists on a spectrum of functionality, from some encoded characters moving from one computer to another, all the way through the huge, bloated email clients we have today. At what point along that scale of innovation could someone step back and say, &amp;ldquo;yep, there it is &amp;ndash; that&amp;rsquo;s this thing called &amp;lsquo;email&amp;rsquo; and I just invented it.&amp;rdquo; The definition of a thing presumes a minimum set of requirements necessary to achieve that thing. Who decides those minimums?&lt;/p&gt;
&lt;p&gt;I have no doubt that Ayyadurai invented &lt;em&gt;something&lt;/em&gt;, but opinions differ on exactly what that thing was. He clearly believes his innovation can be summed up by the label of &amp;ldquo;email,&amp;rdquo; but not everyone agrees. To some, more features and functionality were required to cross the &amp;ldquo;line of definition&amp;rdquo; that constitutes email.&lt;/p&gt;
&lt;p&gt;And the same is true of &amp;ldquo;whatever-as-a-service.&amp;rdquo; Agreeing what &amp;ldquo;whatever&amp;rdquo; &lt;em&gt;is&lt;/em&gt; can be tricky, so splitting hairs about what constitutes infrastructure, platform, or software is subjective &amp;ndash; even more so when you add concepts like &amp;ldquo;component&amp;rdquo; and &amp;ldquo;framework,&amp;rdquo; as we discussed above. Different people have different &amp;ldquo;lines of definition,&amp;rdquo; and arguments can be made regarding which lines a particular vendor crosses or falls short.&lt;/p&gt;
&lt;p&gt;So, asking a vendor whether or not their offering is IaaS, PaaS, SaaS, CaaS, or FaaS is basically soliciting an opinion of where they see their product fitting on a disputed range of functionality, based on how they intend for their customers to use it.&lt;/p&gt;
&lt;p&gt;Whether or not the marketplace agrees with that assessment is another matter entirely.&lt;/p&gt;


&lt;blockquote&gt;
&lt;strong&gt;Note:&lt;/strong&gt;
&lt;p&gt;My thanks for David Aponovich, James Norwood, Sam Saltis, Artas Bartas, Seth Gottlieb and others who provided quotes and feedback during the writing of this post.&lt;/p&gt;

&lt;/blockquote&gt;</description>
      <pubDate>Fri, 10 Feb 2017 00:00:00 -0600</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/whatever-as-service/</guid>
    </item>
    <item>
      <title>The State of the Headless CMS Market</title>
      <link>https://live.deanebarker.net/tech/blog/state-of-the-headless-cms-market/</link>
      <description>&lt;p&gt;Headless CMS is about to &amp;ldquo;tip.&amp;rdquo; It&amp;rsquo;s been gaining steam in the last few years, and 2017 looks to be its big year.&lt;/p&gt;
&lt;p&gt;However, the market is vague and prone to definitional bias &amp;ndash; in some senses, &amp;ldquo;headless&amp;rdquo; is whatever someone says it is. Additionally, systems exist somewhere on a range of purity and allegiance to a mythical &amp;ldquo;headless ideal.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This post is an attempt to put some structure on the market, and define the options which (arguably) make it up. I&amp;rsquo;ve defined both specific headless offerings and &amp;ldquo;headless-ish&amp;rdquo; architectures.&lt;/p&gt;
&lt;p&gt;For each, I provide some examples, but I clearly don&amp;rsquo;t know about every CMS in the world. This post is not meant to provide an exhaustive list. The examples are merely illustrative and a source for more research.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve listed the categories in descending order of &amp;ldquo;purity,&amp;rdquo; meaning the extent to which the model aspires to be a pure headless system (and, yes, even what composes the ideal is entirely arguable).&lt;/p&gt;




&lt;table-of-contents title="Contents" selector="h2, h3, h4"&gt;&lt;/table-of-contents&gt;

&lt;h2&gt;What is Headless CMS?&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;Headless&amp;rdquo; is an architecture or &amp;ndash; even more loosely &amp;ndash; a paradigm or belief. If we consider the &amp;ldquo;head&amp;rdquo; of a CMS to be the subsystem by which content is finally presented to the end consumer, a headless CMS is what you have when this subsystem is &amp;ldquo;lopped off.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;In a headless CMS, you have modeling and editorial tools to help you describe, create, edit, and otherwise manipulate content. But the concept of &amp;ldquo;publishing&amp;rdquo; content just means, &amp;ldquo;make it available via an API.&amp;rdquo; A headless CMS is a &amp;ldquo;content-focused datasource,&amp;rdquo; from which you can build content-based applications.&lt;/p&gt;
&lt;p&gt;Headless is not the same as &amp;ldquo;decoupled.&amp;rdquo; A &lt;a href="/tech/blog/decoupled-content-management-101/"&gt;decoupled CMS&lt;/a&gt; &lt;em&gt;is&lt;/em&gt; concerned with presenting content, it simply pushes that content into a delivery environment, separate from the management environment. That separation of delivery and publishing is something that headless and decoupled CMSs share, but the difference is that a decoupled system concerns itself with what happens in the delivery environment &amp;ndash; for example, it has some concept of templating &amp;ndash; while a headless system doesn&amp;rsquo;t. A headless CMS assumes developers have content delivery handled via other means.&lt;/p&gt;
&lt;p&gt;A decoupled CMS is &lt;em&gt;proactive&lt;/em&gt; &amp;ndash; it prepares content for presentation and pushes it into a delivery environment. A headless CMS is &lt;em&gt;reactive&lt;/em&gt; &amp;ndash; it manages content, then just sits and waits for some process to ask for it.&lt;/p&gt;
&lt;p&gt;Headless systems tacitly distance themselves from HTML and website-centric implementations. You can absolutely power a website from a headless system, but you can also power mobile apps, display advertising, business applications, etc. (See my prior post: &amp;ldquo;&lt;a href="/tech/blog/use-cases-for-headless-cms/"&gt;Use Cases for Headless CMS&lt;/a&gt;.&amp;rdquo;) Headless systems attempt to lay claim to &amp;ldquo;pure&amp;rdquo; content that can be repurposed and presented through multiple different mediums.&lt;/p&gt;
&lt;p&gt;(Perhaps also read the definition of &amp;ldquo;&lt;a href="http://flyingsquirrelbook.com/glossary/term/coupling-model"&gt;coupling models&lt;/a&gt;&amp;rdquo; over at the &lt;a href="http://flyingsquirrelbook.com/glossary/"&gt;Web Content Management Glossary&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;With that aside, let&amp;rsquo;s talk about what this market looks like as of this writing.&lt;/p&gt;
&lt;h2&gt;1. Pure Headless CMSs&lt;/h2&gt;
&lt;p&gt;Part of why the headless market is tipping is because &amp;ldquo;pure&amp;rdquo; players have entered it and are getting attention. They&amp;rsquo;ve defined the term and moved it from some improvised to something &lt;em&gt;intentional&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Intentionality is an important point. If you&amp;rsquo;ve ever spent any time building a CMS, it likely consisted of an enhanced admin system to a relational database. The presentation of content on &amp;ldquo;the other side&amp;rdquo; was done through traditional methods (I first wrote about this model &lt;em&gt;13 years ago&lt;/em&gt; &amp;ndash; &lt;a href="/tech/blog/cms-administration-vs-presentation-languages/"&gt;CMS Administration vs. Presentation Languages&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In some senses, we were all building &amp;ldquo;headless CMSs&amp;rdquo; back in the day, before we got &amp;ldquo;more sophisticated&amp;rdquo; on the delivery side and moved on. This model was really the genesis of the modern CMS market. The difference is that vendors have now sprung up and effectively said, &amp;ldquo;&lt;em&gt;This is okay.&lt;/em&gt; This is no longer a compromise. This is an effective paradigm of CMS, and we&amp;rsquo;re going to formalize and build on it.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The leader here is likely &lt;a href="http://contentful.com/"&gt;Contentful&lt;/a&gt;, as it has funding, staff, and momentum. Contentful began as a system to store content for mobile apps (it was once called &amp;ldquo;Storage Room&amp;rdquo;), and thus had no web origins at all.&lt;/p&gt;
&lt;p&gt;Like Contentful, &lt;a href="https://prismic.io/"&gt;Prismic&lt;/a&gt; is a hosted service, as is &lt;a href="https://buttercms.com/"&gt;Butter CMS&lt;/a&gt; (seems to be blog-focused). &lt;a href="https://getdirectus.com/"&gt;Directus&lt;/a&gt; can be on-premise (it&amp;rsquo;s open-source, written in PHP) but offers hosted options for those who don&amp;rsquo;t want to manage it. (And new ones pop-up all the time: I just stumbled on &lt;a href="https://elemeno.io/"&gt;Elemeno&lt;/a&gt; while writing this post…)&lt;/p&gt;
&lt;p&gt;Also in this category, we have &lt;a href="https://gathercontent.com/"&gt;Gather Content&lt;/a&gt;. This has traditionally been a pre-implementation content aggregation service (a market it basically invented). However, Gather Content is seeing more and more usage by organizations using it for core content management, since the line between their original market and headless CMS is blurry. If you&amp;rsquo;ve structured, aggregated, and cleaned all your content in preparation for a CMS move…then you might already have a CMS, accidentally.&lt;/p&gt;
&lt;p&gt;Also of interest is &lt;a href="https://kenticocloud.com/"&gt;Kentico Cloud&lt;/a&gt;. You might think this should go below as a traditional/cloud hybrid, but it actually has &lt;em&gt;zero&lt;/em&gt; relation to the Kentico CMS. It&amp;rsquo;s a scratch code, ground-up build of a new product that shares nothing with their existing CMS except the name.&lt;/p&gt;
&lt;h2&gt;2. CMSs with Specific Headless Subsystems&lt;/h2&gt;
&lt;p&gt;This is an odd category. What I&amp;rsquo;m including here is traditional CMSs complete with presentation systems, but that include some specific gesture towards headless usage, and which could be used headlessly by specific design, rather than just re-purposed to a headless use case.&lt;/p&gt;
&lt;p&gt;The new release of &lt;a href="http://www.dnnsoftware.com/products/evoq-content"&gt;Evoq&lt;/a&gt; (v9) will include the ability to manage content in a local installation and have that content pushed/synced to their cloud environment, where it can be accessed remotely by other processes. This is a unique model which ends up as a hybrid &amp;ndash; clearly, serving a website is the primary purpose, but the model concedes that might not be the only purpose and provides a framework for access.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.ingeniux.com/"&gt;Ingenuix&lt;/a&gt; occupies a unique space as perhaps the only decoupled .NET CMS, so it&amp;rsquo;s accustomed to heavy remote API usage &amp;ndash; if something happens a decoupled delivery environment that needs to be pushed &amp;ldquo;backwards&amp;rdquo; into the repository, then a remote API is how you do that. As such, Ingeniux has a separate middleware component called Dynamic Site Server (DSS) which you could conceivably use without bothering with decoupled publishing at all.&lt;/p&gt;
&lt;p&gt;So, if there are so few vendors here, why include this category? &lt;em&gt;Because I think we&amp;rsquo;ll see this more and more.&lt;/em&gt; I don&amp;rsquo;t think Evoq and Ingeniux will be alone here for long, and you&amp;rsquo;re going to see traditional vendors (the next category) adopt headless functionality enough to slip &amp;ldquo;upwards&amp;rdquo; into this space.&lt;/p&gt;
&lt;p&gt;(A good example: one would expect &lt;a href="http://kentico.com/"&gt;the core Kentico CMS&lt;/a&gt; to connect to their cloud offering at some point, thus making that a hybrid as well. This is such an obvious pairing, that if they didn&amp;rsquo;t do it, it might feel a little odd.)&lt;/p&gt;
&lt;h2&gt;3. CMSs with Good APIs and Extensibility&lt;/h2&gt;
&lt;p&gt;This is where things get blurry and weird…&lt;/p&gt;
&lt;p&gt;A lot of traditional CMS vendors are likely looking at the &amp;ldquo;headless&amp;rdquo; market with annoyance. Repurposing content out of a web CMS is not new &amp;ndash; this is the essence of multi-channel publishing &amp;ndash; and customers have been doing this for years now.&lt;/p&gt;
&lt;p&gt;While almost all systems have local, language-specific APIs, many (if not most) systems also have remote REST/SOAP APIs to pull content from outside the CMS environment. In that sense, is this not also a &amp;ldquo;headless CMS&amp;rdquo;? By our prior definition it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Models and manages content&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Has no presentation component (for the specific act of pulling content through a remote API)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is reactive, waiting for another process to retrieve content&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Using a traditional web CMS through a remote API would look awfully like any pure headless CMS. &lt;a href="http://blendinteractive.com/"&gt;Blend&lt;/a&gt; has done this with &lt;a href="http://episerver.com/"&gt;Episerver&lt;/a&gt; &amp;ndash; a client accessed Episerver content via Ajax to power contextual help in their web application. And I&amp;rsquo;m hearing about &amp;ldquo;headless &lt;a href="http://drupal.org"&gt;Drupal&lt;/a&gt;&amp;rdquo; more and more often.&lt;/p&gt;
&lt;p&gt;Some vendors might have such a sophisticated remote API that they could conceivably not change a thing and simply start marketing themselves as &amp;ldquo;headless&amp;rdquo; and not be disingenuous at all.&lt;/p&gt;
&lt;p&gt;Even if your CMS doesn&amp;rsquo;t have a remote API, some programming platforms make it easy to add this. My experience is mainly with ASP.NET, and I can attest that it&amp;rsquo;s absurdly easy (like, 10 minutes easy) to set up an XML or JSON endpoint to deliver content however you like.&lt;/p&gt;
&lt;p&gt;Where you might run into problems is in more pedestrian things like licensing. Many commercial CMSs are licensed by website or, more abstractly, by consuming process. If you start scattering content around headlessly, a vendor might claim you&amp;rsquo;re violating the licensing agreement. It will be interesting to see how licensing adapts to this, either proactively or by customer demand.&lt;/p&gt;
&lt;p&gt;Also interesting will be to what extent traditional CMS vendors alter their marketing to address the headless market. Some vendors are already marketing against related search terms. Here&amp;rsquo;s &lt;a href="http://dotcms.com/solutions/content-as-a-service"&gt;one such landing page from dotCMS&lt;/a&gt; touting the &amp;ldquo;API at its core.&amp;rdquo;  Here&amp;rsquo;s &lt;a href="https://www.onehippo.com/en/resources/blogs/2016/2/why-headless-cms-is-wrong.html"&gt;another from Hippo&lt;/a&gt; taking the opposite tack: explaining why headless CMS is &amp;ldquo;wrong.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m wondering how antagonistic or conciliatory traditional vendors will be with their marketing. I know of one vendor that refuses to promote their system as &amp;ldquo;headless&amp;rdquo; because it &amp;ldquo;helps the [headless] cause.&amp;rdquo; As more and more customers go headless, will the existing market align or distance itself?&lt;/p&gt;
&lt;h2&gt;4. Enterprise CMS&lt;/h2&gt;
&lt;p&gt;The &amp;ldquo;old guard&amp;rdquo; of content management is traditionally enterprise systems (ECM) like &lt;a href="http://documentum.com/"&gt;Documentum&lt;/a&gt;, &lt;a href="http://alfresco.com/"&gt;Alfresco&lt;/a&gt;, &lt;a href="http://nuxeo.com/"&gt;Nuxeo&lt;/a&gt;, and even &lt;a href="https://en.wikipedia.org/wiki/SharePoint"&gt;SharePoint&lt;/a&gt;. These systems are primarily concerned with managing content and have very little capacity for content presentation beyond the administrative interface itself. These systems are so management-focused, that most presentation functionality is only to make management and administration easier.&lt;/p&gt;
&lt;p&gt;Many also include remote APIs to manipulate content, which raises the question of whether or not they fit the headless model? Content could easily be modeled and managed in something like SharePoint, then accessed externally through a headless layer like Akumina&amp;rsquo;s &lt;a href="http://www.akumina.com/products/interchange/devframework/"&gt;Interchange&lt;/a&gt;, on-demand and real-time.&lt;/p&gt;
&lt;p&gt;The idea of this, however, might make ECM people a little nervous. ECM systems have traditionally been treated as &amp;ldquo;behind the firewall&amp;rdquo; systems, and they&amp;rsquo;re not normally built or secured for high-volume performance like public web serving. Web publishing out of ECM has historically been decoupled.&lt;/p&gt;
&lt;p&gt;An argument could be made that you should put a public caching layer in front of this, which would fit the same model as something like Contentful that pushes to a global CDN, or some of the headless Drupal architectures we&amp;rsquo;ve seen which push content into an intermediate datasource (my experience was with Drupal pushing to &lt;a href="https://en.wikipedia.org/wiki/MongoDB"&gt;Mongo&lt;/a&gt;, then that being pulled by a Rails app).&lt;/p&gt;
&lt;p&gt;But does this blur the definition even further? If your back-end &amp;ldquo;headless&amp;rdquo; system is pushing into an intermediate layer (like you would do with ECM), then are we still headless, or are we really &lt;em&gt;decoupled&lt;/em&gt;?  Traditional decoupled systems have pushed HTML assets to the delivery environment, but pushing database records is not unheard of. I talked about that in &lt;a href="/tech/blog/decoupled-content-management-101/"&gt;an older article about decoupled CMS&lt;/a&gt; (still highly relevant to this subject) and I presented &lt;a href="/tech/blog/case-studies-of-cms-to-sql-decoupled-publishing/"&gt;a couple CMS-to-SQL case studies&lt;/a&gt; just a few weeks ago.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;All of these above might have brought us full-circle: &lt;em&gt;any datasource might be considered as a headless CMS&lt;/em&gt;, depending on (1) how much you&amp;rsquo;re willing to ignore any built-in presentation systems, and (2) to what extent you consider an intermediate caching layer as part of the system itself.&lt;/p&gt;
&lt;p&gt;Headless will remain a gray area, I think, defying strict boundaries. Systems will be &amp;ldquo;headless&amp;rdquo; to the extent that they fit the barest profile of that paradigm, can be re-purposed or modified to fit it, and the vendor markets them as such.&lt;/p&gt;
&lt;p&gt;One traditional CMS vendor I talked to in putting this post together says the market will hinge on whether or not pure headless vendors pursue a &lt;a href="https://en.wikipedia.org/wiki/Blue_Ocean_Strategy#Blue_ocean_vs._red_ocean"&gt;blue ocean or red ocean&lt;/a&gt; positioning strategy. Will they attempt to fight it out in the same market as traditional CMS (red ocean), or will they attempt to embrace their differentiation and create a new, open market to conquer (blue ocean).&lt;/p&gt;
&lt;p&gt;I suspect the latter is probably the wisest choice. But, I also know that a lot of vendors like a good old-fashioned street fight &amp;ndash; in the world of technology, it&amp;rsquo;s a sadly rare vendor who&amp;rsquo;s willing to admit that anyone else does something better than they do. The history of this industry is littered with vendors wading into markets in which they had no business being. Time will tell whether vendors do the same here.&lt;/p&gt;</description>
      <pubDate>Wed, 8 Feb 2017 00:00:00 -0600</pubDate>
      <guid isPermalink="true">https://live.deanebarker.net/tech/blog/state-of-the-headless-cms-market/</guid>
    </item>
  </channel>
</rss>