@typeroll/mcp-server 0.7.4 → 0.7.7

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.
@@ -0,0 +1,198 @@
1
+ ---
2
+ name: tr-new-site
3
+ description: Use when the user wants to create a new Typeroll site from scratch, set up the initial design, or bootstrap a blank site with working header/footer, brand colors, and a homepage. Also triggers on "start a new site", "set up a site for", or "build a website for [company]".
4
+ ---
5
+
6
+ # Bootstrap a new Typeroll site
7
+
8
+ Start here when the site already exists as a database record (created via
9
+ the portal UI or API) but has no design, no header/footer, and no pages.
10
+ The goal is to go from blank to a working 4-page site with correct brand
11
+ identity in a single session.
12
+
13
+ ## Preconditions
14
+
15
+ - `@typeroll/mcp-server` configured with a valid `TYPEROLL_API_KEY`.
16
+ - The site exists (confirm with `get_site`).
17
+ - You have the customer brief: company name, industry, 2–3 key brand colors,
18
+ tone of voice (formal / friendly / minimal / vibrant), and a list of
19
+ initial pages.
20
+
21
+ ## Recipe
22
+
23
+ ### 1. Audit current state
24
+
25
+ ```
26
+ get_site
27
+ read_site_settings # see what (if anything) is already configured
28
+ list_pages # don't overwrite pages that already exist
29
+ list_partials # check if header/footer already have content
30
+ ```
31
+
32
+ ### 2. Brand + settings
33
+
34
+ One `update_site_settings` call with every field you know:
35
+
36
+ ```json
37
+ {
38
+ "site_name": "Acme Studio",
39
+ "tagline": "Short, punchy tagline",
40
+ "language": "sv",
41
+ "colors": {
42
+ "primary": "#1a1a2e",
43
+ "secondary": "#16213e",
44
+ "accent": "#e94560",
45
+ "background": "#f5f5f5",
46
+ "surface": "#ffffff",
47
+ "text": "#1a1a2e",
48
+ "text_light": "#6b7280"
49
+ },
50
+ "fonts": {
51
+ "heading": "Playfair Display",
52
+ "body": "Inter",
53
+ "size_base": 16
54
+ },
55
+ "contact": {
56
+ "email": "hej@acme.se",
57
+ "phone": "+46 8 123 456",
58
+ "address": "Drottninggatan 1, 111 51 Stockholm"
59
+ },
60
+ "social": {
61
+ "instagram": "https://instagram.com/acme",
62
+ "linkedin": "https://linkedin.com/company/acme"
63
+ }
64
+ }
65
+ ```
66
+
67
+ Read it back: `read_site_settings` — confirm `updated_fields` includes
68
+ everything you intended.
69
+
70
+ Google Fonts names: use the full display name as it appears on
71
+ fonts.google.com, e.g. "Cormorant Garamond", "DM Sans", "Plus Jakarta Sans".
72
+
73
+ ### 3. Header partial
74
+
75
+ Replace the header with a real nav. Keep it simple:
76
+
77
+ ```html
78
+ <header class="site-header">
79
+ <div class="header-inner">
80
+ <a class="header-logo" href="/">Acme Studio</a>
81
+ <nav class="header-nav">
82
+ <a href="/om-oss">Om oss</a>
83
+ <a href="/tjanster">Tjänster</a>
84
+ <a href="/kontakt">Kontakt</a>
85
+ </nav>
86
+ </div>
87
+ </header>
88
+ <style>
89
+ .site-header{background:var(--color-primary);padding:1rem 2rem}
90
+ .header-inner{max-width:1080px;margin:0 auto;display:flex;align-items:center;justify-content:space-between}
91
+ .header-logo{color:#fff;text-decoration:none;font-family:var(--font-heading);font-size:1.25rem;font-weight:700}
92
+ .header-nav{display:flex;gap:2rem}
93
+ .header-nav a{color:rgba(255,255,255,0.85);text-decoration:none;font-size:0.9rem;letter-spacing:0.05em;text-transform:uppercase}
94
+ .header-nav a:hover{color:#fff}
95
+ </style>
96
+ ```
97
+
98
+ Use `replace_partial partial_id="header" html_content="..."`.
99
+
100
+ ### 4. Footer partial
101
+
102
+ ```html
103
+ <footer class="site-footer">
104
+ <div class="footer-inner">
105
+ <p class="footer-brand">Acme Studio</p>
106
+ <p class="footer-tagline">Tagline here</p>
107
+ <div class="footer-links">
108
+ <a href="/om-oss">Om oss</a>
109
+ <a href="/kontakt">Kontakt</a>
110
+ </div>
111
+ <p class="footer-copy">© 2025 Acme Studio. Alla rättigheter förbehållna.</p>
112
+ </div>
113
+ </footer>
114
+ <style>
115
+ .site-footer{background:var(--color-secondary);color:rgba(255,255,255,0.7);padding:3rem 2rem;margin-top:4rem}
116
+ .footer-inner{max-width:1080px;margin:0 auto;text-align:center;display:grid;gap:1rem}
117
+ .footer-brand{font-family:var(--font-heading);font-size:1.5rem;color:#fff;font-weight:700}
118
+ .footer-links{display:flex;justify-content:center;gap:2rem}
119
+ .footer-links a{color:rgba(255,255,255,0.7);text-decoration:none}
120
+ .footer-links a:hover{color:#fff}
121
+ .footer-copy{font-size:0.8rem;opacity:0.5}
122
+ </style>
123
+ ```
124
+
125
+ Use `replace_partial partial_id="footer" html_content="..."`.
126
+
127
+ ### 5. Homepage
128
+
129
+ ```
130
+ create_page title="Start" slug="" content_mode="html"
131
+ html_content="<full hero + intro HTML>"
132
+ status="published"
133
+ ```
134
+
135
+ `slug=""` creates the homepage under `page_id: "home"`. If it already
136
+ exists, use `update_page page_id="home" patch={html_content: "..."}`.
137
+
138
+ A minimal homepage structure:
139
+ - Hero: full-width section with `<h1>`, tagline, one CTA button
140
+ - Intro: 2–3 sentences about what the company does
141
+ - Services/features grid: 3 cards max
142
+ - CTA band: "Kontakta oss" or similar
143
+
144
+ ### 6. Inner pages
145
+
146
+ Create each page:
147
+ ```
148
+ create_page title="Om oss" slug="om-oss" content_mode="html"
149
+ html_content="..." status="published"
150
+ ```
151
+
152
+ Standard set: Om oss, Tjänster, Kontakt. Add more if the brief says so.
153
+
154
+ ### 7. Preview + iterate
155
+
156
+ ```
157
+ get_preview_link # get a signed URL for the whole site
158
+ get_page_preview page_id="home" # get rendered HTML to spot-check
159
+ ```
160
+
161
+ Share the preview link with the user. Iterate on feedback.
162
+
163
+ ### 8. Deploy
164
+
165
+ When the user approves:
166
+ ```
167
+ trigger_deploy
168
+ get_deploy_status job_id=<id> # poll until status=succeeded
169
+ ```
170
+
171
+ ## Design conventions
172
+
173
+ - **One `<h1>` per page.** SEO and screen reader requirement.
174
+ - **CSS variables for colors.** Always use `var(--color-primary)` etc. in
175
+ partial `<style>` blocks — never hardcode hex values.
176
+ - **Responsive layout.** Use `max-width` on containers, `display:flex`
177
+ or `display:grid` for layouts, and `clamp()` for fluid type.
178
+ - **Scoped styles.** Put `<style>` at the bottom of partial HTML.
179
+ Styles apply to the whole page; prefix class names with the partial ID
180
+ to avoid collisions (`site-header__*`, `site-footer__*`).
181
+ - **Minimal JS.** The platform doesn't bundle JS. If you need interactions,
182
+ write a small `<script>` inside the partial or page; keep it under 50
183
+ lines. Avoid external CDN dependencies in page bodies.
184
+
185
+ ## Pitfalls
186
+
187
+ - **Don't create pages that already exist.** Run `list_pages` first;
188
+ if the slug is taken, use `update_page` instead of `create_page`.
189
+ - **Don't hardcode text from settings into partials.** If `site_name`
190
+ is "Acme", the header partial should have literal "Acme" in it —
191
+ there's no template engine. When the name changes the user updates
192
+ the partial.
193
+ - **Google Fonts names are case-sensitive.** "Playfair Display" works;
194
+ "playfair display" or "Playfair-Display" do not.
195
+ - **Empty `custom_css` field.** If you set `custom_css: ""` it's
196
+ stored as an empty string, not removed. Use it only when you have
197
+ global styles that span both partials and pages (e.g. utility classes,
198
+ `@keyframes`, `:root` overrides for things not in `colors`/`fonts`).
@@ -0,0 +1,179 @@
1
+ ---
2
+ name: tr-seo
3
+ description: Use when the user asks to improve SEO, fix meta tags, add structured data, check page titles, or audit the site's search visibility. Triggers on "SEO", "meta descriptions", "Google ranking", "structured data", "JSON-LD", "sitemap", "sökoptimering", or "hjälp mig synas på Google".
4
+ ---
5
+
6
+ # SEO audit and improvements for a Typeroll site
7
+
8
+ ## What Typeroll handles automatically
9
+
10
+ - `<html lang>` from site `language` setting (per-page override via `language` field)
11
+ - `<title>` = `page.seo_title || page.title + settings.default_seo_suffix`
12
+ - `<meta name="description">` from `page.seo_description`
13
+ - `<meta name="robots">` from `page.noindex`
14
+ - `<meta property="og:*">` Open Graph tags from seo_title, seo_description, og_image
15
+ - `<link rel="canonical">` from `page.canonical_url` (falls back to the page's own URL)
16
+ - Article schema from `kind: "article"` + `author` + `date_published`
17
+ - Page schema from `kind: "page"` (default)
18
+ - `robots.txt` from `settings.robots_txt`
19
+ - Sanitized HTML that preserves semantic structure
20
+
21
+ ## Recipe
22
+
23
+ ### 1. Audit current state
24
+
25
+ ```
26
+ list_pages status="all"
27
+ read_site_settings
28
+ ```
29
+
30
+ For each page, check:
31
+ - Is `seo_title` set? (if not, Google uses `title` + suffix — often fine)
32
+ - Is `seo_description` set? (150–160 chars, unique per page, includes keywords)
33
+ - Is `og_image` set for the homepage and key landing pages?
34
+ - Does the page have exactly one `<h1>`?
35
+
36
+ ### 2. Fix missing meta descriptions
37
+
38
+ ```
39
+ batch_update_pages updates=[
40
+ {page_id: "home", patch: {seo_description: "Acme designar rum..."}},
41
+ {page_id: "om-oss", patch: {seo_description: "Vi är ett..."}},
42
+ {page_id: "tjanster", patch: {seo_description: "Våra tjänster..."}}
43
+ ]
44
+ ```
45
+
46
+ Guidelines:
47
+ - 150–160 characters
48
+ - Include the most important keyword naturally
49
+ - Make it a compelling reason to click, not a summary of the page's nav
50
+
51
+ ### 3. Fix page titles
52
+
53
+ SEO title = what Google shows in search results.
54
+
55
+ If `settings.default_seo_suffix` is set (e.g. " — Acme Studio"), every
56
+ page whose `seo_title` is empty will show `title + suffix`. That's usually
57
+ fine for inner pages; set an explicit `seo_title` only when you want
58
+ something different.
59
+
60
+ ```
61
+ update_site_settings {"default_seo_suffix": " — Acme Studio"}
62
+
63
+ update_page page_id="home" patch={
64
+ "seo_title": "Acme Studio — Inredningsdesign i Stockholm"
65
+ }
66
+ ```
67
+
68
+ ### 4. Add Open Graph images
69
+
70
+ Set `og_image` on pages that get shared on social media. If the site has
71
+ a branded hero image, upload it:
72
+
73
+ ```
74
+ upload_media_from_url url="https://..." alt="Acme Studio — Inredningsdesign"
75
+ # → returns cdn_url
76
+
77
+ batch_update_pages updates=[
78
+ {page_id: "home", patch: {og_image: "<cdn_url>"}},
79
+ {page_id: "om-oss", patch: {og_image: "<cdn_url>"}}
80
+ ]
81
+ ```
82
+
83
+ OG image dimensions: 1200×630px ideal. The platform doesn't resize —
84
+ use a correctly-sized source image.
85
+
86
+ ### 5. Add structured data (JSON-LD)
87
+
88
+ Typeroll auto-generates Article and Page schema, but you can override or
89
+ extend with custom JSON-LD per page. Example: LocalBusiness on the homepage.
90
+
91
+ ```
92
+ update_page page_id="home" patch={
93
+ "json_ld": "{\"@context\":\"https://schema.org\",\"@type\":\"LocalBusiness\",\"name\":\"Acme Studio\",\"url\":\"https://acme.se\",\"telephone\":\"+46812345\",\"address\":{\"@type\":\"PostalAddress\",\"streetAddress\":\"Drottninggatan 1\",\"addressLocality\":\"Stockholm\",\"postalCode\":\"111 51\",\"addressCountry\":\"SE\"}}"
94
+ }
95
+ ```
96
+
97
+ **Important:** JSON-LD goes in the `json_ld` field as a JSON *string*
98
+ (not a nested object). The renderer injects it inside
99
+ `<script type="application/ld+json">`.
100
+
101
+ Common schemas worth adding:
102
+ - Homepage: `LocalBusiness` or `Organization`
103
+ - About: `AboutPage`
104
+ - Contact: `ContactPage`
105
+ - Blog articles: auto-generated from `kind:"article"` + `author`
106
+ - Events: `Event` with `startDate`, `location`
107
+ - Products: `Product` with `offers`
108
+
109
+ ### 6. robots.txt
110
+
111
+ The default robots.txt allows all crawlers. Update if needed:
112
+
113
+ ```
114
+ update_site_settings {
115
+ "robots_txt": "User-agent: *\nAllow: /\nSitemap: https://acme.se/sitemap.xml"
116
+ }
117
+ ```
118
+
119
+ Typeroll doesn't generate a sitemap automatically in phase 1. If the
120
+ customer needs one, create a `/sitemap` page with HTML that lists all
121
+ published pages, or write a static `sitemap.xml` as a page with
122
+ `slug: "sitemap.xml"` and HTML-encoded XML (not recommended for large sites).
123
+
124
+ ### 7. Canonical URLs
125
+
126
+ Set `canonical_url` when a page has a duplicate (e.g. the same content
127
+ accessible via two slugs after a migration):
128
+
129
+ ```
130
+ update_page page_id="tjansterna" patch={
131
+ "canonical_url": "https://acme.se/tjanster",
132
+ "noindex": true
133
+ }
134
+ ```
135
+
136
+ ### 8. Language settings
137
+
138
+ ```
139
+ update_site_settings {"language": "sv"}
140
+ ```
141
+
142
+ Per-page override for multilingual content:
143
+ ```
144
+ update_page page_id="about-en" patch={"language": "en"}
145
+ ```
146
+
147
+ ### 9. Heading audit
148
+
149
+ Use `search_pages` to find structural problems:
150
+
151
+ ```
152
+ search_pages contains="<h1" # pages that have at least one H1
153
+ ```
154
+
155
+ Then `read_page` on pages that seem to have none or multiple. Fix via
156
+ `update_page patch={html_content: "<corrected HTML>"}`.
157
+
158
+ ### 10. Deploy
159
+
160
+ ```
161
+ trigger_deploy
162
+ get_deploy_status job_id=<id>
163
+ ```
164
+
165
+ ## Pitfalls
166
+
167
+ - **Don't stuff keywords.** Write descriptions for humans. Google ignores
168
+ `<meta name="keywords">` (not a field in Typeroll anyway).
169
+ - **JSON-LD is a string, not a nested field.** Pass the entire schema as
170
+ a JSON-encoded string in `json_ld`. The server escapes `</script` before
171
+ injection.
172
+ - **OG images need absolute URLs.** The `cdn.typeroll.com` URLs are always
173
+ absolute — use those.
174
+ - **`canonical_url` + `noindex` together.** If you noindex a page AND set
175
+ canonical, the canonical is redundant (noindexed pages don't pass equity).
176
+ Use one or the other.
177
+ - **Default suffix on homepage looks odd.** "Acme Studio — Acme Studio"
178
+ happens when title="Acme Studio" and suffix=" — Acme Studio". Set an
179
+ explicit `seo_title` for the homepage.