docs: describe svelte workflow

This commit is contained in:
Codex
2026-03-07 07:48:04 +00:00
parent f978cadfc6
commit 858c940332
2 changed files with 52 additions and 187 deletions

View File

@@ -1,158 +1,33 @@
# How Do You Convert - AI Agent SOP
# How Do You Convert AI Agent SOP
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.
This repo now ships a **SvelteKit** experience that renders every conversion locally. All calculator logic lives inside `hdyc-svelte`, and the markdown registry plus a generator script drive the data. There are no WordPress posts, Kadence elements, or REST creates involved in the current deployment flow.
---
## 1. Architecture overview
- `hdyc-svelte` is a SvelteKit + Node app that renders the homepage, category lists, and every `/[slug]` calculator page via server-side rendering.
- `src/lib/data/calculators.ts` contains every calculator definition (slug, labels, factor, description, visibility, etc.), along with helper functions for lookups, search, and category metadata.
- `unitDefinitions.ts` derives glossary text from the calculator labels so the site can surface contextual descriptions without additional API calls.
## 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).
## 2. The canonical registry (`calculators_list.md`)
- The **Active Calculators** table at the top is the single source of truth for every published conversion. Only entries listed here will appear in the generated data. Update this table before making any frontend changes.
- Column guidance:
- **Calculator Name**: keep the existing “Name descriptive teaser” format. The human-friendly phrase after the dash becomes the page subtitle.
- **Page Post ID / Kadence JS Element ID**: vestigial metadata from the previous architecture. Preserve the existing values if known, but the Svelte pipeline ignores them; you can leave them blank if you do not know them.
- **Slug**: lowercase, dash-separated, and unique. `migrate.py` uses this as the canonical identifier, so avoid spaces or special characters.
- **Conversion Factor**: this column is the only information `migrate.py` uses to infer the math. Simple multiplicative conversions should use the numeric multiplier that transforms the first unit into the second. Use `Linear Offset (m x + b)` when a fixed offset exists (e.g., `Linear Offset (1.8x + 32)` for Celsius → Fahrenheit), `1/x` for reciprocal conversions, `Multi-Variable` for compound calculators (amps, watts, lux, etc.), and tokens like `10_to_2`, `16_to_10`, `N/A (Text)`, or `Base` for number-system helpers. The script has heuristics built in for the most common patterns; if your calculator is unusual, see section 3 before rerunning.
- After the active table ends, keep the **Backlog** checklist intact. Move a row from the backlog into the table when it is ready for publication, then rerun the generator so the new slug actually ships.
---
## 3. Generating the calculator data
- Every edit to the registry must be followed by `python migrate.py` executed from the repository root. The script reads `calculators_list.md`, applies heuristics to determine category/type/labels, and produces the updated `hdyc-svelte/src/lib/data/calculators.ts` file.
- `calculators.ts` is fully generated; **do not edit it by hand**. If a converter needs a special factor, offset, extra label, base conversion, or text description, adjust the registry row (or the generator logic) so the next run emits the correct values.
- The script automatically adds `hidden` flags for duplicate reverse conversions, infers decimal vs. binary data scales, and embeds any available descriptive paragraphs, so confirm the generated `descriptionHTML` block if you expect custom SEO copy.
## 2. Two-Part Architecture
## 4. Development & verification
- Install dependencies inside `hdyc-svelte`: `cd hdyc-svelte && npm install` (or use your preferred package manager).
- Run `npm run dev` for a local server, then open `/` and `/[slug]` in your browser to confirm the new conversion behaves bidirectionally.
- Before committing, run `npm run check` from `hdyc-svelte` to ensure TypeScript and Svelte checks pass. A production build uses `npm run build`; preview it with `npm run preview` if you want to inspect the output bundle.
- When verifying a new calculator, test both directions, check the formula in the UI, and confirm the glossary/description text reads correctly. If the description needs editing, update the generator source (see section 3) instead of touching the compiled file.
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>
```
### 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}}]'
}
}
# POST to /wp-json/wp/v2/kadence_element
```
---
## 6. Infrastructure Warnings
> [!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.
## 5. What's next
- Every change involves at least these files: `calculators_list.md` (registry), `migrate.py` output (`hdyc-svelte/src/lib/data/calculators.ts`), and any touched component or route within `hdyc-svelte/src/routes`.
- Document any unusual heuristics you add to `migrate.py` so future contributors understand why certain entries require manual adjustments.
- Keep the backlog alive: it is the easiest way to hand off upcoming conversions without cluttering the active registry.

View File

@@ -1,42 +1,32 @@
# sv
# HowDoYouConvert.com Svelte Front End
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
This repository hosts the modern SvelteKit experience for **howdoyouconvert.com**. Every calculator is rendered by Svelte on the server and client; no third-party CMS or injected script is involved anymore.
## Creating a project
## Overview
- The front end lives in `hdyc-svelte`; it uses `@sveltejs/adapter-node` to run as a Node server.
- `src/routes/+page.svelte` renders the hero, search, and category grid, while `src/routes/[slug]/+page.svelte` renders the calculators themselves.
- Conversion metadata is centralized in `src/lib/data/calculators.ts`, which drives the UI, search, glossary, and slug-based routing.
If you're seeing this, you've probably already done this step. Congrats!
## Development
1. Install dependencies inside the `hdyc-svelte` folder (`npm install` is sufficient; feel free to swap `npm` for `pnpm` or `yarn`).
2. Run `npm run dev` while editing to get a localhost server with hot reloading.
3. Use `npm run check` to run `svelte-check` and surface type or markup issues.
4. When you are ready to verify the production bundle, run `npm run build` and optionally `npm run preview` or `npm run start` to exercise the compiled `build` folder.
```sh
# create a new project
npx sv create my-app
```
## Data pipeline
- The single source of truth for every published calculator is `calculators_list.md` in the repo root. The **Active Calculators** table at the top defines which conversions are shipped; the trailing backlog checklist stores future work.
- After editing `calculators_list.md`, run `python migrate.py` from the repo root. The script reads the registry, infers categories/types based on the conversion factor column, and writes the autogenerated `hdyc-svelte/src/lib/data/calculators.ts` file.
- `calculators.ts` contains the `calculators` array, the `categories` map, and helper lookup/search functions. **Do not edit it manually**—regenerate it through `migrate.py` whenever the registry changes.
- The generator also populates descriptions, hidden flags, and label metadata, so confirm the regenerated file before committing.
To recreate this project with the same configuration:
## Adding a calculator
1. Add a new row to the active table in `calculators_list.md`; the slug must be lowercase and dash-separated, and the conversion factor column must encode the math (`Linear Offset (m x + b)`, `1/x`, `Multi-Variable`, `10_to_2`, etc.).
2. Run `python migrate.py` so the new slug appears in `src/lib/data/calculators.ts` with the correct type and labels.
3. Start the dev server and navigate to `/new-slug` to verify the UI, bidirectional math, and description text.
4. Run `npm run check` (and optionally `npm run build`) before committing so the type system stays happy.
```sh
# recreate this project
npx sv@0.12.5 create --template minimal --types ts --install npm hdyc-svelte
```
## Deploying & verification
- The output of `npm run build` can be deployed anywhere that serves a Node app (a hosted environment or edge with Node support). `npm run start` runs the compiled server locally.
- For each release, make sure the generated data file and the registry are in sync. Any mismatch will result in missing calculator pages because the routing is slug-driven.
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```sh
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
To create a production version of your app:
```sh
npm run build
```
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
Maintaining the registry and the generated data file is the only path to publish a calculator in the new architecture.