refactor: Reimplement calculator logic with new JavaScript and PHP files, removing numerous old Python scripts and related content.
This commit is contained in:
215
agents/readme.md
215
agents/readme.md
@@ -1,81 +1,158 @@
|
||||
# How Do You Convert - Agents Documentation
|
||||
# How Do You Convert - AI Agent SOP
|
||||
|
||||
This document explicitly defines the schema, architecture, and standard operating procedure for creating new calculators on `howdoyouconvert.com`.
|
||||
This document defines the standard operating procedure (SOP) for AI agents creating or updating calculators on `howdoyouconvert.com`. Adherence to these steps ensures high code quality, mathematical accuracy, and SEO compliance.
|
||||
|
||||
## 1. WordPress Environment Structure
|
||||
The calculators are managed using the custom post type `calculator`. The REST API endpoint allows full CRUD operations:
|
||||
- **Base Endpoint**: `/wp-json/wp/v2/calculator`
|
||||
- Authentication is handled via Application Passwords `base64(username:password)` utilizing Basic Auth via HTTP Headers.
|
||||
- *Crucial Node*: API requests to this endpoint must emulate browser requests via the `User-Agent` string (e.g., `Mozilla/5.0...`) or they will be blocked by Cloudflare (error 1010).
|
||||
---
|
||||
|
||||
## 2. Calculator Data Payload (HTML)
|
||||
Calculators should use Kadence Block layout components to match the pre-existing grid on the site. Each calculator contains 2 main columns for bidirectional conversion.
|
||||
All calculators *MUST* include the classes `calc-input` and `calc-field` on their `<input type="number">` tags, and unique IDs across the form (e.g. `input-1`, `input-2`). The UI should contain explicit labels.
|
||||
## 1. Environment & Authentication
|
||||
- **Endpoint (Posts)**: `/wp-json/wp/v2/calculator` (Custom Post Type).
|
||||
- **Endpoint (Logic)**: `/wp-json/wp/v2/kadence_element` (Kadence Elements CPT).
|
||||
- **Authentication**: Basic Auth via headers: `Authorization: Basic base64(user:pass)`.
|
||||
- **User-Agent**: **CRITICAL**. You must emulate a modern browser (e.g., `Mozilla/5.0...`) or Cloudflare will block the request (Error 1010).
|
||||
|
||||
**Example JSON Payload Configuration:**
|
||||
```json
|
||||
{
|
||||
"title": "Unit A to Unit B",
|
||||
"status": "publish",
|
||||
"slug": "unita-to-unitb",
|
||||
"content": "<!-- Standard Kadence 2-Column Row Block -> Column 1 (Label + Input) -> Column 2 (Label + Input) -> SEO Text Block -->"
|
||||
}
|
||||
---
|
||||
|
||||
## 2. Two-Part Architecture
|
||||
|
||||
Every calculator consists of **two separate WordPress objects** that work together:
|
||||
|
||||
### Part A: The Calculator Post (`calculator` CPT)
|
||||
Contains the **HTML layout** (inputs, labels, Kadence Row/Column blocks) and the **SEO text**. This is what the user sees as the page content.
|
||||
|
||||
> [!CAUTION]
|
||||
> **WordPress strips `<script>` tags from post content.** You CANNOT put JavaScript logic inside the calculator post. It will be silently removed on save. This is a core WordPress security behavior.
|
||||
|
||||
### Part B: The Logic Element (`kadence_element` CPT)
|
||||
Contains the **JavaScript logic** wrapped in `<script>` tags. This is a separate post of type `kadence_element` that Kadence injects into the page at render time, based on conditional targeting rules stored in its metadata.
|
||||
|
||||
### How They Connect
|
||||
The Kadence Element's metadata tells WordPress *when* and *where* to inject the script:
|
||||
|
||||
| Meta Key | Value | Purpose |
|
||||
| :--- | :--- | :--- |
|
||||
| `_kad_element_hook` | `kadence_after_header` | Injection point in the page template. |
|
||||
| `_kad_element_show_conditionals` | `[{"rule":"singular\|calculator","select":"ids","ids":[POST_ID],"mustMatch":false}]` | Targets the element to only load on the specific calculator post. |
|
||||
|
||||
---
|
||||
|
||||
## 3. Post Creation & Duplicate Prevention
|
||||
**Rule**: Never create duplicate posts. WordPress will append `-2` to the slug, breaking the link structure.
|
||||
1. **Search**: Always GET the intended slug (e.g., `?slug=meters-to-feet`) before creating.
|
||||
2. **Resolution**:
|
||||
- If response is empty: `POST` new.
|
||||
- If post exists: `PUT` to update the existing ID.
|
||||
3. **Registry**: Immediately update `calculators_list.md` with Title, Post ID, and Kadence Element ID.
|
||||
|
||||
---
|
||||
|
||||
## 4. SEO Content Standards
|
||||
All calculators must meet these three non-negotiable standards:
|
||||
1. **Teaser Optimization**: Every post must begin with a 1-sentence summary followed by the `<!-- more -->` tag. This ensures category grids stay clean.
|
||||
- *Example*: `<p><strong>Unit A to Unit B</strong>: Technical specs, symbols, and history. <!-- more --></p>`
|
||||
2. **Encyclopedic Tone**: Content must be strictly informative and **non-self-referential**. Do not mention "this calculator," "our tool," or "enter your value." Focus on history, SI definitions, and industrial use.
|
||||
3. **Length**: At least 3 detailed paragraphs are required for SEO depth.
|
||||
4. **Forbidden Words**: Never use: *tool, calculator, widget, button, click, enter, below, our, this page.*
|
||||
|
||||
---
|
||||
|
||||
## 5. JavaScript Architecture (Self-Polling)
|
||||
|
||||
The JavaScript logic lives in the **Kadence Element** (Part B), NOT in the calculator post content. The "Self-Polling" pattern is mandatory to overcome caching and race conditions:
|
||||
|
||||
```javascript
|
||||
<script>
|
||||
(function() {
|
||||
function init() {
|
||||
const in1 = document.getElementById('input-1');
|
||||
const in2 = document.getElementById('input-2');
|
||||
if (!in1 || !in2) {
|
||||
setTimeout(init, 100); // Poll until DOM is ready
|
||||
return;
|
||||
}
|
||||
|
||||
let cf = 3.2808399; // conversion factor
|
||||
|
||||
function solve(source) {
|
||||
let v1 = parseFloat(in1.value);
|
||||
let v2 = parseFloat(in2.value);
|
||||
if (source === 1) {
|
||||
if (!isNaN(v1)) in2.value = parseFloat((v1 * cf).toFixed(6));
|
||||
else in2.value = '';
|
||||
} else {
|
||||
if (!isNaN(v2)) in1.value = parseFloat((v2 / cf).toFixed(6));
|
||||
else in1.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
in1.addEventListener('input', () => solve(1));
|
||||
in2.addEventListener('input', () => solve(2));
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.has('v1')) { in1.value = urlParams.get('v1'); solve(1); }
|
||||
else if (urlParams.has('v2')) { in2.value = urlParams.get('v2'); solve(2); }
|
||||
}
|
||||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
|
||||
else init();
|
||||
})();
|
||||
</script>
|
||||
```
|
||||
|
||||
### 2.2. Slug Mismatch & Duplicate Prevention
|
||||
**CRITICAL**: Do not create a new post if the calculator already exists. WordPress will automatically append `-2` to the slug (e.g., `inches-to-millimeters-2`).
|
||||
- **Detection**: Always perform a GET request for the intended slug before POSTing.
|
||||
- **Resolution**: If a duplicate is found, capture the existing `id` and use `PUT` to update the content rather than creating a new entry.
|
||||
- **Registry**: Ensure the `Id` in `calculators_list.md` matches the post serving the "clean" slug (no `-2`).
|
||||
|
||||
### 2.1. SEO Copy Guidelines
|
||||
The SEO block appended at the end of the calculator `content` must strictly adhere to the following style:
|
||||
- **Length**: Expand the text to 2-3 detailed paragraphs providing educational information on the units involved, their history, uses, and the conversion methodologies.
|
||||
- **Tone**: The text must be strictly informative and **non-self-referential**. Do not refer to the calculator widget itself. Sentences like "This handy calculator automatically converts values as you type" or "Enter your value below" are explicitly prohibited.
|
||||
|
||||
## 3. JavaScript Event Injection
|
||||
The JavaScript that performs the actual mathematical conversion is *detached* from the calculator post itself. It is managed via the **Kadence Elements** system (`kadence_element` custom post type).
|
||||
|
||||
### Creating the Logic Hook
|
||||
Whenever a new calculator is created:
|
||||
1. Capture the returned `id` of the published calculator.
|
||||
2. Formulate the JS math conversion script wrapping events to the unique input IDs.
|
||||
init();
|
||||
})();
|
||||
</script>
|
||||
```
|
||||
|
||||
### 3.1. 3-Variable Solver Pattern (e.g., Ohm's Law)
|
||||
For calculators with 3 inputs (A, B, C where A * B = C), use the "solve" function pattern to ensure reactivity:
|
||||
```javascript
|
||||
function solve(lastId) {
|
||||
let av = parseFloat(a.value), vv = parseFloat(v.value), wv = parseFloat(w.value);
|
||||
if (lastId === '1' || lastId === '2') {
|
||||
if (!isNaN(av) && !isNaN(vv)) w.value = parseFloat((av * vv).toFixed(3));
|
||||
} else if (lastId === '3') {
|
||||
if (!isNaN(wv)) {
|
||||
if (!isNaN(av) && av !== 0) v.value = parseFloat((wv / av).toFixed(2));
|
||||
else if (!isNaN(vv) && vv !== 0) a.value = parseFloat((wv / vv).toFixed(2));
|
||||
}
|
||||
### Creating the Logic Element via API
|
||||
```python
|
||||
js_data = {
|
||||
"title": f"JS Logic: {title}",
|
||||
"content": js_code, # The <script>...</script> block above
|
||||
"status": "publish",
|
||||
"meta": {
|
||||
"_kad_element_hook": "kadence_after_header",
|
||||
"_kad_element_show_conditionals": f'[{{"rule":"singular|calculator","select":"ids","ids":[{post_id}],"mustMatch":false}}]'
|
||||
}
|
||||
}
|
||||
a.oninput = () => solve('1'); v.oninput = () => solve('2'); w.oninput = () => solve('3');
|
||||
# POST to /wp-json/wp/v2/kadence_element
|
||||
```
|
||||
4. **URL Parameter Support:** Ensure the script parses `window.location.search` for `?v1=` (Input 1) and `?v2=` (Input 2).
|
||||
5. Submit a new `kadence_element` POST request injecting the `<script>...</script>`.
|
||||
6. Apply these required metadata values:
|
||||
- `_kad_element_hook`: `kadence_after_header`
|
||||
- `_kad_element_show_conditionals`: `'[{"rule":"singular|calculator","select":"ids","ids":[<CALCULATOR_POST_ID>],"mustMatch":false}]'`
|
||||
|
||||
## 4. Required Mathematical Verification
|
||||
After the Kadence Element is injected and the calculator is live, **you must verify the math works in both directions** using the live WordPress post.
|
||||
1. Determine a known "Unit A to Unit B" conversion (e.g., 1 inch = 2.54 cm).
|
||||
2. Execute an HTTP/URL request simulating the Unit A input (e.g., `?v1=1`) and verify the output accurately reflects Unit B.
|
||||
3. Reverse the test: simulate the Unit B input (e.g., `?v2=2.54`) and verify the output accurately reflects Unit A.
|
||||
4. If either math direction fails or produces precision floating-point inaccuracies, you must correct the Kadence Element JavaScript block.
|
||||
5. **Live Logic Audit**: View the page source and search for `<!-- [element-ID] -->`. Ensure the ID matches the one in the registry and contains the robust `init` pattern.
|
||||
---
|
||||
|
||||
## 4. Calculator Registry
|
||||
To avoid unnecessary scraping of the REST API, immediately update the `calculators_list.md` file located in the workspace directory with the details (Title, Post ID, Kadence Element ID) upon successful deployment.
|
||||
## 6. Infrastructure Warnings
|
||||
|
||||
*By adhering to these steps, all calculators will natively match the design and function gracefully without requiring direct plugin access.*
|
||||
> [!WARNING]
|
||||
> **Cloudflare Rocket Loader** is active on the site. It rewrites `<script>` tags by changing their `type` attribute (e.g., to `46a62f613affa4914fc4953c-text/javascript`) to defer execution. This means `grep "function init"` on `curl` output will **fail** because scripts are rewritten. Do not rely on `curl | grep` to verify script presence.
|
||||
|
||||
> [!WARNING]
|
||||
> **Autoptimize** is active and bundles/minifies JavaScript. Individual `<script>` blocks from Kadence Elements may be merged into a single `.js` file. This further complicates source-level verification via `curl`.
|
||||
|
||||
> [!WARNING]
|
||||
> **Content Security Policy (CSP)** is enforced via Cloudflare with `strict-dynamic` and nonce-based policies. Inline scripts that are NOT injected through a trusted WordPress pipeline (like `wp_enqueue_script` or Kadence Elements) may be blocked. The CSP warnings in console are expected for third-party scripts but should not affect Kadence-injected logic.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Cloudflare Super Page Cache** aggressively caches pages. After updating a post or element via the API, the cached version may persist. Cache-busting query parameters (e.g., `?v=123`) may not work. The user may need to purge the cache from the Cloudflare dashboard or the WP admin panel for changes to appear immediately.
|
||||
|
||||
---
|
||||
|
||||
## 7. What NOT to Do
|
||||
|
||||
> [!CAUTION]
|
||||
> **Never modify the architecture.** The two-part model (Post + Kadence Element) is the established pattern. Do NOT attempt to:
|
||||
> - Embed `<script>` tags directly in the calculator post content (WordPress strips them).
|
||||
> - Create external `.js` files and enqueue them via a custom plugin (violates the self-contained protocol).
|
||||
> - Wrap post content in custom `<div>` containers with `data-` attributes for use by an external script (this adds unnecessary complexity and breaks when the external script isn't loaded).
|
||||
> - Deactivate (set to `draft`) Kadence Elements without providing an alternative logic source. This will immediately break every affected calculator.
|
||||
|
||||
---
|
||||
|
||||
## 8. Verification Protocol
|
||||
A deployment is not "complete" until it is mathematically and visually verified.
|
||||
1. **Bidirectional Math**: Verify both directions (A→B and B→A) using specific test values (e.g., 25.4 for inches to mm).
|
||||
2. **API Content Audit**: Use the REST API (`?context=edit`) to confirm the raw `content` of both the calculator post AND its Kadence Element. Do NOT rely on `curl` of the live page due to Rocket Loader and Autoptimize rewriting (see Section 6).
|
||||
3. **Element Status Check**: Confirm the Kadence Element's `status` is `publish` and its `_kad_element_show_conditionals` correctly targets the calculator post ID.
|
||||
4. **Keyword Audit**: Screen generated text for forbidden words (see Section 4).
|
||||
|
||||
---
|
||||
|
||||
## 9. Registry Maintenance
|
||||
Maintain `calculators_list.md` as the source of truth for all active units. Each row must contain:
|
||||
|
||||
| Title | Post ID | Kadence Element ID | Slug |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
|
||||
If you encounter a duplicate post ID, resolve the conflict and update the registry to point to the cleanest slug.
|
||||
|
||||
Reference in New Issue
Block a user