Theme.json setup in Sage 11

Sage 11 suggests this in the vite config:

wordpressThemeJson({
  disableTailwindColors: false,
  disableTailwindFonts: false,
  disableTailwindFontSizes: false,
}),

I had a bunch of config in bud in Sage 10 that got generated into the theme.json. I don’t see a place for that here, but I did notice there’s a tailwindConfig setting on ThemeJsonConfig (the type of options to this function) that can point to a tailwind.config.js file. I also see baseThemePath that defaults to ./theme.json according to the comments in that file. As well as a outputPath that defaults to assets/theme.json according to the comments.

Is this currently working? I don’t see it creating root variables for the theme settings I had before, just the generic defaults from plain wordpress. And does that make sense that the generated file goes into the assets directory, and not right into the root by default where Wordpress would look for it?

Yes

Post your code

Thank you, this helped me get closer.

I’ve not written a vite plugin, so I’m not an expert on this. I simply stopped the dev server, added console.log statements to functions in the plugin, restarted the dev server, and refreshed the page to try and determine what’s going on.

When I run vite dev, I never see generateBundle get called, which it looks like is where the merging of the base theme.json and generated theme styles happen.

When I do a full vite build, I DO see the merged theme.json placed in the right path with the correct content.

Here’s a link to the function in the roots vite plugin that I’m referring to:

Again, post your code.

Which files would be most helpful to help you determine if this is an issue?

Unless I’m mistaken, we’re talking about your generated theme.json file being incorrect. Share your theme.json file from the theme root that you’ve made changes to. Looking for what steps are needed to make a minimal reproduction of what you’re describing.

Otherwise there might be confusion as to how you’re supposed to be working with theme.json as of Sage 11?

Thanks Ben. It’s very possible I could be misunderstanding the intention of how to work with theme.json files in sage 11.

From the jsdoc comments, it seemed like the idea is I can have a theme.json at the root of my sage theme, and the plugin will merge it with any styles defined in the @theme layer of my app.css. And that I can optionally also specify some ways that labels are mapped to styles in the @theme layer.

What I was trying to do, was use my existing theme.json from sage 10 (which was generated by bud) and have it be merged with theme styles I used to define in tailwind.config.js, but are now in the @theme layer in app.css.

I actually reuse styles in the @theme layer in both app.css and editor.css by importing them from another shared css file. That doesn’t seem to be currently supported (only theme styles directly in app.css are supported) but that’s a seprate issue.

After some extensive testing it seems to me that the Wordpress theme_file_path hook in setup.php is looking for theme.json at build/assets/theme.json, but that file only gets written when you do a vite build.

This could be a completely different direction than you intended, but to at least get myself up and running, I ended up writing a PR that watches for changes to theme.json or any of your css files and runs the same code you were using to create the “merged” file in generateBundle, but now also when running vite dev. It’s kept me going for now, but I have no idea how the approach I took fits with your plans.

You can check that out here: feat: generate theme.json during dev mode using in-memory CSS by eavonius · Pull Request #15 · roots/vite-plugin · GitHub

Below is the contents of my theme.json at the root of my theme.

