@typeroll/mcp-server 0.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +448 -0
- package/README.md +135 -0
- package/dist/client.js +103 -0
- package/dist/index.js +114 -0
- package/dist/tools/block-types.js +86 -0
- package/dist/tools/bulk.js +24 -0
- package/dist/tools/collections.js +197 -0
- package/dist/tools/deploy.js +38 -0
- package/dist/tools/forms.js +98 -0
- package/dist/tools/helpers.js +59 -0
- package/dist/tools/media.js +202 -0
- package/dist/tools/page-blocks.js +155 -0
- package/dist/tools/pages.js +209 -0
- package/dist/tools/partials.js +108 -0
- package/dist/tools/preview.js +24 -0
- package/dist/tools/redirects.js +40 -0
- package/dist/tools/search.js +22 -0
- package/dist/tools/settings.js +64 -0
- package/dist/tools/sites.js +35 -0
- package/dist/tools/versions.js +52 -0
- package/package.json +50 -0
- package/skills/README.md +63 -0
- package/skills/tr-content-write.md +105 -0
- package/skills/tr-directory.md +214 -0
- package/skills/tr-images.md +152 -0
- package/skills/tr-migrate-wp.md +151 -0
- package/skills/tr-redesign-branch.md +149 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tr-images
|
|
3
|
+
description: Use when the user asks for an image, hero, illustration, or logo to be created and embedded in a Typeroll page. Covers the two-step signed-URL upload flow so the agent doesn't try to POST bytes through the CMS API (it can't).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Add images to a Typeroll site
|
|
7
|
+
|
|
8
|
+
The Typeroll API does NOT accept image bytes directly. Uploads go
|
|
9
|
+
through a signed PUT URL straight to Cloudflare R2, and the API only
|
|
10
|
+
sees the metadata. Two-step flow:
|
|
11
|
+
|
|
12
|
+
## Recipe
|
|
13
|
+
|
|
14
|
+
### 1. Get an image
|
|
15
|
+
|
|
16
|
+
Options, in order of preference:
|
|
17
|
+
|
|
18
|
+
a. **Reuse an existing one.** `list_media` returns CDN URLs for every
|
|
19
|
+
image already on this site. Search the list before generating
|
|
20
|
+
anything — saves bandwidth and keeps the visual catalog tight.
|
|
21
|
+
|
|
22
|
+
b. **Generate locally.** The user's Claude Code installation has
|
|
23
|
+
access to whatever image-gen tools they've configured (DALL-E,
|
|
24
|
+
Midjourney, Stable Diffusion, Replicate, etc.). Generate and save
|
|
25
|
+
to a tempfile.
|
|
26
|
+
|
|
27
|
+
c. **Source from the web** with appropriate licensing (the user is
|
|
28
|
+
responsible for clearing rights). Save locally before upload.
|
|
29
|
+
|
|
30
|
+
### 2. Mint a signed upload URL
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
create_upload_url filename="hero-services.png"
|
|
34
|
+
content_type="image/png"
|
|
35
|
+
size=<bytes>
|
|
36
|
+
alt_text="Office worker reviewing documents at a desk"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"upload_url": "https://...r2.cloudflarestorage.com/.../signed-...",
|
|
44
|
+
"cdn_url": "https://cdn.example.com/orgs/.../images/...png",
|
|
45
|
+
"key": "orgs/.../images/...png",
|
|
46
|
+
"media_id": "abc123",
|
|
47
|
+
"expires_in": 300
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The signed URL is valid for 5 minutes. The media doc is already
|
|
52
|
+
registered — even before the upload completes — so it'll show in
|
|
53
|
+
`list_media` immediately.
|
|
54
|
+
|
|
55
|
+
### 3. PUT the bytes
|
|
56
|
+
|
|
57
|
+
Outside the MCP, hit the signed URL directly:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
PUT <upload_url>
|
|
61
|
+
Content-Type: <same content_type as in step 2>
|
|
62
|
+
Body: <file bytes>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
In a shell:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
curl -X PUT "<upload_url>" \
|
|
69
|
+
-H "Content-Type: image/png" \
|
|
70
|
+
--data-binary @hero-services.png
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Or from JS (Claude Code can run a one-line script):
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
await fetch(uploadUrl, {
|
|
77
|
+
method: 'PUT',
|
|
78
|
+
headers: { 'Content-Type': contentType },
|
|
79
|
+
body: await fs.readFile(path),
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
A 200 OK from R2 means the image is now live at `cdn_url`.
|
|
84
|
+
|
|
85
|
+
### 4. Patch metadata (alt text, etc.)
|
|
86
|
+
|
|
87
|
+
You set `alt_text` at create time, but if you generate the image first
|
|
88
|
+
and only THEN realize what to caption it as, patch later:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
update_media media_id=<id> alt_text="..." filename="hero-services-v2.png"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 4b. Fill missing alt-text on existing media
|
|
95
|
+
|
|
96
|
+
When a customer has uploaded a bunch of images without alt-text (very
|
|
97
|
+
common after a WP migration), don't make it up — use vision:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
list_media → find items with empty alt_text
|
|
101
|
+
suggest_alt_text_context media_id=<id> → returns { image_url, suggested_prompt,
|
|
102
|
+
language, used_on_pages, current_alt_text }
|
|
103
|
+
# Pass image_url + the returned suggested_prompt to YOUR OWN vision
|
|
104
|
+
# capability (you can fetch the URL and pass bytes to vision).
|
|
105
|
+
update_media media_id=<id> alt_text="<what vision returned>"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The prompt is tuned for SEO-grade output: short (5-15 words), no "image
|
|
109
|
+
of / picture of" filler, written in the site's content language,
|
|
110
|
+
decorative images return empty string. Run it sequentially on a
|
|
111
|
+
list_media batch and you can fix alt-text gaps across a whole site
|
|
112
|
+
without burning your context on prompt design. The platform does NOT
|
|
113
|
+
run vision on your behalf — your model does, your usage.
|
|
114
|
+
|
|
115
|
+
### 5. Embed in a page
|
|
116
|
+
|
|
117
|
+
`read_page` the target, insert `<img>` in the right spot:
|
|
118
|
+
|
|
119
|
+
```html
|
|
120
|
+
<img src="<cdn_url>"
|
|
121
|
+
alt="<alt_text>"
|
|
122
|
+
style="width: 100%; height: auto; display: block; margin: 2rem 0;" />
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Then `update_page` with the new HTML. Or, if you're generating a hero
|
|
126
|
+
for a brand-new page, include the `<img>` directly in `create_page`'s
|
|
127
|
+
`html_content`.
|
|
128
|
+
|
|
129
|
+
## Pitfalls
|
|
130
|
+
|
|
131
|
+
- **Always set `alt_text`.** Empty alt is bad for SEO + accessibility.
|
|
132
|
+
Default to a one-sentence description of what's in the image.
|
|
133
|
+
- **`<script>` etc. in SVGs.** The page sanitizer drops `<script>`
|
|
134
|
+
inside SVG, so an icon set that includes script-based animations
|
|
135
|
+
won't render correctly. Use static SVG or a JPG/PNG export.
|
|
136
|
+
- **CSS background-image references aren't dedup'd.** If you set the
|
|
137
|
+
same image as a CSS background on multiple pages, the alt-text +
|
|
138
|
+
metadata are page-irrelevant. The sanitizer allows
|
|
139
|
+
`background-image: url(...)` in inline styles, but think about
|
|
140
|
+
whether an `<img>` is actually better.
|
|
141
|
+
- **Source URL leakage.** If you generated the image from a prompt
|
|
142
|
+
that contains internal info, don't bake that prompt into the
|
|
143
|
+
filename. Use a descriptive but generic filename.
|
|
144
|
+
|
|
145
|
+
## Format choice
|
|
146
|
+
|
|
147
|
+
- **PNG** for logos, icons with hard edges, anything with text.
|
|
148
|
+
- **JPG** for photos. Smaller file, better for big hero images.
|
|
149
|
+
- **WebP** if the target audience runs modern browsers (95%+ in 2026).
|
|
150
|
+
- **SVG** for icons + simple illustrations. Vector scales perfectly.
|
|
151
|
+
- **PDF** is supported by `create_upload_url` for document downloads;
|
|
152
|
+
link with `<a href>`, not `<img>`.
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tr-migrate-wp
|
|
3
|
+
description: Use when the user asks to migrate a WordPress site to Typeroll, mentions wp-json, or names a WP source URL. Walks the WP REST API, rebuilds pages in the target site's design, transfers media, sets redirects, leaves everything as drafts for human review.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Migrate from WordPress to Typeroll
|
|
7
|
+
|
|
8
|
+
The platform's in-portal migration workflow is the "managed" path for
|
|
9
|
+
customers who want one-click. This skill is the "power-user" path: you
|
|
10
|
+
do it locally, mix data sources freely, and the user (consultant /
|
|
11
|
+
agency) reviews each step in their terminal.
|
|
12
|
+
|
|
13
|
+
## Preconditions
|
|
14
|
+
|
|
15
|
+
- `@typeroll/mcp-server` configured with a valid `TYPEROLL_API_KEY`.
|
|
16
|
+
- The source WP site has `/wp-json` reachable (Google for "wordpress
|
|
17
|
+
REST API disabled" if not — common for hardened hosts).
|
|
18
|
+
- The Typeroll target site exists. New, blank sites with the
|
|
19
|
+
starter design work best. If the target already has content, you
|
|
20
|
+
must NOT clobber it — always `list_pages` first and only write to
|
|
21
|
+
slugs that don't already exist.
|
|
22
|
+
|
|
23
|
+
## Recipe
|
|
24
|
+
|
|
25
|
+
### 1. Probe and inventory
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
fetch <wp-url>/wp-json # confirm REST is on
|
|
29
|
+
fetch <wp-url>/wp-sitemap.xml or /sitemap.xml # URL inventory
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Build a list of every URL you intend to migrate. WP custom post types
|
|
33
|
+
need their REST endpoint (e.g. `/wp-json/wp/v2/news?per_page=100`),
|
|
34
|
+
walking `X-WP-TotalPages` to paginate.
|
|
35
|
+
|
|
36
|
+
### 2. Learn the target's design
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
get_site
|
|
40
|
+
read_site_settings # colors, fonts, voice cues
|
|
41
|
+
list_partials # header / footer / shared
|
|
42
|
+
read_partial partial_id="header" # nav structure
|
|
43
|
+
list_pages limit=5
|
|
44
|
+
batch_read_pages page_ids=[<2-3 representative ids>] # see actual conventions
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Don't skip this. Imposing a stranger's design on a customer's site is
|
|
48
|
+
the biggest avoidable mistake.
|
|
49
|
+
|
|
50
|
+
### 3. Migrate one page at a time, draft status
|
|
51
|
+
|
|
52
|
+
For each source URL:
|
|
53
|
+
|
|
54
|
+
a. Fetch from WP. Prefer the helper plugin's authenticated endpoint
|
|
55
|
+
(`/wp-json/typeroll/v1/...`) if available — it bypasses
|
|
56
|
+
`show_in_rest=false` and returns ACF + builder fields. Otherwise
|
|
57
|
+
fall back to `/wp-json/wp/v2/<post-type>?slug=<slug>`.
|
|
58
|
+
|
|
59
|
+
b. Clean the HTML. Strip Elementor / Gutenberg / Breakdance class
|
|
60
|
+
soup. Drop empty `<div>` and `<span>` wrappers. Keep semantic tags,
|
|
61
|
+
tables, iframes from known hosts (YouTube / Vimeo / Calendly).
|
|
62
|
+
|
|
63
|
+
c. Migrate referenced images:
|
|
64
|
+
- For each `<img src>` and CSS `background-image: url()`:
|
|
65
|
+
1. Download the source image locally.
|
|
66
|
+
2. `create_upload_url filename=... content_type=...` → returns
|
|
67
|
+
`{ upload_url, cdn_url, media_id }`.
|
|
68
|
+
3. PUT the bytes to `upload_url` (curl or fetch with the same
|
|
69
|
+
content type).
|
|
70
|
+
4. Replace the `src` with `cdn_url` in the rewritten HTML.
|
|
71
|
+
- Use `update_media media_id=... alt_text="..."` to set a real alt
|
|
72
|
+
text (existing WP `alt` attribute or `aria-label`; fall back to
|
|
73
|
+
filename only as a last resort).
|
|
74
|
+
|
|
75
|
+
d. Reconstruct in the target's design. The cleaned HTML is rarely
|
|
76
|
+
ready to ship — typical fixes: replace WP `wp-block-*` classes
|
|
77
|
+
with the target's CSS variables; turn Elementor sections into
|
|
78
|
+
plain `<section>` with the target's spacing; fix headings so the
|
|
79
|
+
page has exactly one `<h1>`. If you're confident, batch these
|
|
80
|
+
through `bulk_replace_text` with `dry_run: true` first.
|
|
81
|
+
|
|
82
|
+
e. Write the page as a draft:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
create_page title="..." slug="<preserved-from-wp>"
|
|
86
|
+
html_content="<reconstructed>"
|
|
87
|
+
status="draft" kind="article" author="..."
|
|
88
|
+
seo_title="..." seo_description="..."
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Preserve the source URL.** WP post URLs like
|
|
92
|
+
`/2024/01/foo-bar/` go in as `slug: "2024/01/foo-bar"`. The
|
|
93
|
+
slug supports slashes; encode the WP permalink structure verbatim
|
|
94
|
+
when the customer wants existing links to keep working.
|
|
95
|
+
|
|
96
|
+
### 4. Redirects
|
|
97
|
+
|
|
98
|
+
After migration, every URL the agent didn't preserve verbatim needs a
|
|
99
|
+
redirect:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
create_redirect from_path="/old-services" to_path="/services"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Walk the inventory; for each URL: did it become a page with the same
|
|
106
|
+
path? If yes, no redirect. If renamed, `create_redirect`. If
|
|
107
|
+
intentionally dropped, mark it excluded in your notes (the customer
|
|
108
|
+
should sign off on every dropped URL).
|
|
109
|
+
|
|
110
|
+
### 5. Preview + review with the user
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
get_preview_link page_id=<id> # one URL the user can click
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Open in the user's browser. The preview navigates the whole site from
|
|
117
|
+
one mint. Iterate on feedback: pages, header, footer.
|
|
118
|
+
|
|
119
|
+
### 6. Ship
|
|
120
|
+
|
|
121
|
+
When the user signs off:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
# Bulk-publish drafts that look right
|
|
125
|
+
batch_update_pages updates=[{page_id, patch:{status:"published"}}, ...]
|
|
126
|
+
|
|
127
|
+
# Deploy
|
|
128
|
+
trigger_deploy
|
|
129
|
+
get_deploy_status job_id=<id> # poll
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Pitfalls
|
|
133
|
+
|
|
134
|
+
- **Don't publish during migration.** Always import as `draft`. Even
|
|
135
|
+
if the agent is confident, the customer needs the chance to spot-check.
|
|
136
|
+
- **WP slugs sometimes drift.** A post saved with slug `foo-bar` may
|
|
137
|
+
have been served at `/2024/01/foo-bar/` due to the permalink
|
|
138
|
+
structure. The full URL is what users see in Google; preserve that,
|
|
139
|
+
not the bare slug.
|
|
140
|
+
- **Image bandwidth.** R2 upload is metered. Use `find_pages_matching`
|
|
141
|
+
contains="<old-domain>" on already-imported content to spot images
|
|
142
|
+
that weren't transferred.
|
|
143
|
+
- **WP-specific JSON-LD** (Yoast, Rank Math) is usually wrong after a
|
|
144
|
+
redesign because it references old URLs. Strip it; let Typeroll
|
|
145
|
+
emit fresh Article/Page schemas via `kind: 'article'` + `author`.
|
|
146
|
+
|
|
147
|
+
## When the source isn't WordPress
|
|
148
|
+
|
|
149
|
+
The same shape applies for any source — Squarespace export, custom
|
|
150
|
+
CMS, scraped HTML, CSV. Replace step 1's "WP REST" probe with whatever
|
|
151
|
+
discovery the source supports, and the rest of the recipe is unchanged.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tr-redesign-branch
|
|
3
|
+
description: Use when the user asks to redesign, modernize, or restructure a Typeroll site (or a section of it). Forces branch-isolated work so the live site stays untouched until the redesign is approved.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Redesign a site without breaking the live one
|
|
7
|
+
|
|
8
|
+
Site-wide changes are exactly where copy-on-write branches earn their
|
|
9
|
+
keep. This skill enforces the discipline: every redesign happens on a
|
|
10
|
+
branch, preview-checked end-to-end, merged only after user sign-off.
|
|
11
|
+
|
|
12
|
+
## Recipe
|
|
13
|
+
|
|
14
|
+
### 1. Discover (always)
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
get_site
|
|
18
|
+
read_site_settings
|
|
19
|
+
read_partial partial_id="header"
|
|
20
|
+
read_partial partial_id="footer"
|
|
21
|
+
list_pages limit=20
|
|
22
|
+
batch_read_pages page_ids=[<top 3-5 pages>] # see actual conventions
|
|
23
|
+
list_partials # what free blocks exist
|
|
24
|
+
list_collections # any data we need to consider
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Write the user a short read-back: *"This is a 12-page agency site
|
|
28
|
+
using CSS variables, primary color #1e40af, Inter heading + Source
|
|
29
|
+
Sans body. Existing pages are content-dense, single-column. Main nav
|
|
30
|
+
has 5 items including a CTA. I'd suggest..."*
|
|
31
|
+
|
|
32
|
+
Confirm direction before touching anything.
|
|
33
|
+
|
|
34
|
+
### 2. Create a branch
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
create_branch name="<descriptive name>"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Save the response's `id` — pass it as `version=<id>` on every
|
|
41
|
+
subsequent call. Branches default `robots_blocked: true` so a
|
|
42
|
+
half-finished redesign won't be indexed.
|
|
43
|
+
|
|
44
|
+
### 3. Iterate on the branch
|
|
45
|
+
|
|
46
|
+
For each redesign step:
|
|
47
|
+
|
|
48
|
+
a. Make the change with `?version=<branch-id>`. Updates here don't
|
|
49
|
+
touch main:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
update_partial partial_id="header" patch={...} version="<branch>"
|
|
53
|
+
update_page page_id=home patch={...} version="<branch>"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
b. Preview after every meaningful change:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
get_preview_link page_id=home version="<branch>"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Send the URL to the user. The preview navigates the whole branch
|
|
63
|
+
from one mint.
|
|
64
|
+
|
|
65
|
+
c. Iterate on feedback. Common rounds: headline tightening, color
|
|
66
|
+
tweaks, swapping hero images.
|
|
67
|
+
|
|
68
|
+
### 4. Site-wide changes through partials, not pages
|
|
69
|
+
|
|
70
|
+
If the redesign touches every page (e.g. new global header, new
|
|
71
|
+
footer, new CTA bar) — edit a partial, not 23 pages. Before editing a
|
|
72
|
+
shared block, check the blast radius:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
find_pages_using_block partial_id="header" version="<branch>"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
This returns every page that would show the change. Communicate that
|
|
79
|
+
to the user before the save.
|
|
80
|
+
|
|
81
|
+
### 5. Bulk content cleanups via dry-run first
|
|
82
|
+
|
|
83
|
+
If the redesign requires content rewrites (e.g. "remove every mention
|
|
84
|
+
of the old company name"), use the bulk tool with dry-run:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
search_pages contains="OldCo" version="<branch>"
|
|
88
|
+
bulk_replace_text pattern="OldCo" replacement="NewCo" dry_run=true version="<branch>"
|
|
89
|
+
# Show the user the sample_diffs
|
|
90
|
+
bulk_replace_text pattern="OldCo" replacement="NewCo" dry_run=false version="<branch>"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 6. Approval round
|
|
94
|
+
|
|
95
|
+
Send the user a final preview link:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
get_preview_link page_id=home version="<branch>" ttl_seconds=86400
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The 24h TTL gives them time to share with stakeholders. Wait for an
|
|
102
|
+
explicit "looks good, ship it."
|
|
103
|
+
|
|
104
|
+
### 7. Merge + deploy
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
merge_branch version_id="<branch>" # branch's diffs land on main
|
|
108
|
+
trigger_deploy
|
|
109
|
+
get_deploy_status job_id=<id> # poll until succeeded
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Optionally, after a successful deploy:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
delete_branch version_id="<branch>" # tidy up
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
(You can also leave the branch around as a record of the redesign;
|
|
119
|
+
disk cost is tiny.)
|
|
120
|
+
|
|
121
|
+
## Pitfalls
|
|
122
|
+
|
|
123
|
+
- **Forgetting `version=` on writes.** Every call you make on the
|
|
124
|
+
branch must include `version=<branch-id>`. A missing one writes
|
|
125
|
+
straight to main — silent and bad.
|
|
126
|
+
- **Skipping discovery.** "Modernize" without first reading the site
|
|
127
|
+
produces a confidently-out-of-place result. Always sample existing
|
|
128
|
+
pages.
|
|
129
|
+
- **Editing the in-portal preview URL by mistake.** That's the user's
|
|
130
|
+
own preview, not yours. `get_preview_link` returns a signed
|
|
131
|
+
external URL — always use that for sharing.
|
|
132
|
+
- **Auto-merge.** Don't `merge_branch` without explicit user sign-off.
|
|
133
|
+
Once merged, the only undo is another branch + reverse edits.
|
|
134
|
+
- **Header rewrites that drop the brand block.** Even when the
|
|
135
|
+
redesign is dramatic, preserve the brand mark + the nav skeleton
|
|
136
|
+
unless the user said to redo them.
|
|
137
|
+
|
|
138
|
+
## When to NOT use a branch
|
|
139
|
+
|
|
140
|
+
Tiny edits — "fix the typo on the About page" — don't need a branch.
|
|
141
|
+
The in-portal chat handles those directly on main. This skill is for
|
|
142
|
+
work where:
|
|
143
|
+
|
|
144
|
+
- The user might want to walk away mid-redesign and come back later
|
|
145
|
+
- Multiple changes need to ship together
|
|
146
|
+
- The site is high-traffic and "broken for an hour" is unacceptable
|
|
147
|
+
- Stakeholder review across multiple pages is expected
|
|
148
|
+
|
|
149
|
+
If none of those apply, edit main directly and move on.
|