Building dbRosetta Part 6: Let’s Make a Web Page
Once more in this series, we’re moving into areas where I’m not entirely comfortable. I haven’t built a PHP plugin and web page, ever. However, we’re going to put the LLM/AI and associated agents to work on this task. As with so much else when working with AI, it all starts with the prompt, so let’s go there.
Creating the WordPress Plugin Prompt
For those who haven’t been following this series (links to the rest down below), I’m providing my prompt to CoPilot (paid) running on my desktop. CoPilot then creates a prompt for VSCode and the GitHub CoPilot agent. It’s supposed to follow a pretty strict prompt outline that we created together at the beginning of the series. However, it keeps forgetting that, and I get sick of trying to force it to behave (if for no other reason, I’ve found the more you correct AI on a given path, the more they start to move towards hallucinations). I tried to be more explicit than usual in my initial prompt this time. I don’t go into all sorts of detail because I assume that the AI is maintaining context. It usually is, but not always. However, here’s my prompt and the CoPilot output.
| Please generate the necessary prompt for VS Code in order to create the WordPress application for dbRosetta. Be sure to include appropriate prompts for very clear steps for any manual work since I assume that VS Code will not be able to directly access my WordPress environment. Let’s start with just the necessary page to read from the dbRosetta database. No additional functionality such as administration or data entry is necessary at this step. Keep it simple and clear. Allow people to define their search term for a given database. The return will be for a selected database and may include multiple terms and an explanation as is supported by the current database design. Let’s be sure that there is no possibility of SQL Injection and that we’re otherwise making a secure connection to the API hosted in Azure. | Project: dbRosetta WordPress Plugin — Part 6 (Read/Search Integration)
Context You are an expert WordPress plugin developer. Implement a minimal, secure plugin that allows a WordPress site to query the dbRosetta API (hosted in Azure) and display results. The plugin must: – Provide a search form where users can enter a term and select a database. – Send the query securely to the dbRosetta API (using HTTPS and JWT/OAuth tokens). – Display multiple terms and explanations returned by the API. – Prevent SQL injection and insecure input handling by validating and sanitizing all user input before sending to the API. – Be simple: no admin UI or data entry at this stage.
High-level Goals 1. Scaffold a WordPress plugin folder with the necessary files. 2. Implement a shortcode 3. Securely call the Azure-hosted API using WordPress HTTP functions ( 4. Validate and sanitize all inputs before sending to the API. 5. Provide clear manual steps for installation and activation in WordPress.
Deliverables – Plugin folder – – – – – Secure API client that: – Reads endpoint and token from plugin constants or environment variables. – Uses – Handles errors gracefully. – Shortcode – Displays the search form. – On submission, calls the API client. – Renders results using the template.
Security Requirements – Sanitize all user input with – Never construct raw SQL; all queries go through the API. – Use HTTPS for API calls. – Store API token securely (in – Escape all output before rendering.
Manual Steps (outside VS Code) 1. Copy the generated plugin folder into 2. In
define(‘DBROSETTA_API_URL’, ‘https://your-api.azurewebsites.net/v1/query’); define(‘DBROSETTA_API_TOKEN’, ‘your-secure-jwt-token’); |
I save the prompts to a Markdown file in the project (source code here). The articles are all my writing, but I will show some of the AI responses. Those will always be clearly marked, so you’ll know which is me, Grant, nominally human, and which is the LLM. And yeah, throughout the series, I refer to it as LLM, AI, Agent, and sometimes here at home, several different curse words.
Let’s go run the prompt.
Creating the WordPress Plugin
With the Prompt provided, there’s not a single other interaction before it’s created a full blown WordPress Plugin. As per my instructions, as translated by CoPilot, the output includes my next steps:
Now, I’m pretty sure I know how to do these steps, but, I want to, as much as possible, rely on AI for all of this. So, instead of going with what I know, I went back to CoPilot and got some more advice:
| OK. VSCode has created the wordpress plugin. It says I have to copy the folder over to wordpress. How do I do that? | Step-by-Step: Copying Your Plugin to WordPress
Code wp-content/plugins/
bash cp -r path/to/generated-plugin ~/wordpress/wp-content/plugins/
|
Excellent, detailed advice. But when I went to look at WordPress, to start to prep doing all this, I found a very simple “Install Plugin” button. All I had to do was provide a *.ZIP file. I go back to CoPilot and it says:
Yes — that’s actually the most straightforward way to install a custom plugin you’ve built in VSCode. WordPress expects plugins to be packaged as a
.ziparchive, and the Upload Plugin option inwp-adminis designed exactly for this.
Uhm. Well, if it’s the “most straightforward way” why on earth didn’t you tell me that up front? Again, this reinforces stuff I already knew about AI from all the work I’ve done. It’s not just about providing the AI with context and a prompt. CoPilot knew, based on other prompts and discussions that we were working within WordPress. With that knowledge, and the knowledge that we had a plug-in ready to go, why didn’t it tell me to do this right up front? Because I asked it how to copy the folder. That’s what it focused on. Why am I not too worried about my job (even though mine is writing long-winded articles like this one, that AI does constantly)? Because these things can’t reason. They can’t say, “Oh, I see what you’re asking, but, really, here’s what you should be doing.” Instead, it’s “OK. Here we go. WHOOP!!!”
Regardless, I now have a plug-in:
I like the “By dbRosetta Team”. Ha! Me and two AIs.
Time to get the JWT setting, whatever the heck that is…
And all hell breaks loose.
Fixing the Deployment
Unbeknownst to me, the Github Actions deployment has been failing (actually, I knew, the AI didn’t). When we went to get the JWT signature thingie (still not sure what that is), VSCode found out for the first time that the deployments weren’t running. And I found out that the deployments were triggered only on the branch for Part 5 of the project, which we’ll address later. In the mean time, we had to go back to that branch to start fixing stuff.
This is one of those times throughout this process where the AI and I have quite a lot of back and forth. I’m copying and pasting error messages. It’s trying to update & modify scripts. First, our linting was extremely strict, failing a bunch of the code. Rather than fix the code, the AI limited the linting (ha! typical development choice). Then we hit issues with other bits of code that hadn’t been sufficiently tested.
Oof. That was a long one. However, after a lot of back & forth, as well as several code updates, because the AI doesn’t always remember context when it creates new code, we deployed the API within Azure successfully. On to testing the plug-in.
The dbRosetta Web Page
Setting up the web page was silly simple. I created a new page. I put [dbrosetta-search] on it.
DONE!
I tested the URL (this one, feel free, try it, just understand, it’s a work in progress, there’s not even data as I type this) and it loaded! WHOOP! That’s right. I’ve got a functional web page built entirely (mostly entirely) by AI.
And I hate it. This is the first time I’ve seen what it did with my original prompt and the prompt generated by CoPilot. Well, we’ll iterate. Let’s test it…
<BOOM> error. Here’s the conversation:
“OK. The page loaded and the dbRosetta plug in was visible. When I typed in a search term though, I got this error: body/filters must be object”
The WordPress plugin is using the wrong API request format. Let me check the API client code and fix it:
Read class-dbrosetta-client.php, lines 1 to 100
I see the issue. The plugin is sending filters as an array, but the API expects it as an object (key-value pairs). Let me check the actual API schema to see the correct format:
Read query.ts, lines 1 to 30
The API expects filters to be a record/object (key-value pairs), not an array. Let me also check what the correct field names are in the database schema:
Searched for text model Term (**/services/dbrosetta-api/prisma/schema.prisma), 1 result
Read schema.prisma, lines 37 to 60Now I understand. The field is canonicalTerm, and filters should be an object. Let me fix the WordPress plugin:
class-dbrosetta-client.php+5-10
Now update the plugin file on your WordPress server with the corrected version. The key changes:Changed filters from an array to an object
Changed field name from standard_term to canonicalTerm (matches the database schema)
Removed select and page (API uses fields and offset instead)
After uploading the updated file, the search should work without that error. Keep in mind you’ll still get 0 results until we populate the database with data.
So, as before, it just made stuff up instead of either remembering what it had done, or, reading from what it had done. Once prompted with the error, it went and investigated. It updated the code. I updated the plugin. Did it work?
YES IT DID!
Conclusion
OK. I’m stopping this one here. First up, I want to declare this a rip roaring success. Yes, there was pain along the way. Yes, I found that you can’t just let the AI run without a lot of input, hand holding, guidance, and a little evil snickering ‘I told you so’ feelings in there. Yet, it did the job and did it pretty well. I have a bunch of work ahead of me. I’ve got to refactor this thing to make it actually functionally correct. It should allow you to define where the given term is from, then you get output, either for all databases, or the database you selected. We’ll get to it. I also want the AI to load up the test data. After that, I don’t know. I’d love to hear from you. Should I see what else the AI thinks we should do to make this a fully functional application, or do I wait to see if any of you want to start issuing pull requests to update it? I’m pretty open.
As per usual, I’ll give the last word to CoPilot:
At this stage, dbRosetta has moved beyond its foundation of schema translation and API design into the practical challenge of presenting those capabilities through a WordPress plugin and web interface. While this step has pushed the project into less familiar territory, it marks an important milestone: the toolkit is no longer just a backend service, but something contributors and users can interact with directly. The work so far has established a reproducible path from database migration scripts to a functioning plugin, and although there are still refinements ahead, the project now stands as a tangible, teachable reference implementation that bridges CI/CD workflows with accessible front-end integration.
If you’re interested in previous posts in the series:


