@stellisoft/stellify-mcp 0.1.37 → 0.1.38
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/dist/index.js +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/skills/wordpress-import.md +253 -200
package/dist/index.js
CHANGED
|
@@ -1509,7 +1509,7 @@ const SERVER_INSTRUCTIONS = `Stellify is a coding platform where code is stored
|
|
|
1509
1509
|
// Create MCP server
|
|
1510
1510
|
const server = new Server({
|
|
1511
1511
|
name: 'stellify-mcp',
|
|
1512
|
-
version: '0.1.
|
|
1512
|
+
version: '0.1.38',
|
|
1513
1513
|
}, {
|
|
1514
1514
|
capabilities: {
|
|
1515
1515
|
tools: {},
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/Stellify-Software-Ltd/stellify-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.1.
|
|
9
|
+
"version": "0.1.38",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "@stellisoft/stellify-mcp",
|
|
14
|
-
"version": "0.1.
|
|
14
|
+
"version": "0.1.38",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|
|
@@ -1,264 +1,317 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: wordpress-import
|
|
3
|
-
description: "Use this skill when importing WordPress sites into Stellify. Invoke with /wordpress-import to
|
|
3
|
+
description: "Use this skill when importing WordPress sites into Stellify. Invoke with /wordpress-import to analyse a WordPress project and generate resources for custom post types, taxonomies, and fields. Assumes standard WordPress models (Post, Page, Category, Tag, User, Media) are already scaffolded via Stellify."
|
|
4
4
|
license: MIT
|
|
5
|
+
icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>wordpress</title><path d="M3.42,12C3.42,10.76 3.69,9.58 4.16,8.5L8.26,19.72C5.39,18.33 3.42,15.4 3.42,12M17.79,11.57C17.79,12.3 17.5,13.15 17.14,14.34L16.28,17.2L13.18,8L14.16,7.9C14.63,7.84 14.57,7.16 14.11,7.19C14.11,7.19 12.72,7.3 11.82,7.3L9.56,7.19C9.1,7.16 9.05,7.87 9.5,7.9L10.41,8L11.75,11.64L9.87,17.27L6.74,8L7.73,7.9C8.19,7.84 8.13,7.16 7.67,7.19C7.67,7.19 6.28,7.3 5.38,7.3L4.83,7.29C6.37,4.96 9,3.42 12,3.42C14.23,3.42 16.27,4.28 17.79,5.67H17.68C16.84,5.67 16.24,6.4 16.24,7.19C16.24,7.9 16.65,8.5 17.08,9.2C17.41,9.77 17.79,10.5 17.79,11.57M12.15,12.75L14.79,19.97L14.85,20.09C13.96,20.41 13,20.58 12,20.58C11.16,20.58 10.35,20.46 9.58,20.23L12.15,12.75M19.53,7.88C20.2,9.11 20.58,10.5 20.58,12C20.58,15.16 18.86,17.93 16.31,19.41L18.93,11.84C19.42,10.62 19.59,9.64 19.59,8.77L19.53,7.88M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,21.54C17.26,21.54 21.54,17.26 21.54,12C21.54,6.74 17.26,2.46 12,2.46C6.74,2.46 2.46,6.74 2.46,12C2.46,17.26 6.74,21.54 12,21.54Z" /></svg>
|
|
5
6
|
metadata:
|
|
6
7
|
author: stellify
|
|
7
8
|
---
|
|
8
9
|
|
|
9
10
|
# WordPress Import Skill
|
|
10
11
|
|
|
11
|
-
You are importing a WordPress site into Stellify
|
|
12
|
+
You are importing a WordPress site into Stellify. This skill focuses on **analysing what's custom** about the WordPress site and generating only those elements. Standard WordPress functionality (Posts, Pages, Categories, Tags, Users, Media) is handled by Stellify's WordPress scaffold.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
## Step 1 — Verify WordPress Scaffold
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
Before proceeding, check that the Stellify WordPress scaffold has been run. Look for the presence of standard WordPress models in the Laravel project:
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
- `app/Models/Post.php`
|
|
19
|
+
- `app/Models/Page.php`
|
|
20
|
+
- `app/Models/Category.php`
|
|
21
|
+
- `app/Models/Tag.php`
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
If these don't exist, instruct the user:
|
|
20
24
|
|
|
21
|
-
> **
|
|
25
|
+
> **WordPress scaffold required**
|
|
22
26
|
>
|
|
23
|
-
>
|
|
27
|
+
> Before importing, you need to run the Stellify WordPress scaffold. This creates the standard models, controllers, and routes that every WordPress site uses.
|
|
24
28
|
>
|
|
25
|
-
>
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
> Run: `[scaffold command TBD]`
|
|
30
|
+
>
|
|
31
|
+
> Let me know when this is complete.
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
Do not proceed until the scaffold is in place.
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
## Step 2 — Analyse the WordPress Project
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
- **Structural partials**: header.php, footer.php, sidebar.php
|
|
35
|
-
- **Template parts**: anything in template-parts/ or patterns/
|
|
36
|
-
- **Functions**: functions.php (and any files it includes/requires)
|
|
37
|
-
- **Styles**: style.css, any CSS/SCSS files
|
|
38
|
-
- **Config**: theme.json if present (block theme configuration)
|
|
37
|
+
Perform a comprehensive analysis of the WordPress site to understand what's custom. This produces a report before any code generation happens.
|
|
39
38
|
|
|
40
|
-
|
|
39
|
+
### 2a. Identify the Active Theme
|
|
41
40
|
|
|
42
|
-
|
|
41
|
+
Look in `./wp-content/themes/` to find the active theme. If there are multiple themes, check for the most recently modified one, or the one with the most template files. If unsure, ask which theme to import.
|
|
43
42
|
|
|
44
|
-
|
|
43
|
+
Note whether it's a classic PHP theme or a block theme (presence of `theme.json` and HTML templates).
|
|
44
|
+
|
|
45
|
+
### 2b. Scan for Custom Post Types & Taxonomies
|
|
46
|
+
|
|
47
|
+
Read `functions.php` and any files it includes/requires. Extract:
|
|
48
|
+
|
|
49
|
+
- **Custom post types** via `register_post_type()` — capture name, labels, supports array, and any custom rewrite rules
|
|
50
|
+
- **Custom taxonomies** via `register_taxonomy()` — capture name, which post types it attaches to, hierarchical setting
|
|
51
|
+
|
|
52
|
+
Also check for CPT plugins that store configuration differently:
|
|
53
|
+
- Custom Post Type UI stores config in `wp_options` under `cptui_post_types` and `cptui_taxonomies`
|
|
54
|
+
- Pods, Toolset, and similar plugins have their own storage patterns
|
|
55
|
+
|
|
56
|
+
### 2c. Scan Plugins Directory
|
|
57
|
+
|
|
58
|
+
List the contents of `wp-content/plugins/` and categorise:
|
|
59
|
+
|
|
60
|
+
**Functionality plugins** (affect what the site does — need attention):
|
|
61
|
+
- WooCommerce — e-commerce (major rebuild)
|
|
62
|
+
- Advanced Custom Fields / ACF Pro — custom fields
|
|
63
|
+
- Gravity Forms / Contact Form 7 / WPForms — forms
|
|
64
|
+
- The Events Calendar — event post type
|
|
65
|
+
- Custom plugin folders (not from wordpress.org)
|
|
66
|
+
|
|
67
|
+
**Low priority** (usually don't need porting):
|
|
68
|
+
- Yoast SEO / Rank Math — SEO meta (can note fields but not critical)
|
|
69
|
+
- Caching plugins (W3 Total Cache, WP Rocket)
|
|
70
|
+
- Security plugins (Wordfence, Sucuri)
|
|
71
|
+
- Backup plugins
|
|
72
|
+
|
|
73
|
+
**Builder plugins** (affect how templates work):
|
|
74
|
+
- Elementor / Elementor Pro
|
|
75
|
+
- WPBakery / Visual Composer
|
|
76
|
+
- Divi Builder
|
|
77
|
+
- Beaver Builder
|
|
78
|
+
|
|
79
|
+
Note: If a builder plugin is present, templates may be stored in the database rather than theme files.
|
|
80
|
+
|
|
81
|
+
### 2d. Database Analysis
|
|
82
|
+
|
|
83
|
+
If database access is available (direct connection or SQL dump), run these diagnostic queries:
|
|
84
|
+
|
|
85
|
+
```sql
|
|
86
|
+
-- Custom post types in use (beyond standard post/page/attachment)
|
|
87
|
+
SELECT post_type, COUNT(*) as count
|
|
88
|
+
FROM wp_posts
|
|
89
|
+
WHERE post_status = 'publish'
|
|
90
|
+
AND post_type NOT IN ('post', 'page', 'attachment', 'revision', 'nav_menu_item', 'wp_template', 'wp_template_part', 'wp_global_styles', 'wp_navigation')
|
|
91
|
+
GROUP BY post_type
|
|
92
|
+
ORDER BY count DESC;
|
|
93
|
+
|
|
94
|
+
-- Custom taxonomies in use (beyond standard category/post_tag)
|
|
95
|
+
SELECT taxonomy, COUNT(*) as term_count
|
|
96
|
+
FROM wp_term_taxonomy
|
|
97
|
+
WHERE taxonomy NOT IN ('category', 'post_tag', 'nav_menu', 'link_category', 'post_format', 'wp_theme', 'wp_template_part_area')
|
|
98
|
+
GROUP BY taxonomy
|
|
99
|
+
ORDER BY term_count DESC;
|
|
100
|
+
|
|
101
|
+
-- Custom meta keys (reveals ACF fields, custom meta)
|
|
102
|
+
-- Excludes WordPress internal keys (prefixed with _)
|
|
103
|
+
SELECT meta_key, COUNT(*) as usage_count
|
|
104
|
+
FROM wp_postmeta
|
|
105
|
+
WHERE meta_key NOT LIKE '\_%'
|
|
106
|
+
GROUP BY meta_key
|
|
107
|
+
ORDER BY usage_count DESC
|
|
108
|
+
LIMIT 30;
|
|
109
|
+
|
|
110
|
+
-- ACF field groups (if ACF is used)
|
|
111
|
+
SELECT post_title, post_name
|
|
112
|
+
FROM wp_posts
|
|
113
|
+
WHERE post_type = 'acf-field-group'
|
|
114
|
+
AND post_status = 'publish';
|
|
115
|
+
|
|
116
|
+
-- Shortcodes in content (indicates embedded functionality)
|
|
117
|
+
SELECT post_type, COUNT(*) as posts_with_shortcodes
|
|
118
|
+
FROM wp_posts
|
|
119
|
+
WHERE post_content REGEXP '\\[[a-zA-Z0-9_-]+.*\\]'
|
|
120
|
+
AND post_status = 'publish'
|
|
121
|
+
GROUP BY post_type;
|
|
122
|
+
|
|
123
|
+
-- Gutenberg blocks in use (for block themes)
|
|
124
|
+
SELECT
|
|
125
|
+
SUBSTRING_INDEX(SUBSTRING_INDEX(post_content, '<!-- wp:', -1), ' ', 1) as block_type,
|
|
126
|
+
COUNT(*) as usage_count
|
|
127
|
+
FROM wp_posts
|
|
128
|
+
WHERE post_content LIKE '%<!-- wp:%'
|
|
129
|
+
AND post_status = 'publish'
|
|
130
|
+
GROUP BY block_type
|
|
131
|
+
ORDER BY usage_count DESC
|
|
132
|
+
LIMIT 20;
|
|
133
|
+
```
|
|
45
134
|
|
|
46
|
-
|
|
47
|
-
- **Taxonomies** registered via `register_taxonomy()` → these become models or enums
|
|
48
|
-
- **Navigation menus** registered via `register_nav_menus()` → these define nav structure
|
|
49
|
-
- **Widget areas** registered via `register_sidebar()` → note for layout
|
|
50
|
-
- **Enqueued scripts/styles** via `wp_enqueue_script/style()` → note any JS dependencies
|
|
51
|
-
- **Custom image sizes** via `add_image_size()` → note for media handling
|
|
52
|
-
- **Theme supports** via `add_theme_support()` → note post formats, thumbnails, etc.
|
|
53
|
-
- **Shortcodes** via `add_shortcode()` → these become Blade includes or components
|
|
54
|
-
- **AJAX handlers** via `wp_ajax_*` → these become API routes
|
|
55
|
-
- **Any included files** → read those too
|
|
135
|
+
### 2e. Produce Analysis Report
|
|
56
136
|
|
|
57
|
-
|
|
137
|
+
Present a structured summary before proceeding:
|
|
58
138
|
|
|
59
|
-
|
|
139
|
+
```
|
|
140
|
+
## WordPress Site Analysis
|
|
141
|
+
|
|
142
|
+
### Theme
|
|
143
|
+
- Name: theme-name
|
|
144
|
+
- Type: Classic PHP / Block theme
|
|
145
|
+
- Template files: [count]
|
|
146
|
+
|
|
147
|
+
### Content Summary
|
|
148
|
+
- Posts: [count]
|
|
149
|
+
- Pages: [count]
|
|
150
|
+
- [custom-type]: [count]
|
|
151
|
+
|
|
152
|
+
### Custom Post Types
|
|
153
|
+
| Name | Slug | Supports | Count |
|
|
154
|
+
|------|------|----------|-------|
|
|
155
|
+
| Portfolio | project | title, editor, thumbnail | 34 |
|
|
156
|
+
| Testimonial | testimonial | title, editor | 12 |
|
|
157
|
+
|
|
158
|
+
### Custom Taxonomies
|
|
159
|
+
| Name | Slug | Attached To | Hierarchical | Terms |
|
|
160
|
+
|------|------|-------------|--------------|-------|
|
|
161
|
+
| Project Type | project_type | project | Yes | 5 |
|
|
162
|
+
|
|
163
|
+
### Custom Fields (non-standard meta keys)
|
|
164
|
+
| Key | Used By | Count |
|
|
165
|
+
|-----|---------|-------|
|
|
166
|
+
| project_client | project | 34 |
|
|
167
|
+
| project_url | project | 34 |
|
|
168
|
+
| testimonial_company | testimonial | 12 |
|
|
169
|
+
|
|
170
|
+
### Plugins Requiring Attention
|
|
171
|
+
- Advanced Custom Fields Pro — field definitions above
|
|
172
|
+
- Contact Form 7 — 2 forms found
|
|
173
|
+
|
|
174
|
+
### Content Flags
|
|
175
|
+
- 15 posts contain shortcodes (will need processing during content migration)
|
|
176
|
+
- Page builder detected: Elementor (some layouts stored in database)
|
|
177
|
+
|
|
178
|
+
### Generation Plan
|
|
179
|
+
**Will generate:**
|
|
180
|
+
- Model: Project (custom post type)
|
|
181
|
+
- Model: Testimonial (custom post type)
|
|
182
|
+
- Model: ProjectType (custom taxonomy)
|
|
183
|
+
- Add fields to models: client, url, company
|
|
184
|
+
|
|
185
|
+
**Standard (already scaffolded):**
|
|
186
|
+
- Post, Page, Category, Tag, User, Media
|
|
187
|
+
|
|
188
|
+
**Manual attention needed:**
|
|
189
|
+
- Contact forms (2) — recreate in Laravel
|
|
190
|
+
- Shortcodes in content — process during migration
|
|
191
|
+
- Elementor layouts — extract design intent from theme templates
|
|
192
|
+
```
|
|
60
193
|
|
|
61
|
-
|
|
62
|
-
- **Controllers:** One per model with index/show actions
|
|
63
|
-
- **Routes:** Match WordPress URL structure (archive at `/`, singles at `/{slug}`, taxonomies at `/category/{slug}`)
|
|
64
|
-
- **Views:** Mirror WordPress template hierarchy — layout from header+footer, index/show views per post type, partials from template-parts
|
|
65
|
-
- **Migrations (Mode B only):** One per model with fields from WordPress core + any custom fields found in templates
|
|
194
|
+
After presenting the report, ask:
|
|
66
195
|
|
|
67
|
-
|
|
196
|
+
> Does this analysis look correct? Ready to proceed with generating the custom resources?
|
|
68
197
|
|
|
69
|
-
|
|
198
|
+
## Step 3 — Generate Custom Resources
|
|
70
199
|
|
|
71
|
-
|
|
200
|
+
For each custom post type and taxonomy identified, create the necessary Laravel resources using Stellify MCP tools.
|
|
72
201
|
|
|
73
|
-
|
|
202
|
+
### 3a. Custom Post Type Models
|
|
74
203
|
|
|
75
|
-
|
|
204
|
+
For each custom post type, use `create_resources` with `api: false`:
|
|
76
205
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
206
|
+
**Model requirements:**
|
|
207
|
+
- Table name matching the post type slug (e.g., `projects`, `testimonials`)
|
|
208
|
+
- Standard fields: `title`, `slug`, `content`, `excerpt`, `status`, `published_at`, `author_id`
|
|
209
|
+
- Custom fields identified from meta analysis
|
|
210
|
+
- `getRouteKeyName()` returning `'slug'` for URL-friendly routing
|
|
211
|
+
- Relationships to custom taxonomies
|
|
83
212
|
|
|
84
|
-
|
|
213
|
+
**Migration requirements:**
|
|
214
|
+
- All standard fields plus custom fields
|
|
215
|
+
- Foreign keys to users table for author
|
|
216
|
+
- Indexes on slug, status, published_at
|
|
85
217
|
|
|
86
|
-
**
|
|
218
|
+
**Controller requirements:**
|
|
219
|
+
- `index()` returning paginated published items
|
|
220
|
+
- `show($model)` returning single item
|
|
221
|
+
- Return arrays (Stellify convention), not views or JSON
|
|
87
222
|
|
|
88
|
-
|
|
223
|
+
Example model structure:
|
|
89
224
|
|
|
90
225
|
```php
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
protected $
|
|
94
|
-
|
|
226
|
+
class Project extends Model
|
|
227
|
+
{
|
|
228
|
+
protected $fillable = [
|
|
229
|
+
'title', 'slug', 'content', 'excerpt',
|
|
230
|
+
'status', 'published_at', 'author_id',
|
|
231
|
+
'client', 'url', // custom fields
|
|
232
|
+
];
|
|
233
|
+
|
|
234
|
+
protected $casts = [
|
|
235
|
+
'published_at' => 'datetime',
|
|
236
|
+
];
|
|
95
237
|
|
|
96
|
-
// Enable slug-based route model binding (WordPress uses post_name for slugs)
|
|
97
238
|
public function getRouteKeyName(): string
|
|
98
239
|
{
|
|
99
|
-
return '
|
|
240
|
+
return 'slug';
|
|
100
241
|
}
|
|
101
242
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return $
|
|
105
|
-
->where('post_type', 'post');
|
|
243
|
+
public function author(): BelongsTo
|
|
244
|
+
{
|
|
245
|
+
return $this->belongsTo(User::class, 'author_id');
|
|
106
246
|
}
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
Key WordPress table mappings:
|
|
111
|
-
- Posts & Pages → `wp_posts` (distinguished by `post_type` column: 'post', 'page', or custom types)
|
|
112
|
-
- Categories & Tags → `wp_terms` + `wp_term_taxonomy` + `wp_term_relationships`
|
|
113
|
-
- Users → `wp_users`
|
|
114
|
-
- Post meta / custom fields → `wp_postmeta`
|
|
115
|
-
- Comments → `wp_comments`
|
|
116
|
-
- Navigation menus → `wp_posts` with `post_type = 'nav_menu_item'` + `wp_terms` with taxonomy `nav_menu`
|
|
117
|
-
|
|
118
|
-
In Blade templates, use WordPress column names:
|
|
119
|
-
- `$post->post_title` (not `$post->title`)
|
|
120
|
-
- `$post->post_content` (not `$post->content`)
|
|
121
|
-
- `$post->post_excerpt` (not `$post->excerpt`)
|
|
122
|
-
- `$post->post_name` (this is the slug)
|
|
123
|
-
- `$post->post_date` (not `$post->published_at`)
|
|
124
|
-
- `$post->post_status` (not `$post->status`)
|
|
125
|
-
|
|
126
|
-
**If Mode B (fresh database):**
|
|
127
|
-
|
|
128
|
-
Create new resources with clean Laravel migrations for each model identified in Step 4. Use clean column names (`title`, `slug`, `content`, `excerpt`, `status`, `published_at`, etc.). After the import is complete, suggest a data migration SQL query or artisan command that maps data from the WordPress tables to the new schema.
|
|
129
|
-
|
|
130
|
-
For each model with a `slug` field, add `getRouteKeyName()`:
|
|
131
|
-
|
|
132
|
-
```php
|
|
133
|
-
public function getRouteKeyName(): string
|
|
134
|
-
{
|
|
135
|
-
return 'slug';
|
|
136
|
-
}
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### 5b. Refine Controller Methods
|
|
140
247
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
public function index(): array
|
|
146
|
-
{
|
|
147
|
-
return ['posts' => Post::where('status', 'published')->latest('published_at')->paginate(10)];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
public function show(Post $post): array
|
|
151
|
-
{
|
|
152
|
-
return ['post' => $post];
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// WRONG — do not return JSON
|
|
156
|
-
public function index()
|
|
157
|
-
{
|
|
158
|
-
return Post::where('status', 'published')->get();
|
|
159
|
-
}
|
|
248
|
+
public function projectTypes(): BelongsToMany
|
|
249
|
+
{
|
|
250
|
+
return $this->belongsToMany(ProjectType::class);
|
|
251
|
+
}
|
|
160
252
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
253
|
+
public function scopePublished($query)
|
|
254
|
+
{
|
|
255
|
+
return $query->where('status', 'published');
|
|
256
|
+
}
|
|
165
257
|
}
|
|
166
258
|
```
|
|
167
259
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
### 5c. Create Routes
|
|
171
|
-
Create route entries mapping URLs to controller methods.
|
|
172
|
-
|
|
173
|
-
### 5d. Create the Layout (layouts/app.blade.php)
|
|
174
|
-
Read header.php and footer.php. Create a single Blade layout that combines:
|
|
175
|
-
- The HTML structure from header.php (doctype, head, opening body, nav)
|
|
176
|
-
- `@yield('content')` for page content
|
|
177
|
-
- The structure from footer.php (closing elements, footer content)
|
|
178
|
-
|
|
179
|
-
Translate WordPress functions to Blade:
|
|
180
|
-
- `wp_head()` → `@vite(['resources/css/app.css', 'resources/js/app.js'])` and `<meta>` tags
|
|
181
|
-
- `wp_footer()` → nothing needed (Vite handles it)
|
|
182
|
-
- `wp_nav_menu()` → `@include('partials.nav')`
|
|
183
|
-
- `bloginfo('name')` → `{{ config('app.name') }}`
|
|
184
|
-
- `bloginfo('description')` → `{{ config('app.description', '') }}`
|
|
185
|
-
- `body_class()` → appropriate Tailwind classes
|
|
186
|
-
- `language_attributes()` → `lang="{{ str_replace('_', '-', app()->getLocale()) }}"`
|
|
187
|
-
|
|
188
|
-
### 5e. Create Blade Views
|
|
189
|
-
For each WordPress template file, read the PHP and create the equivalent Blade view using `html_to_elements`. **All views use `@extends('layouts.app')` and `@section('content')`.**
|
|
190
|
-
|
|
191
|
-
**⚠️ Multiple Root Elements:** When converting HTML with multiple root-level elements (e.g., `<header>`, `<main>`, `<footer>`), only the first root element gets attached to the route. Make separate `html_to_elements` calls for each root element.
|
|
260
|
+
### 3b. Custom Taxonomy Models
|
|
192
261
|
|
|
193
|
-
|
|
262
|
+
For each custom taxonomy:
|
|
194
263
|
|
|
195
|
-
|
|
264
|
+
**Model requirements:**
|
|
265
|
+
- Table name matching taxonomy slug (e.g., `project_types`)
|
|
266
|
+
- Fields: `name`, `slug`, `description`, `parent_id` (if hierarchical)
|
|
267
|
+
- `getRouteKeyName()` returning `'slug'`
|
|
268
|
+
- Relationship to associated post types via pivot table
|
|
196
269
|
|
|
197
|
-
**
|
|
270
|
+
**Migration requirements:**
|
|
271
|
+
- Main taxonomy table
|
|
272
|
+
- Pivot table linking to each associated post type (e.g., `project_project_type`)
|
|
198
273
|
|
|
199
|
-
|
|
200
|
-
|-----------|----------------|----------------|-------------------|
|
|
201
|
-
| `the_title()` | `{{ $item->post_title }}` | `{{ $item->title }}` | `textField: "title"` |
|
|
202
|
-
| `the_content()` | `{!! $item->post_content !!}` | `{!! $item->content !!}` | statement with code |
|
|
203
|
-
| `the_excerpt()` | `{{ $item->post_excerpt }}` | `{{ $item->excerpt }}` | `textField: "excerpt"` |
|
|
204
|
-
| `the_permalink()` | `{{ route('posts.show', $item->post_name) }}` | `{{ route('posts.show', $item->slug) }}` | `hrefExpression: "..."` |
|
|
205
|
-
| `the_date()` | `{{ $item->post_date->format('d M Y') }}` | `{{ $item->published_at->format('d M Y') }}` | statement with code |
|
|
206
|
-
| `the_author()` | `{{ $item->author->display_name }}` | `{{ $item->author->name }}` | statement with code |
|
|
207
|
-
| `get_template_part()` | `@include('partials.post-card', ['post' => $item])` | same | s-directive |
|
|
208
|
-
| `have_posts()` | `@foreach($posts as $item)` | same | s-directive pair |
|
|
274
|
+
### 3c. Routes
|
|
209
275
|
|
|
210
|
-
|
|
276
|
+
Create routes following WordPress URL conventions where sensible:
|
|
211
277
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
- `<!-- wp:post-excerpt -->` → `@if($item->post_excerpt)` ... `@endif`
|
|
217
|
-
- `<!-- wp:post-comments -->` → `@if($item->comments->count() > 0)` ... `@endif`
|
|
218
|
-
- `<!-- wp:query-no-results -->` → `@if($posts->isEmpty())` ... `@endif` (outside loop)
|
|
219
|
-
|
|
220
|
-
**Iteration (The Loop):**
|
|
278
|
+
```php
|
|
279
|
+
// Custom post type archives and singles
|
|
280
|
+
Route::get('/projects', [ProjectController::class, 'index'])->name('projects.index');
|
|
281
|
+
Route::get('/projects/{project}', [ProjectController::class, 'show'])->name('projects.show');
|
|
221
282
|
|
|
222
|
-
|
|
283
|
+
// Custom taxonomy archives
|
|
284
|
+
Route::get('/project-type/{projectType}', [ProjectTypeController::class, 'show'])->name('project-types.show');
|
|
285
|
+
```
|
|
223
286
|
|
|
224
|
-
|
|
225
|
-
1. Do NOT pass raw Blade syntax to `html_to_elements` — it will be stored literally
|
|
226
|
-
2. Create clean HTML first, then use `update_element` to add dynamic attributes:
|
|
227
|
-
- `textField: "title"` → outputs `{{ $item->title }}`
|
|
228
|
-
- `hrefField: "slug"` → outputs `href="{{ $item->slug }}"`
|
|
229
|
-
- `srcField: "featured_image"` → outputs `src="{{ $item->featured_image }}"`
|
|
230
|
-
3. For complex expressions (route helpers, method calls), use:
|
|
231
|
-
- `hrefExpression: "{{ route('posts.show', $item->slug) }}"`
|
|
232
|
-
- `srcExpression: "{{ $item->featured_image }}"`
|
|
233
|
-
4. For text with Blade code, create a statement with `create_statement_with_code`, then add its UUID to the element's `statements` array via `update_element`
|
|
287
|
+
## Step 4 — Document Manual Tasks
|
|
234
288
|
|
|
235
|
-
|
|
236
|
-
```
|
|
237
|
-
1. s-directive with statement: "@foreach($posts as $item)"
|
|
238
|
-
2. article element (content to repeat)
|
|
239
|
-
3. s-directive with statement: "@endforeach"
|
|
240
|
-
```
|
|
289
|
+
Create a summary of items requiring manual attention:
|
|
241
290
|
|
|
242
|
-
###
|
|
243
|
-
|
|
291
|
+
### Forms
|
|
292
|
+
List each form found with fields and purpose. The user will need to recreate these using Laravel form handling or a package like Laravel Livewire.
|
|
244
293
|
|
|
245
|
-
###
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
- WordPress post grid → `<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">`
|
|
294
|
+
### Shortcodes in Content
|
|
295
|
+
List shortcodes found and their apparent purpose. These will need to be:
|
|
296
|
+
1. Processed during content migration (find/replace with HTML)
|
|
297
|
+
2. Or converted to Blade components if they need to remain dynamic
|
|
250
298
|
|
|
251
|
-
|
|
299
|
+
### Plugin Functionality
|
|
300
|
+
For significant plugins (WooCommerce, membership plugins, booking systems), note that this functionality needs separate planning and is outside the scope of this import.
|
|
252
301
|
|
|
253
|
-
|
|
302
|
+
### Content Migration
|
|
303
|
+
Note that content migration is a separate step. The user will need to:
|
|
304
|
+
1. Export content from WordPress (WP-CLI, plugin, or direct SQL)
|
|
305
|
+
2. Transform data to match new schema
|
|
306
|
+
3. Import into Laravel database
|
|
307
|
+
4. Process/clean embedded shortcodes
|
|
308
|
+
5. Migrate media files and update URLs
|
|
254
309
|
|
|
255
310
|
## Important Rules
|
|
256
311
|
|
|
257
|
-
- **
|
|
258
|
-
- **
|
|
259
|
-
- **
|
|
260
|
-
- **
|
|
261
|
-
- **
|
|
262
|
-
- **
|
|
263
|
-
- **Be pragmatic** — focus on the core templates that define the site's main pages. Skip hyper-specific template variations unless they're clearly important.
|
|
264
|
-
- **Content handling depends on database mode** — In Mode A (existing DB), the content is already there via the WordPress tables. In Mode B (fresh DB), content is separate and can be migrated later.
|
|
312
|
+
- **Analysis first** — Always complete the full analysis before generating any code
|
|
313
|
+
- **Only generate custom elements** — Standard WordPress models come from the scaffold
|
|
314
|
+
- **Fresh database only** — This skill assumes a clean Laravel database, not connecting to WordPress tables
|
|
315
|
+
- **No template conversion** — Visual design/styling is handled by a separate skill
|
|
316
|
+
- **Document unknowns** — Flag anything that can't be automatically converted
|
|
317
|
+
- **Be pragmatic** — Focus on post types and taxonomies actually in use (have content), not just registered
|