200 lines
9.0 KiB
Markdown
200 lines
9.0 KiB
Markdown
# WP Lovable
|
|
|
|
Use this skill when turning a Lovable export into a Websimple WordPress project, especially when the output should become a normal WordPress marketing site rather than a detached static React app.
|
|
|
|
Use related references as needed:
|
|
|
|
- `references/wp-project.md` and `references/wp-local-site.md` for resolving, creating, provisioning, or checking local WordPress sites.
|
|
- `references/websimple-stack.md` for local stack protocol/domain configuration and Traefik SSL routing.
|
|
- `references/wp-kaliroots.md` for Kaliroots child-theme structure and template wrapper decisions.
|
|
- `references/wp-theme-dev.md` for general theme PHP organization.
|
|
- `references/wp-assets.md` for frontend source, Vite/Tailwind, build output, and enqueue integration.
|
|
- `references/wp-acf.md` for editable content models, local JSON, options pages, and section data.
|
|
- `references/wp-browser.md` for frontend/wp-admin smoke tests and visual checks.
|
|
|
|
## Core Approach
|
|
|
|
Keep WordPress as the application shell and source of truth. Treat the Lovable project as frontend source material to port into the active theme, not as a static app to drop into WordPress unchanged.
|
|
|
|
For new Websimple WordPress projects, start from the `wp-boilerplate` template unless the user or project context says otherwise:
|
|
|
|
```text
|
|
https://gitea.websimple.com/templates/wp-boilerplate
|
|
```
|
|
|
|
Prefer this shape for a Websimple WordPress conversion:
|
|
|
|
```text
|
|
wp-content/themes/{child-theme}/
|
|
acf-json/
|
|
includes/
|
|
core/
|
|
assets.php
|
|
theme-setup.php
|
|
vendors/
|
|
acf.php
|
|
gravityforms.php
|
|
templates/
|
|
src/
|
|
components/
|
|
hooks/
|
|
lib/
|
|
pages/
|
|
main.tsx
|
|
index.css
|
|
dist/
|
|
package.json
|
|
vite.config.ts
|
|
tailwind.config.*
|
|
postcss.config.*
|
|
```
|
|
|
|
Adapt the paths to the existing theme. Do not reorganize established projects broadly without approval.
|
|
|
|
## First Pass
|
|
|
|
Before editing, inspect both sides:
|
|
|
|
1. Identify the Lovable source project, its framework, routes, components, CSS/Tailwind setup, static assets, forms, and data assumptions.
|
|
2. Identify the WordPress site, active theme, parent theme, template wrappers, ACF setup, menus, SEO plugin, forms plugin, and asset pipeline.
|
|
3. Check git status in the WordPress project and avoid touching unrelated dirty files.
|
|
4. Decide which Lovable pieces are presentation components and which are actually content, navigation, SEO, media, forms, or settings that belong in WordPress.
|
|
|
|
Use `rg --files`, `package.json`, `vite.config.*`, `tailwind.config.*`, `src/`, `includes/`, `templates/`, and `acf-json/` as the main inspection points.
|
|
|
|
## Porting Rules
|
|
|
|
Port reusable React/Tailwind UI into the child theme `src/`. Keep TypeScript path aliases, component names, and Tailwind conventions only when they still make sense inside the theme.
|
|
|
|
Move editable site concerns into WordPress:
|
|
|
|
- page and section content into pages, ACF fields, flexible content, or options pages;
|
|
- navigation into WordPress menus;
|
|
- images and downloadable media into the media library or ACF media fields;
|
|
- SEO title, canonical, OpenGraph/Twitter, schema, and indexing behavior into the SEO plugin and WordPress-rendered document head;
|
|
- contact forms into Gravity Forms or the existing WordPress form plugin;
|
|
- global settings such as phone, address, social links, CTAs, and layout toggles into ACF options when they are truly site-wide.
|
|
|
|
React should render serialized WordPress data with safe fallbacks. It should not become the CMS.
|
|
|
|
## Routing And SEO
|
|
|
|
Avoid pure React Router SPA behavior for normal WordPress marketing pages.
|
|
|
|
Prefer WordPress-rendered URLs and document navigation so SEO plugins can output correct per-page titles, canonical URLs, OpenGraph/Twitter tags, JSON-LD, breadcrumbs, and indexing controls.
|
|
|
|
Use React routing only when the requested result is an actual app-like interface where client-side routing is intentional. For standard pages, replace internal SPA links with normal document links and let WordPress resolve the route.
|
|
|
|
## Bundler Pattern
|
|
|
|
For modern Lovable migrations, Vite in the child theme is usually the cleanest fit:
|
|
|
|
- keep the app entry at `src/main.tsx` or the existing theme entrypoint;
|
|
- keep Tailwind/PostCSS config in the theme root;
|
|
- use an alias such as `@` to point at `src` only if the source already uses it or it improves the port;
|
|
- output production assets to `dist/`;
|
|
- generate `dist/.vite/manifest.json`;
|
|
- set production `base` to `/wp-content/themes/{child-theme}/dist/` when assets are served from the theme;
|
|
- have PHP enqueue code read the manifest rather than hardcoding hashed filenames;
|
|
- mark Vite client and app scripts as `type="module"` when needed.
|
|
|
|
For local development, bind Vite to the local WordPress host on a fixed port and expose CORS headers so the WordPress page can load the dev server assets.
|
|
|
|
Mirror Mooncake's local SSL pattern when the Websimple stack uses HTTPS:
|
|
|
|
```ts
|
|
import basicSsl from "@vitejs/plugin-basic-ssl";
|
|
import { homedir } from "os";
|
|
import { resolve } from "path";
|
|
|
|
const isHttps = process.env.LOCAL_PROTOCOL === "https";
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
...(isHttps ? [basicSsl({ certDir: resolve(homedir(), ".local/share/certs") })] : []),
|
|
],
|
|
server: {
|
|
host: `${resolve(__dirname, "../../..").split("/").pop()}.${process.env.TLD || "ledevsimple.ca"}`,
|
|
port: 3001,
|
|
strictPort: true,
|
|
headers: { "Access-Control-Allow-Origin": "*" },
|
|
},
|
|
});
|
|
```
|
|
|
|
Resolve `LOCAL_PROTOCOL` and `TLD` from the local stack configuration whenever possible:
|
|
|
|
- `LOCAL_PROTOCOL` should match `$WEBSIMPLE_STACK_PROTOCOL`, usually `https` when Traefik serves local sites with TLS.
|
|
- `TLD` should match `$WEBSIMPLE_STACK_DOMAIN`, for example `ledevsimple.ca`.
|
|
- Prefer package scripts, shell environment, or generated local env files that pass those values through to Vite.
|
|
- If the stack protocol cannot be discovered, inspect `references/websimple-stack.md` config and the current local site URL before choosing `http` or `https`.
|
|
|
|
Do not let leftover `dist/.vite/manifest.json` silently force production mode if the local workflow expects the dev server. Prefer an explicit local/dev switch, an environment constant, or a detection strategy that matches the project's generated-output policy.
|
|
|
|
## PHP Integration
|
|
|
|
Keep PHP integration small and explicit:
|
|
|
|
- enqueue assets from `includes/core/assets.php` or the existing asset module;
|
|
- localize or inline only the WordPress data React needs to render;
|
|
- keep data preparation in helpers/includes when it becomes non-trivial;
|
|
- keep template files responsible for mounting the frontend and providing page context;
|
|
- keep ACF and vendor integrations in the existing vendor/module files.
|
|
|
|
For Kaliroots child themes, use Kaliroots wrapper and template conventions instead of inventing top-level WordPress templates.
|
|
|
|
## Forms
|
|
|
|
Do not rebuild normal WordPress forms in React just because the Lovable export included form markup.
|
|
|
|
Prefer a WordPress-native form flow:
|
|
|
|
1. Add an ACF field for a form selector or section configuration.
|
|
2. Render the selected Gravity Form or existing form plugin output in PHP or through a focused React wrapper fed by WordPress data.
|
|
3. Style the generated form in theme source CSS.
|
|
4. Verify submit behavior, validation, notifications, spam protection, and accessibility in the browser.
|
|
|
|
Only build a custom React form when the project specifically needs custom app behavior and the backend handling is clear.
|
|
|
|
## What To Avoid
|
|
|
|
- Do not drop the Lovable export into WordPress as a static page dump.
|
|
- Do not make WordPress serve a one-route SPA for normal marketing content.
|
|
- Do not hard-code editor-controlled content, layout settings, form IDs, media, menus, or SEO metadata in React.
|
|
- Do not edit compiled `dist/` assets manually when source exists.
|
|
- Do not migrate build tools, package managers, or theme architecture as a side effect unless the user approved that scope.
|
|
- Do not assume Lovable's placeholder copy, mock data, or generated routes are production information.
|
|
- Do not use manifest existence alone as the only dev/prod signal if generated output may be checked in or left over locally.
|
|
|
|
## Verification
|
|
|
|
Use the smallest checks that cover the migration risk:
|
|
|
|
```bash
|
|
pnpm build
|
|
find wp-content/themes/{child-theme} -name '*.php' -print0 | xargs -0 -n1 php -l
|
|
```
|
|
|
|
Then smoke-test representative URLs in the browser:
|
|
|
|
- home page;
|
|
- at least one inner page;
|
|
- contact/form page;
|
|
- mobile viewport;
|
|
- browser console;
|
|
- SEO/head output for title, canonical, OpenGraph/Twitter, JSON-LD, and no accidental SPA-only metadata.
|
|
|
|
Report changed source files, generated files, existing dirty files left untouched, and any checks that could not run.
|
|
|
|
## Reference Pattern
|
|
|
|
The first known conversion following this pattern was:
|
|
|
|
```text
|
|
Lovable source: https://github.com/Moonthewhite/chemineeschaleurs
|
|
WordPress site: https://gitea.websimple.com/wp-sites/chemineeschaleurs
|
|
Child theme: wp-content/themes/cheminees
|
|
```
|
|
|
|
That project used a Kaliroots child theme, React/Tailwind source under `src/`, Vite output under `dist/`, ACF local JSON under `acf-json/`, PHP enqueueing under `includes/core/assets.php`, WordPress/ACF-owned section layout settings, and Gravity Forms for the contact form.
|