Files

9.0 KiB

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:

https://gitea.websimple.com/templates/wp-boilerplate

Prefer this shape for a Websimple WordPress conversion:

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:

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:

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:

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.