Skip to main content

Get started

Migrate a project to LUZ

Move a project that has its own CSS to LUZ one page at a time, in five steps. An AI does the mechanical work; you decide and check.

How the migration works

Keep the old CSS running until the last page has moved. One rule comes before all the others: an AI speeds up the mechanical work, and you decide and check.

It fits a site of many pages or of content. In a single-page app built on a component library such as React or Vue, a migration changes the look but not the components: see what it costs.

What makes it possible is luz.conditional.css, the same file as luz.css with the reset and the bare elements limited to a region marked data-luz. Install it in step 3.

Before you touch anything

  1. Make an inventory. Ask the AI to list the pages or templates, the components of the old framework and how often each is used, the JavaScript that depends on classes or markup (modals, menus, tabs, validation) and every !important. Correct the list: it is the map of the migration.
  2. Take screenshots. One of each page in the states that matter: light and dark, phone and desktop, a form with an error, an open modal. Without them you cannot tell what you broke.
  3. Write smoke tests. If the project has no tests, ask the AI for a few on what must not break: the form sends, the menu opens, the login works. You run them.
  4. Write down when a page is done, once. The page loads no class or script of the old framework, luz-check and an accessibility check come out clean, the screenshots match except what you chose to change, and the smoke tests pass.

The five steps

Step 1: tokens with your current brand

Make a look of your own from themes/_template.css with the values you use today. The AI maps your variables or loose colors to the tokens of LUZ and gives you the table; you check it. Nothing changes on screen, and your CSS and LUZ now share a vocabulary. Make it yours shows how.

Step 2: the old CSS in a layer before LUZ

Put the old stylesheet in a layer that comes before luz, so LUZ wins where both style an element:

CSS
/* site.css, linked before the LUZ stylesheets */
@layer legacy, luz;
@import url("legacy.css") layer(legacy);
  • Check the !important rules. In an earlier layer they still win over LUZ. The AI lists them; you decide which go now.
  • Look for CSS with no layer. A style attribute or the CSS of a plugin beats every layer, LUZ included. The screenshots show it.
  • Use @import for the migration only. It adds a request. Cascade layers explains the order.

Step 3: the first region

Load luz.conditional.css instead of luz.css, pick a small page with no JavaScript, and put data-luz on the element that holds it. Inside, the HTML with no classes comes out styled by LUZ:

HTML
<main data-luz>
  <h1>Contact us</h1>
  <form action="/contact" method="post">
    <label for="email">Email</label>
    <input id="email" name="email" type="email" required>
    <button>Send</button>
  </form>
</main>

Do this one by hand. What you learn goes into the prompt for the next pages.

Step 4: page by page

Choose the order, from the simple pages to the complex ones, with the pages that share a template together. Migrate the shared parts (header, footer, menu) once, after the simple pages and before the complex ones, so you do not keep two headers for months. For each page, repeat the same loop:

  1. The AI, with the LUZ prompt, puts the page in the region, removes the classes of the old framework, leaves the HTML semantic, and adds a LUZ class only where HTML is not enough. Removing is safer than adding.
  2. It runs npx @luz-ds/check@0.3.0 and an accessibility check, and shows you what changed and what is left, never the whole file rewritten.
  3. You read the diff and the screenshots, and run the smoke tests.
  4. One commit per page, so you can revert a page and not a month.

luz-check reads LUZ’s classes, elements, load order and color tokens. It does not look for classes of the old framework that are left over: search for them yourself.

Step 5: remove the old CSS

When no page uses the old CSS, remove the legacy layer, load luz.css instead of luz.conditional.css, and drop data-luz. The AI searches for the classes and scripts that are left; you delete the old framework. Never earlier: the AI deletes nothing without your OK for this step.

Where the bugs come from

The bugs of a migration do not come from the new CSS. They come from deleting the old code without knowing who used it.

  • The JavaScript of the old framework. A Bootstrap modal is a dialog in LUZ, but the code that opened or validated it is still there. The AI tells you which script each page touches; you review the replacement, because it holds business logic.
  • Forms. Migrate one form first, from the field to the submit.
  • Shared parts. Migrate the header, footer and menu once, as step 4 says.
  • JavaScript that looks for old classes. Before you delete a class, search the scripts and templates for it. A querySelector('.btn-primary') that stops finding its button gives no error: it just stops working.

Who does what

The AI works on the mechanical parts; you keep every decision.

The AIYou
Makes the inventory, maps variables to tokens, lists the !important rules
Reads and corrects the inventory, and chooses the order of the pages
Writes the smoke tests and the tests of each page
Runs them and decides if they are enough
Removes classes, leaves semantic HTML, adds the few LUZ classes
Does the first region by hand and reviews every diff
Runs luz-check and the accessibility check, and sums up what changed and what is left
Looks at the screenshots and approves the commit
Searches for classes and scripts left over before anything is deleted
Replaces the JavaScript that holds business logic, and deletes the old framework

What it costs, and when not to

A migration has three costs, and one case where it does not pay.

  • The costs: two visual languages for a while (step 1 softens it), the weight of both stylesheets while it lasts, and the JavaScript of the old framework, which you must rewrite.
  • When not to: in a single-page app built on a component library for React or Vue, you change the look but not the components. It is more honest to rewrite screen by screen with LUZ.

Next steps