Skip to content

In short: it’s increasingly common for a client who is comfortable working with AI to want to publish, on their own, pages built with HTML, CSS and JavaScript generated by artificial intelligence, not just plain text. The temptation is to hand them a box to paste the code into and call it done. But the real work isn’t generating that code: AI does it in seconds. The real work is building the container that hosts it without putting the site at risk. In this piece we explain how we do it: a dedicated template, the generation rules written inside the field itself, a disclaimer for visitors, and an automatic expiry that drags along consequences almost nobody sees coming.

A while ago we faced a request that today comes up with some regularity. A client comfortable working with AI wanted to publish, independently, time-limited pages: promotions, announcements, content tied to a date that becomes useless once that date has passed. Nothing strange so far. The novelty was the how: those pages were to be generated with AI, asking a model to produce the whole block of markup, styles and any interactivity, then uploading it to the site without going through us every time.

It’s a legitimate request, and in many cases a sensible one. But between “I have the code ready” and “the code is online and doing no harm” there’s a distance that the enthusiasm for AI tends to hide. That distance is exactly our job.

The real problem isn’t generating, it’s hosting

Almost all the public conversation about AI applied to websites looks at the moment of generation: which tool to use, how good it is, how much code it can produce. It’s the visible, spectacular part. But it’s also the part that, by now, takes the least effort of all.

WordPress was built to manage textual content: posts, pages, structured fields. It wasn’t designed to take a block of arbitrary HTML, CSS and JavaScript and inject it into production as-is. The moment you accept complete code from an external source, the right questions become different ones. Where do I print it, within the page structure? How do I make sure the styles and scripts don’t clash with the rest of the site? And above all: what happens to that page when it’s no longer needed? These are questions of architecture, not of generation. AI neither asks nor answers them. We do, before the code ever touches the server.

A dedicated template, not a textarea in the content

The first decision is the most important: isolate. Instead of letting the generated code end up in the body of any old page, mixed in with the other content, we give it a page template all of its own. A page that uses that template behaves differently from all the others, and this lets us control every aspect of it.

On that template we set up three separate fields, one for each of the three things AI produces: the markup, the styles, the JavaScript. It’s not an aesthetic choice. The three pieces need to be printed in three different points of the document to work correctly. The CSS goes in the page head, before the browser starts drawing, so the styles are already in place when the content appears. The markup goes in the body. The JavaScript goes at the bottom, right before the page closes, when the content it needs to attach to already exists in the document. Keeping the three fields separate means being able to place each one where it belongs, instead of receiving a single confused block in which styles and scripts are drowned inside the HTML.

On the same template we also handle a seemingly minor but useful detail: for these pages, often conceived as standalone landings, we allow either the full site header or a reduced version with just the logo, depending on whether the page should live inside the site’s navigation or work as the isolated landing spot of a campaign. The footer stays unchanged, because that’s where information that’s always needed lives. All of this work rests on WordPress and on our Flying infrastructure, the custom theme we build our clients’ sites with.

The generation contract: the rules live inside the field

Here’s the point you rarely find written down anywhere. If you give someone three empty boxes to paste AI-generated code into, you’ll get code that doesn’t line up: CSS classes that match no element, scripts hunting for selectors that don’t exist, stray opening and closing tags. Not because the AI is bad, but because nobody told it what context that code was going to live in.

That’s why we wrote the generation instructions inside the help text of each field. Whoever produces the code finds, right where they need it, the reminder of what to ask the model: generate only the markup that goes inside the page body, with no document or head tags; keep styles and scripts out of the HTML, in their dedicated fields; use the same class and identifier names across all three fields, because they have to match one to one; write the JavaScript knowing it will run when the content is already present, so there’s no need to wrap it in document-loading waits. And, cutting across all of it, the rule that matters most of all: the three fields must be generated as a single, coherent package in the same request, not in three separate conversations, otherwise the selectors don’t talk to each other.

The field, in short, isn’t an empty box. It’s an interface that teaches how it’s meant to be used. It’s the same principle we design our clients’ management panels with: giving autonomy without giving up control, a balance we think about often, for example when we choose the tools that let the client manage their own forms without breaking anything.

What “printed without sanitisation” really means

Now we get to the part that overturns the common intuition. That code is printed on the page as-is, with no automatic filters cleaning it up. In jargon it’s called “without sanitisation,” and the instinctive reaction is to think it’s carelessness. It’s the opposite: it’s a deliberate choice, possible only because the code comes from a client we trust, and it’s their code. But precisely because there’s no filter, the only real barrier becomes human review before saving. And here’s a delicate point: knowing how to use AI well and knowing how to verify the code AI produces are not the same skill. Being comfortable with the prompt doesn’t guarantee a critical eye on the output, and that’s exactly why the review can’t stay an implicit gesture, taken for granted. You need a written, explicit check, with a list of things to verify at a glance: no calls to external scripts or domains that weren’t requested, no obfuscated or unreadable code, no functions that execute strings as if they were commands, no credentials or keys left in the code, no collection of user data that wasn’t declared. “Without sanitisation” does not mean “without rules.” It means moving the rule from the code to the person, and setting it down in black and white so nobody forgets it. Anyone who wants to understand why this matters can start with the MDN documentation on cross-site scripting, which explains well what arbitrary code can do in the wrong hands.

There’s then a second direction to transparency, one that looks not at whoever writes but at whoever reads. On these pages we show a disclaimer warning visitors that the content was generated with AI. We manage it with a two-level mechanism: a single text, defined once at site level and available in every language, and a per-page switch, on by default. The disclaimer appears only if both conditions are true, which gives us a cautious default behaviour (it tends to show) but the freedom to turn it off where it makes no sense. It isn’t only courtesy toward the reader: in some cases it’s also a legal obligation, and that’s the subject of the next section.

