feat: Add calculator documentation and registry, and remove obsolete test and upload scripts.

This commit is contained in:
Ben
2026-02-20 23:42:07 -08:00
parent 17d46746be
commit e679e20912
5 changed files with 62 additions and 62 deletions

46
agents/readme.md Normal file
View File

@@ -0,0 +1,46 @@
# How Do You Convert - Agents Documentation
This document explicitly defines the schema, architecture, and standard operating procedure for creating new calculators on `howdoyouconvert.com`.
## 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.
**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.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.
3. **CRITICAL: URL Parameter Support:** Ensure the script listens to the DOM `DOMContentLoaded` event and parses the `window.location.search` URL query parameters for `?v1=` (Input 1) and `?v2=` (Input 2). If present, the corresponding input must be automatically populated and the calculation function triggered.
4. Submit a new `kadence_element` POST request injecting the `<script>...</script>`.
5. Apply these required metadata values so it correctly loads on your specific calculator:
- `_kad_element_hook`: `kadence_after_header`
- `_kad_element_show_conditionals`: `'[{"rule":"singular|calculator","select":"ids","ids":[<CALCULATOR_POST_ID>],"mustMatch":false}]'`
## 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.
*By adhering to these steps, all calculators will natively match the design and function gracefully without requiring direct plugin access.*

6
calculators.md Normal file
View File

@@ -0,0 +1,6 @@
# Current Calculators on How Do You Convert
Here is a list of all current calculators available on the site:
1. **[Kilograms to Pounds](https://howdoyouconvert.com/calculator/kilograms-to-pounds/)**
2. **[Inches to Feet](https://howdoyouconvert.com/calculator/inches-to-feet/)**

10
calculators_list.md Normal file
View File

@@ -0,0 +1,10 @@
# Active Calculators Registry
This document lists all active calculators on `howdoyouconvert.com`.
Whenever a new calculator is published via the REST API, it must be appended here including its matching Javascript element ID.
| Calculator Name | Page Post ID | Kadence JS Element ID | Slug | Conversion Factor |
| :--- | :--- | :--- | :--- | :--- |
| Inches to Feet | 16 | 57 | inches-to-feet | 12 |
| Kilograms to Pounds | 54 | 28 | kilograms-to-pounds | 0.453592 |
| Miles to Kilometers | 102 | 103 | miles-to-kilometers | 0.62137119 |

View File

@@ -1 +0,0 @@
test

View File

@@ -1,61 +0,0 @@
#!/usr/bin/env python3
"""Upload a Miles to Kilometers calculator to WordPress via REST API."""
import urllib.request
import urllib.error
import json
import base64
url = "https://howdoyouconvert.com/wp-json/wp/v2/calculator"
creds = base64.b64encode(b"ben:6YGf wVxu gBpz pkqx BGZO lfVP").decode("utf-8")
content = (
'<style>.kb-row-layout-id_m2k_row > .kt-row-column-wrap{align-content:start;}'
':where(.kb-row-layout-id_m2k_row > .kt-row-column-wrap) > .wp-block-kadence-column{justify-content:start;}'
'.kb-row-layout-id_m2k_row > .kt-row-column-wrap{column-gap:var(--global-kb-gap-md, 2rem);row-gap:var(--global-kb-gap-md, 2rem);max-width:600px;margin-left:auto;margin-right:auto;padding-top:var(--global-kb-spacing-sm, 1.5rem);padding-bottom:var(--global-kb-spacing-sm, 1.5rem);grid-template-columns:repeat(2, minmax(0, 1fr));}'
'.kb-row-layout-id_m2k_row > .kt-row-layout-overlay{opacity:0.30;}'
'@media all and (max-width: 1024px){.kb-row-layout-id_m2k_row > .kt-row-column-wrap{grid-template-columns:repeat(2, minmax(0, 1fr));}}'
'@media all and (max-width: 767px){.kb-row-layout-id_m2k_row > .kt-row-column-wrap{grid-template-columns:minmax(0, 1fr);}}'
'</style>'
'<div class="kb-row-layout-wrap kb-row-layout-id_m2k_row aligncenter wp-block-kadence-rowlayout">'
'<div class="kt-row-column-wrap kt-has-2-columns kt-row-layout-equal kt-tab-layout-inherit kt-mobile-layout-row kt-row-valign-top">'
'\n<style>.kadence-column_m2k_col1 > .kt-inside-inner-col,.kadence-column_m2k_col1 > .kt-inside-inner-col:before{border-top-left-radius:0px;border-top-right-radius:0px;border-bottom-right-radius:0px;border-bottom-left-radius:0px;}'
'.kadence-column_m2k_col1 > .kt-inside-inner-col{column-gap:var(--global-kb-gap-sm, 1rem);flex-direction:column;}'
'.kadence-column_m2k_col1 > .kt-inside-inner-col > .aligncenter{width:100%;}'
'.kadence-column_m2k_col1 > .kt-inside-inner-col:before{opacity:0.3;}'
'.kadence-column_m2k_col1{position:relative;}</style>\n'
'<div class="wp-block-kadence-column kadence-column_m2k_col1"><div class="kt-inside-inner-col">\n'
'<input type="text" id="input-1" class="calc-input calc-field" onclick="clearPlaceholder(\'input-1\')" placeholder="0">\n\n'
'<input type="hidden" id="factor-1" name="factor-1" value="0.62137119">\n'
'</div></div>\n\n\n'
'<style>.kadence-column_m2k_col2 > .kt-inside-inner-col,.kadence-column_m2k_col2 > .kt-inside-inner-col:before{border-top-left-radius:0px;border-top-right-radius:0px;border-bottom-right-radius:0px;border-bottom-left-radius:0px;}'
'.kadence-column_m2k_col2 > .kt-inside-inner-col{column-gap:var(--global-kb-gap-sm, 1rem);flex-direction:column;}'
'.kadence-column_m2k_col2 > .kt-inside-inner-col > .aligncenter{width:100%;}'
'.kadence-column_m2k_col2 > .kt-inside-inner-col:before{opacity:0.3;}'
'.kadence-column_m2k_col2{position:relative;}</style>\n'
'<div class="wp-block-kadence-column kadence-column_m2k_col2"><div class="kt-inside-inner-col">\n'
'<input type="text" id="input-2" class="calc-input calc-field" onclick="clearPlaceholder(\'input-2\')" placeholder="0">\n'
'</div></div>\n\n'
'</div></div>'
)
data = json.dumps({
"title": "Miles to Kilometers",
"status": "publish",
"slug": "miles-to-kilometers",
"content": content,
}).encode("utf-8")
req = urllib.request.Request(url, data=data, method="POST")
req.add_header("Content-Type", "application/json")
req.add_header("Authorization", "Basic " + creds)
try:
resp = urllib.request.urlopen(req)
result = json.loads(resp.read().decode("utf-8"))
print("SUCCESS:", result.get("link"))
print("ID:", result.get("id"))
except urllib.error.HTTPError as e:
print("HTTP Error:", e.code)
print(e.read().decode("utf-8")[:500])
except Exception as e:
print("Error:", e)