Skip to content

Local Development

There are two supported local-development loops:

  • Workbench development — the default loop for changing Lattice itself.
  • External app source-linking — an integration loop for testing an unreleased checkout inside a real Laravel app with Vite HMR.

Use package-linking only when you want publish-like verification. It exercises the built dist package and therefore requires rebuilding after JavaScript changes.

The repository ships with an Orchestra Testbench workbench app. This is the default way to develop Lattice because PHP, routes, fixtures, Vite, Tailwind, icons, and the React renderer are already wired together.

Install dependencies once:

Terminal window
composer install
npm install

Serve the workbench in two terminals — composer serve runs the PHP server (building the workbench app first), and npm run dev runs Vite for hot-reloading the React and CSS:

Terminal window
composer serve # PHP server
npm run dev # Vite HMR (separate terminal)

The workbench compiles Lattice directly from resources/js and imports the stylesheet directly from resources/css/lattice.css, so frontend changes are picked up by Vite without running the package build.

The canonical references are:

  • workbench/resources/js/app.tsx
  • workbench/resources/css/app.css
  • vite.config.ts

Use this when you need to try local Lattice changes inside an existing Laravel + Inertia React application. The PHP side is linked with Composer, and the React renderer is compiled from source by the consuming app’s Vite dev server.

This mode gives you HMR for Lattice’s TypeScript and CSS without running npm run build:lib.

In the consuming app’s composer.json, add a path repository and require the dev version:

{
"repositories": [
{
"type": "path",
"url": "../lattice",
"options": {
"symlink": true
}
}
]
}
Terminal window
composer require lattice-php/lattice:"*@dev" -W

Composer symlinks your checkout into vendor/lattice-php/lattice, so PHP changes are picked up by the app immediately.

Terminal window
npm install @lattice-php/lattice

Keep application imports on the public package name:

import LatticePage from "@lattice-php/lattice/page";
import { Provider, registry } from "@lattice-php/lattice";

Source-linking redirects that same public package name to your local checkout.

Add the Lattice helper to the consuming app’s vite.config.ts:

import { lattice } from "@lattice-php/lattice/vite";
import { defineConfig } from "vite";
const useLocalLattice = process.env.LATTICE_SOURCE === "1";
export default defineConfig({
plugins: [
lattice({
source: useLocalLattice,
icons: {
dirs: ["resources/icons"],
},
}),
// your existing Laravel, Inertia, React, and Tailwind plugins
],
});

This keeps normal development on the installed npm package, while LATTICE_SOURCE=1 switches Vite to the checkout under vendor/lattice-php/lattice. The helper configures the source aliases, Vite filesystem allow-list, React/Inertia dedupe, and the package-link Vitest dependency inline rule. It also registers the SVG sprite plugin with Lattice’s built-in icons and any app icon dirs you pass through icons.dirs.

If your editor or tsc does not follow Vite aliases, mirror the public package name in tsconfig.json:

{
"compilerOptions": {
"paths": {
"@lattice-php/lattice": ["./vendor/lattice-php/lattice/resources/js/index.ts"],
"@lattice-php/lattice/*": ["./vendor/lattice-php/lattice/resources/js/*"]
}
}
}

Keep the regular stylesheet import, then add a Tailwind source path for the linked checkout:

resources/css/app.css
@import "tailwindcss";
@import "tw-animate-css";
@import "@lattice-php/lattice/css";
@source "../../vendor/lattice-php/lattice/resources/js";
Terminal window
LATTICE_SOURCE=1 npm run dev

Vite now compiles the linked checkout directly. TypeScript and CSS changes in Lattice update through the consuming app’s dev server without a package build.

Source-linking is intended for browser development and HMR. It is not a reliable way to run the consuming app’s Vitest suite against a full Lattice checkout.

The checkout has its own node_modules, so React-based dependencies imported from Lattice source can resolve their own copy of React instead of the application’s copy. In tests this can show up as React’s “Invalid hook call” error. Browser dev and production builds dedupe correctly, but the test runner can still cross that dependency boundary.

For green test verification, switch back to package-linking or the published npm package so the app tests the built package surface rather than the checkout’s source tree.

Use package-linking when you want to test the same surface that npm publishes:

Terminal window
npm install @lattice-php/lattice@file:../lattice

This mode reads the package exports and dist files. It is closer to a release, but it is not a live source workflow. Run the package build after renderer changes:

Terminal window
cd ../lattice
npm run build:lib

For a continuously refreshed package-link build:

Terminal window
cd ../lattice
npm run build:lib:watch

Use source-linking for daily integration work, and package-linking for publish-like checks.