The EU AI Act and the obligation to disclose generated content

Since 2 August 2026, the AI Act article on transparency applies, and in some cases it requires disclosing when content has been generated by AI. It’s worth understanding the boundaries of this obligation, because it’s narrower than the headline suggests, yet it closely concerns anyone publishing pages like the ones we’re discussing.

The obligation isn’t universal. According to the European Commission’s guidance, labelling AI-generated text concerns content published to inform the public on matters of public interest: topics such as politics, health, the environment, consumer safety, or economic and scientific developments relevant to public debate. A time-limited promotional landing, as a rule, doesn’t fall into this category; a page informing the public on a matter of collective interest, on the other hand, does. It’s a distinction that depends on the purpose of the content, not on the fact that it was generated with AI, and it’s the first thing to assess case by case.

There’s then an exception that concerns us directly. The obligation doesn’t apply when the content has gone through substantial human review or editorial control, with a person holding responsibility for it. And the rule is explicit about what counts as review: superficial or purely formal checks, like a spell-check, aren’t enough. It takes a genuine examination of the substance of the content, by someone with the competence to judge it. That’s exactly the fence we’ve described so far: the security checklist and the human review before publication are the substantial review the legislator is talking about. In other words, the scaffolding we’d built to avoid breaking the site is also what determines which side of the obligation the page falls on.

Two useful clarifications before closing the topic. Content generated before 2 August 2026 doesn’t need to be labelled retroactively. And there’s a difference between the obligations of whoever provides the model (the technical, machine-readable marking of the output) and those of whoever publishes the content (the label visible to the reader): in this scenario you and your client are in the second category. That said, we keep the disclaimer on by default regardless, because transparency toward visitors is a choice before it’s a compliance measure. One last note of honesty, which holds as always: we aren’t lawyers, and the specific case should be verified with the right people. Here we care about the principle, not legal advice.

Behind the scenes: expiry and its domino effect

The function that at first glance seems the most trivial is the one that best tells how we think. Many of these pages have a life with an end date: a promotion that finishes, an event that passes. So we needed to be able to tell a page “from this date you no longer exist,” and send whoever lands on it elsewhere.

The solution is a redirect handled server-side, hooked to the moment WordPress decides which template to use, that is, before any portion of the page is produced. If the page has expired, whoever requests it is sent to a destination chosen at configuration time, with a temporary redirect (the 302 code, the one that tells browsers and search engines “this resource is elsewhere for now,” without deleting it permanently). The expiry boundary is precise: it kicks in from midnight of the given day.

And here comes the domino effect nobody sees coming at first. A page that changes behaviour based on the date sits badly with full-page caching, that is, the system that, to go faster, freezes a static version of the page and serves it to everyone. If that frozen copy is saved before the expiry midnight, the site would keep showing the page even when it should be redirecting. So expiry, on its own, forces two more decisions on us: excluding these pages from full-page caching, and scheduling any cache clearing in a way that’s consistent with the midnight boundary, a few minutes after the date ticks over. A seemingly simple function drags along two more. It’s the kind of chain reasoning that separates a page that works by chance from one that works every time, and it sits at the heart of how we treat a site’s life after it goes live.


A real limitation: trust isn’t a function

It has to be said clearly, because being honest about limitations is part of how we work. All this scaffolding doesn’t eliminate the risk. It shifts it and makes it manageable, but it doesn’t zero it out. If the client pastes wrong or harmful code and skips the checklist, the site will run it anyway, because it’s built precisely not to filter anything.

This approach only makes sense with clients we trust, and it’s worth saying honestly how delicate the matter is: as we’ve seen, knowing how to use AI doesn’t coincide with knowing how to read and judge the code it produces. Trust, in this scheme, isn’t a function we can program: it’s a premise, and it has to be calibrated on the individual client and their real ability to validate what they publish. We prefer to say it, rather than pretend the template is foolproof. For projects where that trust isn’t there, or where the risk isn’t acceptable, the right answer is different: a tighter watch, where the code goes through us, inside a WordPress maintenance and security service that takes responsibility for it.

Where to start

Isolate the AI-generated code in a dedicated template, with separate fields for markup, styles and scripts. Don’t let it end up in the content of any old page: that separation is what lets you control where and how each piece runs.

Write the generation rules inside the interface itself, not in a separate document nobody will open. The field has to tell whoever uses it what to ask the AI, so the code that arrives is already compatible with the context it’ll live in.

Decide who validates before publication, and with what checklist. If the code enters without automatic filters, the human eye is the only barrier: make it explicit, don’t leave it to the good sense of the moment. And check that whoever publishes can genuinely read the code, not just generate it: those are two different skills.

Declare to visitors that the content is AI-generated, both for transparency and because in certain cases European regulation requires it. A switch on by default is the simplest way not to forget.

Think about the page’s life cycle before putting it online: when it expires, where it redirects, how the cache behaves. These are the questions AI doesn’t ask you, and they make the difference between a page that holds and one that breaks silently.

If you need a hand

If you’re weighing up how to give your clients, or yourself, the freedom to publish AI-generated content inside WordPress without turning the site into a minefield, we can talk it through. At PaperPlane we offer a free thirty-minute consultation where we look at your case together: what kind of pages you need, who’ll produce them, which controls make sense to put in the middle. Without selling a pre-packaged solution: what we care about is figuring out whether this approach is the right one for you, or whether you need a different one.