Appearance
Development Setup
This page sets up a Magento project for working on Lynx-based code: your own modules, components and themes. For a plain store install, Installation is enough.
Requirements
| Version | |
|---|---|
| Magento | Magento Open Source 2.4 |
| PHP | 8.2 or newer, within the versions your Magento release supports |
| Node.js | 22.12 or newer, with npm, wherever the frontend is built |
Node.js is only needed to build. The store itself runs on PHP alone, unless you run the SSR renderer as a Node.js process.
Lynx is a storefront stack of its own and cannot be combined with Hyvä: the two render the storefront in different ways (Hyvä: layout XML and .phtml with Alpine.js; Lynx: Vue components on Inertia.js). Do not install both, and expect an extension's Hyvä compatibility module to do nothing on Lynx.
Installing the packages
Install Lynx as on a store, following Installation; the packages are listed in Packages. Turning off Magento's merging and Inline Translation applies to development stores too.
Keep packages inside the project root
The Vite dev server only serves files inside the Magento root. Modules and themes in app/code, app/design or vendor are fine.
Your own module
A module that adds Lynx pages or components depends on the Lynx modules it uses. Declare them in composer.json and in etc/module.xml, so your di.xml entries merge after theirs:
xml
<!-- etc/module.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Vendor_Module">
<sequence>
<module name="OOCS_LynxComponent"/>
<module name="OOCS_LynxInertia"/>
<module name="OOCS_LynxPageBuilder"/>
</sequence>
</module>
</config>Frontend sources go in view/frontend/lynx/vue/src. See Creating Components.
Store configuration
- Assign Lynx Vue (or your child theme) to the store view in Content › Design › Configuration.
- Keep Magento's CSS merging, JS merging, JS bundling, "move JS to bottom" and Inline Translation off for Lynx store views. The commands are in Installation.
- Keep
Magento_Wishlistenabled: Lynx replaces its customer-data section. - Pick a design in Stores › Configuration › Lynx › Theme Settings (the default one works for development).
Setting up a theme
Every Lynx theme has a lynx/ folder with its package.json, Vite config and entry point. That folder is its own npm project with its own node_modules (about 470 MB for Lynx Vue). Modules contribute sources from view/frontend/lynx/vue/src.
The theme's lynx/package.json is committed and no command writes it. Besides the theme's own packages (ESLint, fonts…), it declares the key the setup needs:
json
"workspaces": [".lynx"]Set up the themes you build:
bash
bin/magento lynx:theme:setup OOCS_LynxVueThe command writes <theme>/lynx/.lynx/package.json, a generated package (gitignored) that holds:
| Key | Content |
|---|---|
dependencies | The npm packages of the Lynx build kit (@oocs/lynx-vue) and of every enabled module that has a view/frontend/lynx/vue/package.json. Packages the theme declares itself are left out. |
lynx.modules | Every enabled module that has a view/frontend/lynx/vue/src folder, mapped to its folder. Only these modules are compiled into the bundle. |
lynx.parents | The folders of the parent themes, so the build can resolve overrides |
It then runs npm install in the theme's lynx/ folder when that package changed. When two sources (two modules, or a module and the theme) pin the same package to different versions, setup stops and names both. Without theme names, it sets up every theme set up before; --list shows the Lynx themes the installation has.
A module brings npm packages by listing them in its own view/frontend/lynx/vue/package.json; its sources are built either way. Nobody runs npm install in a module. To add a package to a theme only, run npm install <package> in the theme's lynx/ folder and commit its package.json.
Run it again when modules change
lynx:static:deploy and lynx:static:test install nothing. When a theme's installed packages no longer match the enabled modules and the build kit, they stop with Not set up for the enabled modules and the kit. Run lynx:theme:setup again after enabling or disabling a module, a composer update, a module changing its npm packages, or a change to the theme's own package.json (pulled from your repository, for example).
Building the frontend
bash
bin/magento lynx:static:deploy # every theme set up
bin/magento lynx:static:deploy OOCS_LynxVuelynx:static:deploy runs npm run build in each theme's lynx/ folder; you can also run npm run build there yourself. A theme build type-checks first (vue-tsc), so a type error fails the build.
Each theme prints one summary line, plus any warning and the chunks built from theme overrides:
[lynx] 94 chunks · JS 1250.9 kB (407.3 kB gzip) · CSS 118.7 kB (19.4 kB gzip) · 2.1sAdd -v (bin/magento lynx:static:deploy -v) for npm's full output, Vite's per-file table and the source of every chunk.
Before committing, run npm run lint (ESLint over the theme, its parent themes and the enabled modules; npm run lint -- --fix fixes what it can) and npm run format (Prettier; format:check only checks) in the theme's lynx/ folder.
Output goes to the theme's web/js/lynx/ and web/css/lynx/. Magento publishes those like any theme asset, so in production mode run bin/magento setup:static-content:deploy afterwards. Always build before the static content deploy; the other way round publishes the previous bundles.
SSR bundles
| Renderer | Build |
|---|---|
| Node.js | bin/magento lynx:static:deploy --ssr, or npm run build:ssr in the theme's lynx/ folder. Output: lynx/dist/ssr/nodejs/server.mjs. |
| Cloudflare Worker | npm run build:ssr:worker in the theme's lynx/ folder, then npm run deploy:ssr:worker. |
Rebuild and restart (or redeploy) the renderer whenever you rebuild the client, so both run the same code. See Running the renderer.
The editor
The PageBuilder editor in the admin is a separate build, outside the storefront themes. It ships prebuilt in view/adminhtml/web/js/pagebuilder/ of OOCS_LynxPageBuilder, so a store does not build it. Rebuild it only after changing its sources in view/adminhtml/pagebuilder, or for an enabled editor extension that does not ship its bundle prebuilt:
bash
bin/magento lynx:pagebuilder:buildIt runs npm ci and npm run build in the editor of OOCS_LynxPageBuilder and of every enabled extension, stopping at the first failure. Run it before setup:static-content:deploy, and commit the output with the sources.
Compiling module XML
bash
bin/magento lynx:compileOn every config cache miss, Magento merges the XML files of all modules (events.xml, routes.xml, config.xml, webapi.xml, acl.xml, translations, the lynx_*.xml layouts of each Lynx theme…), and some files such as view.xml are read on every request. lynx:compile performs those merges once and writes the results as PHP files in generated/lynx_compile/; Magento's readers are replaced by versions that load the file when it exists and merge as usual when it does not. It is optional, and the store works without it, only slower on cache misses; run it when the store goes live. Once used, it is a snapshot: run it again after every change to module XML, including in third-party modules. setup:upgrade, module:enable and module:disable delete generated/lynx_compile together with generated/code, so run it again after those too. Run it after setup:upgrade and setup:di:compile, since the translation step needs stores and themes in the database. To drop the snapshot, use Flush Lynx Compile in System › Cache Management, or delete generated/lynx_compile. Pass names to compile only some parts, such as bin/magento lynx:compile events routes; bin/magento lynx:compile --help lists them.
TIP
In development, simply do not run lynx:compile, or flush it after XML changes. A forgotten snapshot is the usual reason an observer, route or config value "does nothing".
Day-to-day workflow
| You changed | Then run |
|---|---|
A .vue or .ts file | npm run build (or bin/magento lynx:static:deploy), then reload the page. In production mode also setup:static-content:deploy. |
di.xml (components, settings, providers, pools, plugins) | bin/magento cache:clean config full_page. In production mode also setup:di:compile. |
events.xml, routes.xml, config.xml or other module XML | bin/magento cache:clean config, plus lynx:compile if you use it |
A lynx_*.xml layout file | bin/magento cache:clean layout full_page, plus lynx:compile layout if you use it |
| Layout rows written by a data patch or directly in the database | bin/magento cache:clean lynx_component full_page |
An etc/components/*.graphqls file, or a module enabled or disabled | bin/magento cache:clean lynx_component full_page, then bin/magento lynx:static:deploy (props types, containers and events) |
| What a provider returns | bin/magento cache:clean full_page (the full page cache holds both the HTML and the Inertia JSON) |
| A CSV translation | bin/magento cache:clean translate full_page, plus lynx:compile translate if you use it |
Enabled, disabled or added a module with frontend sources, ran composer update, or changed a module's npm packages | bin/magento lynx:theme:setup <themes>, then build |
Lynx uses Magento's static deployment version as its asset version. When it changes, open tabs reload the page on their next click instead of mixing old JavaScript with new props.
CLI reference
| Command | Arguments and options | What it does |
|---|---|---|
lynx:theme:setup | [theme...] themes to set up, such as OOCS_LynxVue; none means every theme set up before--list list Lynx themes and stop--npm=<binary> npm to run (default: LYNX_NPM, then npm on PATH) | Writes each theme's lynx/.lynx/package.json from the build kit and the enabled modules, then runs npm install in the theme's lynx/ folder. |
lynx:static:deploy | [theme...] themes to build; none means every theme set up--ssr also build the Node.js SSR bundle (npm run build:ssr)--list, --npm as above | Runs npm run build in each theme's lynx/ folder. Stops when a theme is not set up for the enabled modules. |
lynx:pagebuilder:build | --npm=<binary> npm to run (default npm) | Runs npm ci and npm run build for the PageBuilder editor and every enabled extension. Only needed after changing the editor's sources: it ships prebuilt. |
lynx:compile | [type...] parts to compile; none means all (listed in --help) | Writes merged module XML and translations to generated/lynx_compile. |
lynx:mcp:serve | --host address to listen on (default 127.0.0.1)--port (default 7361)--max-children requests handled at the same time (default 8)--timeout seconds before a request is killed (default 120) | Runs the MCP server. See MCP Server. |
lynx:mcp:tools | --details full description and input schema--json everything, as JSON | Lists the MCP tools. |
Theme names are the theme code with _ instead of / (frontend/OOCS/LynxVue → OOCS_LynxVue). A theme counts as buildable when it has a lynx/package.json.