{
  "$schema": "https://schemas.wp.org/trunk/theme.json",
  "version": 3,
  "settings": {
    "appearanceTools": true,
    "layout": {
      "contentSize": "1280px",
      "wideSize": "1512px"
    },
    "color": {
      "custom": false,
      "link": true,
      "customDuotone": false,
      "customGradient": false,
      "defaultDuotone": false,
      "defaultGradients": false,
      "defaultPalette": false,
      "duotone": [],
      "palette": [
        {
          "slug": "primary",
          "color": "#29d48d",
          "name": "Primary"
        },
        {
          "slug": "primary-border",
          "color": "#2CE698",
          "name": "Primary border"
        },
        {
          "slug": "primary-hover",
          "color": "#2CE698",
          "name": "Primary hover"
        },
        {
          "slug": "primary-hover-border",
          "color": "#2CFF98",
          "name": "Primary hover border"
        },
        {
          "slug": "secondary",
          "color": "#B83259",
          "name": "Secondary"
        },
        {
          "slug": "secondary-border",
          "color": "#ca3f66",
          "name": "Secondary border"
        },
        {
          "slug": "secondary-hover",
          "color": "#ca3f66",
          "name": "Secondary hover"
        },
        {
          "slug": "secondary-hover-border",
          "color": "#d35f80",
          "name": "Secondary hover border"
        },
        {
          "slug": "tertiary",
          "color": "#219FC4",
          "name": "Tertiary"
        },
        {
          "slug": "tertiary-border",
          "color": "#2eb3dc",
          "name": "Tertiary border"
        },
        {
          "slug": "tertiary-hover",
          "color": "#2eb3dc",
          "name": "Tertiary hover"
        },
        {
          "slug": "tertiary-hover-border",
          "color": "#51c0e1",
          "name": "Tertiary hover border"
        },
        {
          "slug": "muted",
          "color": "#555",
          "name": "Muted"
        },
        {
          "slug": "dark",
          "color": "#333",
          "name": "Dark"
        },
        {
          "slug": "dark-link",
          "color": "#29c1ec",
          "name": "Link on dark"
        },
        {
          "slug": "disabled",
          "color": "#888",
          "name": "Disabled"
        },
        {
          "slug": "disabled-text",
          "color": "#444",
          "name": "Disabled text"
        },
        {
          "slug": "black",
          "color": "#111",
          "name": "Black"
        },
        {
          "slug": "Grey",
          "color": "#ddd",
          "name": "grey"
        },
        {
          "slug": "white",
          "color": "#fff",
          "name": "White"
        },
        {
          "slug": "off-white",
          "color": "#eee",
          "name": "Off white"
        },
        {
          "slug": "gold",
          "color": "#d6aa14",
          "name": "Gold"
        },
        {
          "slug": "primary-dark",
          "color": "#1f8e6b",
          "name": "Primary Dark"
        }
      ]
    },
    "custom": {
      "spacing": {},
      "typography": {
        "font-size": {},
        "line-height": {}
      }
    },
    "spacing": {
      "blockGap": true,
      "margin": true,
      "padding": true,
      "units": ["px", "%", "em", "rem", "vw", "vh"]
    },
    "typography": {
      "dropCap": true,
      "lineHeight": true,
      "customFontSize": false,
      "fontSizes": [
        {
          "slug": "tiny",
          "size": "clamp(0.56rem, calc(0.38rem + 0.39vw), 0.69rem)",
          "name": "Tiny"
        },
        {
          "slug": "small",
          "size": "clamp(0.8rem, calc(0.56rem + 0.39vw), 0.88rem)",
          "name": "Small"
        },
        {
          "slug": "normal",
          "size": "clamp(1.05rem, calc(0.50rem + 0.78vw), 1.18rem)",
          "name": "Normal"
        },
        {
          "slug": "large",
          "size": "clamp(1.1rem, calc(0.63rem + 0.78vw), 1.25rem)",
          "name": "Large"
        },
        {
          "slug": "x-large",
          "size": "clamp(1.1rem, calc(0.75rem + 0.78vw), 1.38rem)",
          "name": "Extra Large"
        },
        {
          "slug": "xx-large",
          "size": "clamp(1.3rem, calc(1.03rem + 0.98vw), 1.81rem)",
          "name": "Extra Extra Large"
        },
        {
          "slug": "heading-one",
          "size": "clamp(2em, calc(1.59rem + 1.76vw), 3.00rem)",
          "name": "Heading One"
        },
        {
          "slug": "heading-two",
          "size": "clamp(1.85rem, calc(1.53rem + 1.37vw), 2.63rem)",
          "name": "Heading Two"
        },
        {
          "slug": "heading-three",
          "size": "clamp(1.6rem, calc(1.25rem + 1.17vw), 2.19rem)",
          "name": "Heading Three"
        },
        {
          "slug": "heading-four",
          "size": "clamp(1.3rem, calc(1.03rem + 0.98vw), 1.81rem)",
          "name": "Heading Four"
        },
        {
          "slug": "heading-five",
          "size": "clamp(1.1rem, calc(0.75rem + 0.78vw), 1.38rem)",
          "name": "Heading Five"
        },
        {
          "slug": "heading-six",
          "size": "clamp(1.1rem, calc(0.63rem + 0.78vw), 1.25rem)",
          "name": "Heading Six"
        },
        {
          "slug": "subtitle",
          "size": "clamp(1.1rem, calc(0.75rem + 0.78vw), 1.38rem)",
          "name": "Subtitle"
        }
      ],
      "fontFamilies": [
        {
          "fontFamily": "\"Inter\", sans-serif",
          "slug": "open-sans",
          "name": "Open Sans"
        },
        {
          "fontFamily": "\"Jost\", sans-serif",
          "slug": "jost",
          "name": "Jost"
        }
      ]
    }
  },
  "styles": {}
}

@ben so a complication I ran into, is that as soon as build/assets/theme.json exists, it appears that when this code runs in the admin_head hook in setup.php for the sage theme:

$dependencies = json_decode(Vite::content('editor.deps.json'));

It finds the build directory there and thinks this is a prod build and errors out since it can’t find the editor deps.

I didn’t realize this was a problem until I tried to hop into the admin side of the site once the “built” theme.json exists. So I’m not sure what to do next.

I was able to get this to still work if I add a check for WP_ENV being set to anything other than development (I have a staging and production environment for my site):

add_filter('admin_head', function () {
    if (! get_current_screen()?->is_block_editor()) {
        return;
    }

    if (defined("WP_ENV") && WP_ENV !== 'development') {
        $dependencies = json_decode(Vite::content('editor.deps.json'));

        foreach ($dependencies as $dependency) {
            if (! wp_script_is($dependency)) {
                wp_enqueue_script($dependency);
            }
        }
    }

    echo Vite::withEntryPoints([
        'resources/js/editor.js',
    ])->toHtml();
});

I was able to get this to still work if I add a check for WP_ENV being set to anything other than development (I have a staging and production environment for my site):

I’m confused on when this would ever be necessary? In the current configuration (outside of your PR)- you’re expected to have done an initial npm run build before going into development mode, but otherwise everything should work as expected. I’m not against theme.json being watched/built in dev mode, I just hadn’t thought about it. I just want to make sure there’s not another issue I’m missing here?

Yes, that’s the only issue. In bud we had the theme.json generated hot I believe, so I just expected that was the same here.

I have several custom gutenberg blocks and content I work on at the same time as blade code, so I have just grown accustomed to being able to update the theme to make stuff available to the content editor without having to stop the server.

It’s not a deal-breaker, I just didn’t see anywhere that a build was required first before doing development. That could have been something I just overlooked, or I may be the only one working with developing my theme and editing content at the same time.

3 Likes