Edward Daniel Narkiewicz on Why AI Gets USWDS Right but Drupal Wrong
Coding agents can produce valid HTML and still implement a U.S. Web Design System (USWDS) component incorrectly in Drupal. Edward Daniel Narkiewicz, engineering and DevSecOps lead at iCUBE Inc., encountered both structural markup errors and Drupal-specific implementation problems while experimenting with AI-assisted development. Even when agents generated plausible component markup, their outputs could overlook functionality distributed across themes, Paragraph bundles, Twig templates and other Drupal layers.
To address that gap, Edward developed two connected open-source repositories: USWDS AI Components, which provides structured design guidance, and Drupal USWDS AI Components, which documents Drupal implementation options. Speaking with Kazima Abbas, sub-editor of The DropTimes, he explains why the second registry builds on the first without prescribing a single Drupal implementation method.
Edward also discusses limits that remain unresolved. He has not tested the workflow end to end on a production Drupal installation, and keeping the implementation guidance current still depends on manual maintenance. He describes how an overly absolute instruction about the USWDS government banner entered the metadata and says he was updating it to reflect the more nuanced official USWDS documentation. The interview examines component selection, implementation choices, version and security checks, and the responsibility developers retain when using AI-generated code.
Whether your project’s workflow is production ready is something only you can measure, and this repo is built to make that cheap to find out.
TDT[1]: What concrete problem did you encounter when AI agents had access to USWDS design guidance but lacked Drupal-specific implementation knowledge, and why did you solve it with two separate registries rather than a single schema containing both layers?
Edward Daniel: Models are already trained pretty heavily on USWDS, as it is all public info, and the same for Drupal in general, so you would think there isn’t anything more they need to know. Despite this, I was getting a lot of structural tag and class hallucinations, and even when the HTML was clean, I still wasn’t getting the Drupal-specific results I wanted. In Drupal, the components and their behaviours can be distributed all over the place: the main theme, sub theme overrides, custom CSS, paragraphs, module overrides, SDC, etc. I ended up spending a lot of time making drupal-uswds-component-specific prompts to get the same type of changes I would have made manually by hand. These two USWDS-specific projects were really just an extension of that process. I initially found the forever-ai-components repo and liked the general idea of targeting AI agents with public structured metadata about each component. That way, you are being a grounded source of truth that will pull back the drift that happens when working through LLMs. The idea of being a public reference seemed very inline with USWDS itself. So I initially created only the uswds-ai-components registry, and it worked, but pointing an LLM towards those URLs only produced good standalone components. When I tried to generate Drupal implementations, I had the issues I mentioned, and so I played around with adding another layer with Drupal-specific instructions and built drupal-uswds-ai-components, which knows about and uses the first repo. In the grand scheme of things, it may end up being too many repos, but the goal was to keep each repo light and simple to integrate with Agents.
TDT[2]: When you create a Drupal implementation mapping for a USWDS component, what is your hierarchy of authoritative sources—USWDS documentation, Drupal.org project information, module or theme source code, maintainer guidance, or observed behaviour on an installed Drupal site? How do you resolve conflicts between them?
Edward Daniel: Authority is always USWDS documentation first for specification matching, then Drupal.org project information for implementation details, then module or theme source code as truth for what will actually render, then maintainer guidance from the issue queues and changelogs, with observed behaviour on a live Drupal site last. I wanted to make sure to acknowledge that in practical use we often deviate from the component specs, especially with Cards; everyone wants their own cards. So I have, in the metadata for the components, stored whether or not it deviates from the canon by using an origin label: “design-system” for canon markup from official docs, “live-site” for variants found in real in-use sites, and "extension" for classes in the USWDS namespace that don’t ship with the USWDS itself, like, someone creates usa-alert--no-collapse on their own. I want to capture that real-life usage pattern but let the LLM know it isn’t canon. The concept is that alterations and deviations are recorded and made available as facts to the LLM, which will be the decision maker.
TDT[3]: All 20 entries in the current Drupal component index are marked tier: "curated." What does “curated” mean operationally? Who reviews a mapping, what must be verified, and what evidence must exist before that label is applied?
Edward Daniel: Well, in reality, it is just me working on this, and the project doesn’t have wide adoption. I only label things as needs-review that I’m not quite sure about, but since all these components come from the specs directly or live sites, everything is currently labelled “curated”. Any component that made it through development, accessibility, and QA checks for a production government site counts as curated. In the future, there may be some other theoretically useful components that might be of interest that aren’t as standard and accepted, and there may need to be some distinction for that. Or there may be a tighter judgement on which variations get allowed if they get all crazy.
TDT[4]: Have you conducted end-to-end tests in which coding agents use these registries to implement components on actual Drupal installations? If so, what have those tests revealed about where the mappings succeed or fail? If not, which parts of the workflow should users currently regard as unvalidated?
Edward Daniel: No, I have not tested this end-to-end on a production Drupal installation. But, since I am most familiar with USA.gov, my non-published internal full-run tests are mostly focused on recreating that site. I have an angular-usagov-demo case in the example dir of the base repo for the uswds-ai-components project. That tells me the basics about what works when identifying components. For the drupal-uswds-ai-components repo, I scrape USA.gov and, from that HTML, ask for a rebuild of the site. I can compare it to the original. USA.gov has a public repo, so we can not only inspect the output HTML, but we can inspect the Drupal configuration as well. This has mostly found issues with how the Agents choose to implement behavioural contracts in the Drupal JS module, and composite complexity across different modules like twigTemplate, paragraphs, and uswds_paragraph_components. As long as the component is functional, passes accessibility/508 scans, and is readable in the code, I’m happy. Whenever I get in the mood to work on this more, I pick a random site and re-implement the site in USWDS Drupal.
TDT[5]: How will the registry detect and handle stale implementation guidance when Drupal core, contributed modules, themes, Twig templates, configuration schemas, Drush commands, or supported version ranges change? Do you envisage automated checks or CI alongside human maintenance?
Edward Daniel: This is a real issue. For the moment, staleness detection is manual. I have the design system pinned to an exact release, but implementation guidance will need to change with releases of Core, modules, theme, and USWDS updates. I have to manually check for updates now across these targets. CI automation is definitely called for in this situation, but I wouldn’t trust any LLM to update the code automatically, so the blocker is still my attention.
TDT[6]: Drupal now offers several approaches to implementing USWDS, including the uswds and uswds_base themes, Paragraph-based components, and SDC/UI Patterns implementations such as UI Suite USWDS. How do you decide which implementation path an agent should prefer, and where do Single Directory Components fit into the registry's current Paragraph/theme-region/Twig/field-type taxonomy?
Edward Daniel: I try to stay out of the implementation path choice as much as I can. The goal of the project was to start with the assumption that an Agent using this repo would be working in some project with whatever rules and restrictions they have, so just giving one implementation methodology wouldn’t be useful. I picked those things because I was personally familiar enough with them to judge whether or not generated output is reasonable in that context. I worked with Stephen Mustgrave for a long time and had many discussions about USWDS implementation patterns in Drupal while he was working on the paragraph components, SDC, BLB layout options, and other UI Suite stuff. So I’m aware that there is not a single favoured implementation. Personally, I believe Single Directory Components are the future, and I have tried to bake that into this project by including what I hope is a minimal set of usage instructions along those lines. But, the reality is that people don’t always do things the way I imagine, so I’ve also tried to keep the metadata helpful enough to allow an LLM to fill in the blanks for any implementation style it chooses. I don’t want to bloat the metadata up front, but also acknowledge that I could be doing more along these lines, and there is room for more. I want to expand to more implementation methodologies eventually.
TDT[7]: The registries describe the USWDS banner as required on all federal government websites—and the companion registry calls it “required by law”—while current USWDS documentation says most government sites should use it and identifies exceptions. How did that difference arise, and what safeguards should prevent nuanced upstream guidance from becoming an overly absolute instruction when translated for an AI agent?
Edward Daniel: This actually has a deeper history than just, oops. The original thought for this comes from IDEA, M-23-22, and earlier USWDS versions, which explicitly did mandate the banner. But the current USWDS docs have a more detailed and lenient explanation of when you should and shouldn’t. This discrepancy came about because one of the first things I had a major problem with in my setup was just basic component choice. I wanted to nudge the LLM into picking what I thought to be the correct component and created the use/avoid metadata params. Top-tier models usually choose components I agreed with, but I didn’t think the choices were very strong when using smaller local models like Gemma:e4b. So, I decided to add some heavy-handed hints to get the results I wanted. To get my page level looking correct on a generic page, I left that instruction in. This brings up a general issue I have struggled with in this project, how much metadata is enough, and how much is too much. Not only are LLMs all trained on the public USWDS docs and OMB docs, but they can always look them up, so trying to hardcode too much into the metadata can lead to this situation where the info is out of date. But that info may be sometimes necessary for the smaller models. I go back and forth on this, and different models results make me think there isn’t a universal correct answer. I am torn between brevity and hard-coded specificity, but am also putting in a commit now to update the banner hint and remove the “required” language because, yeah, that shouldn’t be there now.
TDT[8]: Your usage documentation envisages agents inspecting live Drupal configuration and potentially making changes through Drush or configuration import. What level of human review and what technical safeguards do you consider necessary before those instructions are applied to a real project?
Edward Daniel: This is more of a personal question, since my repo doesn’t really do much about this directly. The best it can do is to include some metadata hints about accessibility and security considerations, but this repo is informational and can’t enforce anything. The reality, though, for public sector work, is that developers are being paid to take responsibility for the full scope of their implementation. There should be Zero Trust, and that includes reviewing all code to ensure it is safe and functional. I would imagine, if some agent is using this repo to fire off a bunch of Drush commands it found, that they are running on an internal local development container or are filtering commands. That should happen early enough in the project’s Software Development Life Cycle for all the manual and automated scans and tests to run and for the QA team to catch any unintended side effects and verify safety. So here you go, better instructions for how to use responses generated by this repo:
- Contain Your Agent: Never be running on or against a production system
- Changes are Code: Every change uses auditable, repository-manageable files
- Rollback Plan: Don’t do anything you can’t roll back
- Review and Test: Stage all changes and run tests and scans before accepting
TDT[9]: The registry maps data visualisation to the Plotly.js Drupal module even though Plotly.js is not itself a USWDS implementation. What objective criteria determine when a non-USWDS Drupal tool belongs in the registry, how are alternatives represented, and how do you prevent a maintainer or organisational preference from becoming an agent's default recommendation?
Edward Daniel: Interesting find. First, to directly answer why Plotly: Utility. I wanted to open up the category of visualisation-based components, and I was familiar enough with the module as we had used it on projects before, and it is one of Mustgrave’s many adopted co-maintained projects, so I felt it was a fairly safe choice. This was my first attempt at including a non-Drupal or third-party tool into this. Originally, I wanted to try and see how well the Agents picked up on being able to deal with this scenario since it requires not only knowledge of a UI component, but also of two layers of dependencies, then requires cache management, config management, Drush commands, and touches on complex client-side loading order and rendering. It is perfect for a real full end-to-end test. On the topic of defaults, I don’t want any single implementation to be preferred, and the project is built around the concept of providing variant implementations and options in the first place. So the real answer is to grow the number of component variants available. Plotly.js, interestingly enough, has had some security vulnerabilities lately, and I needed to be able to handle that as well. Since the metadata doesn’t pin or recommend any specific versions, the Agent handling the component won’t be recommended to an older, insecure version. I’m doing that on purpose; the registry's job is to make the version fact-checkable, not to be the scanner itself. That step is better off handled by the Agent and with real security tools later in the SDLC.
TDT[10]: What evidence would you personally require before recommending this workflow for a production government Drupal project—independent review, reproducible agent tests, real-world deployments, accessibility testing, version-compatibility checks, measured failure rates, or something else?
Edward Daniel: I don’t think there is an absolute measure of whether this repo is or is not ready for production systems, because this repo doesn’t produce anything by itself; it only provides a curated context to downstream Agents, who control implementation. Results will depend on the LLM/Agent/Framework combinations, so pass/fail rates won’t transfer directly to your stack. What I can stand behind, and is production-ready, is the information layer: pinned USWDS releases, class conformance, ledgers of test failures and fixes. Whether your project’s workflow is production-ready is something only you can measure, and this repo is built to make that cheap to find out. So, basically, it is helpful now and will be even more so in the future as more versions and variations are added to the components.

