@fluid-app/fluid-cli-theme-dev 0.1.27 → 0.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,33 +1,45 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: template-stylesheet-to-asset-migration
|
|
3
3
|
description: |
|
|
4
|
-
Migrates
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
Migrates deprecated stylesheet files in a local Fluid theme repo to theme-level assets.
|
|
5
|
+
Covers two related shapes: (1) per-template `<themeable_type>/<name>/styles.css` files
|
|
6
|
+
→ `assets/template-*.css` referenced from each template's `index.liquid`; (2) the
|
|
7
|
+
theme-root `styles.css` and `global_styles.css` (theme-level `custom_stylesheet` /
|
|
8
|
+
`global_stylesheet` columns) → `assets/styles.css` and `assets/global_styles.css`
|
|
9
|
+
referenced from the theme's `layouts/theme.liquid` inside `<head>`. Use when
|
|
10
|
+
`fluid theme push` warned about skipped stylesheets, when a push failed with 422
|
|
11
|
+
because the backing company has `STYLESHEET_STRICT_INPUT` on, or when proactively
|
|
12
|
+
bringing an older repo onto the new asset-based shape. The skill walks the repo
|
|
13
|
+
one file at a time — moves CSS bytes, chooses inline vs external emission based
|
|
14
|
+
on size, updates the appropriate Liquid file, and lints. Never pushes without
|
|
15
|
+
explicit approval.
|
|
13
16
|
---
|
|
14
17
|
|
|
15
|
-
#
|
|
18
|
+
# Stylesheet → Theme-Level Asset Migration
|
|
19
|
+
|
|
20
|
+
Two shapes ship in the same repo migration: **per-template** stylesheets (the older, larger surface — dozens of files) and **theme-level** stylesheets (two files at the theme root). Both funnel through the same `STYLESHEET_STRICT_INPUT` company feature flag on the backend; once it flips on, every deprecated stylesheet payload is rejected with 422 and every deprecated stylesheet column is nilled from API responses.
|
|
21
|
+
|
|
22
|
+
Work Part 1 first (bulk of files), then Part 2 (the two theme-root files).
|
|
16
23
|
|
|
17
24
|
## Why this migration exists
|
|
18
25
|
|
|
19
|
-
Fluid used to inject
|
|
26
|
+
Fluid used to inject deprecated stylesheet columns into the rendered HTML as inline `<style>` blocks on every request. That bloated HTML, defeated browser and CDN caching, and made stylesheets impossible to author independently of Liquid. The new model:
|
|
20
27
|
|
|
21
|
-
- Each
|
|
22
|
-
- The template's `index.liquid` **explicitly references** the asset via a
|
|
28
|
+
- Each stylesheet lives in a **theme-level `FileResource`** — a real asset under `assets/` in the theme repo, cacheable, editable independently.
|
|
29
|
+
- The referencing Liquid file (each template's `index.liquid` for per-template, `layouts/theme.liquid` for theme-level) **explicitly references** the asset via a Shopify-compat filter:
|
|
23
30
|
|
|
24
31
|
```liquid
|
|
25
|
-
{{ 'template-<themeable_type>-<name>.css' | asset_url | stylesheet_tag }}
|
|
32
|
+
{{ 'template-<themeable_type>-<name>.css' | asset_url | stylesheet_tag }} {%- comment -%} per-template external <link> {%- endcomment -%}
|
|
33
|
+
{{ 'styles.css' | inline_asset_content }} {%- comment -%} theme-level inline <style> {%- endcomment -%}
|
|
26
34
|
```
|
|
27
35
|
|
|
28
|
-
- Once a template has been migrated (backend marker `stylesheet_tag_injected: true`), the CLI **skips** any local `<themeable_type>/<name>/styles.css` on push and prints a warning
|
|
36
|
+
- Once a per-template stylesheet has been migrated (backend marker `stylesheet_tag_injected: true`), the CLI **skips** any local `<themeable_type>/<name>/styles.css` on push and prints a warning. Under the `STYLESHEET_STRICT_INPUT` company feature flag, the API rejects both deprecated shapes with 422 for any caller that still sends them.
|
|
37
|
+
|
|
38
|
+
The migration is one-way. Once the flag flips on for a company, legacy `styles.css` pushes just fail — the repo needs to be on the new shape first.
|
|
39
|
+
|
|
40
|
+
# Part 1 — Per-template stylesheets
|
|
29
41
|
|
|
30
|
-
|
|
42
|
+
Applies to every `<themeable_type>/<name>/styles.css` under the theme root except mysite.
|
|
31
43
|
|
|
32
44
|
## When to use this skill
|
|
33
45
|
|
|
@@ -186,3 +198,139 @@ Every migrated template's `index.liquid` starts with a `{{ 'template-*.css' | ..
|
|
|
186
198
|
- **Refactoring the CSS while migrating.** Two changes at once — hard to review, easy to break. Do the byte-for-byte move first, refactor later in its own commit.
|
|
187
199
|
- **Skipping the lint step.** The validator catches missing assets, dangling Liquid expressions, and other easy misses.
|
|
188
200
|
- **Pushing from within this skill.** Not this skill's job. Hand the reshaped repo back to the user; they decide when to push.
|
|
201
|
+
|
|
202
|
+
# Part 2 — Theme-level stylesheets (`styles.css` + `global_styles.css` at the theme root)
|
|
203
|
+
|
|
204
|
+
## What this shape is
|
|
205
|
+
|
|
206
|
+
Two files at the theme root — **NOT** inside a `<themeable_type>/<name>/` folder:
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
theme_root/
|
|
210
|
+
├── styles.css ← theme-level custom_stylesheet column
|
|
211
|
+
├── global_styles.css ← theme-level global_stylesheet column
|
|
212
|
+
├── variables.json
|
|
213
|
+
├── layouts/theme.liquid ← the layout template
|
|
214
|
+
├── assets/
|
|
215
|
+
└── …
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Both files are the legacy on-disk shape of two DB columns: `application_themes.custom_stylesheet` and `application_themes.global_stylesheet`. The storefront renderer used to inline them into `<head>` from those columns; the new shape is theme-level FRs the layout references directly.
|
|
219
|
+
|
|
220
|
+
## Skip conditions
|
|
221
|
+
|
|
222
|
+
- Repo has no `styles.css` and no `global_styles.css` at the theme root → nothing to do.
|
|
223
|
+
- Repo's `layouts/theme.liquid` already includes both `{{ 'styles.css' | inline_asset_content }}` and `{{ 'global_styles.css' | inline_asset_content }}` **AND** the two files no longer exist at the theme root → already migrated.
|
|
224
|
+
- Root theme (no company_id) — theme-level migration is out of scope for root themes; only company-scoped themes go through this shape.
|
|
225
|
+
|
|
226
|
+
## Emission choice — always inline
|
|
227
|
+
|
|
228
|
+
Both filters exist for theme-level too (`asset_url | stylesheet_tag` for external, `inline_asset_content` for inline). **The theme-level migration always uses inline** — matches the pre-migration output byte-for-byte (`PageBuilder` used to emit one inline `<style>` block for these). No size threshold; no external link. Storefront behavior is preserved exactly.
|
|
229
|
+
|
|
230
|
+
## Workflow
|
|
231
|
+
|
|
232
|
+
Work the two files together — they migrate as a pair because they share one target Liquid file (`layouts/theme.liquid`).
|
|
233
|
+
|
|
234
|
+
1. **Read** the three inputs:
|
|
235
|
+
- `styles.css` at theme root (may or may not exist).
|
|
236
|
+
- `global_styles.css` at theme root (may or may not exist).
|
|
237
|
+
- `layouts/theme.liquid` — the layout to edit.
|
|
238
|
+
2. **Move** each present file to `assets/` with the same filename (no rename):
|
|
239
|
+
- `styles.css` → `assets/styles.css`
|
|
240
|
+
- `global_styles.css` → `assets/global_styles.css`
|
|
241
|
+
3. **Edit** `layouts/theme.liquid` — insert both tags immediately before `</head>` (see "Placement" below).
|
|
242
|
+
4. **Delete** the theme-root originals (already moved).
|
|
243
|
+
5. **Validate** with `fluid theme lint --json` — parse, fix, re-run until clean.
|
|
244
|
+
6. **Preview** — if `fluid theme dev` is running, reload the storefront and confirm the CSS still renders. Byte-for-byte identical to pre-migration.
|
|
245
|
+
|
|
246
|
+
## Filename convention
|
|
247
|
+
|
|
248
|
+
Fixed. Do **not** rename these to `template-*.css` — they are theme-level, not per-template. The backend expects the exact filenames `styles.css` and `global_styles.css` on the theme's FR list. Existing pre-migration FRs at these filenames (author-uploaded, prior migrator runs) are prepended on backfill, not overwritten.
|
|
249
|
+
|
|
250
|
+
## Placement in `layouts/theme.liquid`
|
|
251
|
+
|
|
252
|
+
Insert both tags immediately before `</head>`, `global_styles.css` first (foundation) then `styles.css` (override). The `<head>` region of `theme.liquid` typically has other `{% style %}` literals for CSS variables — put the two `inline_asset_content` tags AFTER those so the theme-level custom CSS wins the cascade for equal specificity.
|
|
253
|
+
|
|
254
|
+
```liquid
|
|
255
|
+
{% style %}
|
|
256
|
+
:root {
|
|
257
|
+
/* CSS variables from settings */
|
|
258
|
+
}
|
|
259
|
+
{% endstyle %}
|
|
260
|
+
|
|
261
|
+
{{ 'global_styles.css' | inline_asset_content }}
|
|
262
|
+
{{ 'styles.css' | inline_asset_content }}
|
|
263
|
+
</head>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Worked example
|
|
267
|
+
|
|
268
|
+
Starting state — theme root:
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
theme_root/
|
|
272
|
+
├── styles.css ← 800 bytes of custom overrides
|
|
273
|
+
├── global_styles.css ← 51,000 bytes of foundation CSS
|
|
274
|
+
├── variables.json
|
|
275
|
+
├── layouts/theme.liquid
|
|
276
|
+
├── assets/
|
|
277
|
+
└── …
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Step 1 — move both:**
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
mv styles.css assets/styles.css
|
|
284
|
+
mv global_styles.css assets/global_styles.css
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**Step 2 — edit `layouts/theme.liquid`, insert before `</head>`:**
|
|
288
|
+
|
|
289
|
+
```liquid
|
|
290
|
+
{% style %}
|
|
291
|
+
:root { /* ... */ }
|
|
292
|
+
{% endstyle %}
|
|
293
|
+
|
|
294
|
+
{{ 'global_styles.css' | inline_asset_content }}
|
|
295
|
+
{{ 'styles.css' | inline_asset_content }}
|
|
296
|
+
</head>
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Step 3 — lint:**
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
fluid theme lint --json
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Step 4 — dev-server sanity check:**
|
|
306
|
+
|
|
307
|
+
Confirm the storefront renders with the same CSS. Both `<style>` blocks appear in `<head>` in the DOM inspector.
|
|
308
|
+
|
|
309
|
+
## What good looks like after Part 2
|
|
310
|
+
|
|
311
|
+
- `styles.css` and `global_styles.css` no longer exist at the theme root — only in `assets/`.
|
|
312
|
+
- `layouts/theme.liquid` has both `{{ '…' | inline_asset_content }}` tags before `</head>`.
|
|
313
|
+
- `fluid theme lint --json` is clean.
|
|
314
|
+
- `fluid theme push` reports no 422 and no "Skipped … styles.css" warning.
|
|
315
|
+
|
|
316
|
+
## Post-migration repo shape
|
|
317
|
+
|
|
318
|
+
```
|
|
319
|
+
theme_root/
|
|
320
|
+
├── variables.json
|
|
321
|
+
├── layouts/theme.liquid ← references both theme-level FRs via inline_asset_content
|
|
322
|
+
├── assets/
|
|
323
|
+
│ ├── styles.css ← was theme-root styles.css (custom_stylesheet)
|
|
324
|
+
│ ├── global_styles.css ← was theme-root global_styles.css (global_stylesheet)
|
|
325
|
+
│ ├── template-*.css ← Part 1 outputs (one per migrated template)
|
|
326
|
+
│ └── …
|
|
327
|
+
├── components/, sections/ ← out of scope for Part 2 (theme-level). Any co-located `styles.css` / `style.css` files here remain deprecated — see Part 1 above and `themes-review/references/css-js-hygiene.md`. Migrate them separately.
|
|
328
|
+
├── <themeable_type>/<name>/ ← index.liquid + variables.json only (no styles.css after Part 1)
|
|
329
|
+
└── …
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Anti-patterns specific to Part 2
|
|
333
|
+
|
|
334
|
+
- **Choosing external `<link>` for theme-level.** Storefront behavior is preserved by staying inline. External `<link>` would add an extra HTTP round trip for the foundation CSS every page.
|
|
335
|
+
- **Renaming `styles.css` / `global_styles.css`.** The backend FR lookup keys on these exact filenames. Rename breaks the storefront's `inline_asset_content` resolution.
|
|
336
|
+
- **Placing the tags outside `<head>` or after `</head>`.** The `<style>` block emitted by `inline_asset_content` MUST land inside `<head>` for the browser to treat it as page-level CSS.
|
|
@@ -42,6 +42,9 @@ A typical theme repo looks like this (verified against the `base-theme` starter
|
|
|
42
42
|
```
|
|
43
43
|
my-theme/
|
|
44
44
|
├── assets/ ← CSS, JS, images, video — flat at root
|
|
45
|
+
│ ├── styles.css ← theme-level custom_stylesheet (was theme-root styles.css)
|
|
46
|
+
│ ├── global_styles.css ← theme-level global_stylesheet (was theme-root global_styles.css)
|
|
47
|
+
│ └── … ← all other CSS/JS/images
|
|
45
48
|
├── components/{name}/ ← shared partials, at root (no templates/ wrapper)
|
|
46
49
|
│ ├── pagination/index.liquid
|
|
47
50
|
│ ├── cart_template/index.liquid
|
|
@@ -76,7 +79,6 @@ my-theme/
|
|
|
76
79
|
│ └── ...
|
|
77
80
|
├── styleguide/index.liquid ← optional dev-only preview
|
|
78
81
|
├── cover.png ← theme thumbnail for the editor picker
|
|
79
|
-
├── global_styles.css ← optional theme-wide CSS at root
|
|
80
82
|
├── .fluid-theme.json ← CLI metadata (themeId, company, checksums)
|
|
81
83
|
├── .fluidignore ← like .gitignore
|
|
82
84
|
└── README.md
|
|
@@ -117,8 +119,7 @@ Every artifact has a fixed depth and shape. **No deeper nesting is allowed under
|
|
|
117
119
|
| Layouts | `layouts/{name}.liquid` (flat file, no wrapping dir) | `layouts/theme.liquid` | Multiple layouts possible; each is a flat `.liquid` file. |
|
|
118
120
|
| Global config | `config/settings_schema.json`, `config/settings_data.json` (flat) | — | — |
|
|
119
121
|
| Locales | `locales/{lang}.json` (flat) | `locales/en.json`, `locales/de.json` | — |
|
|
120
|
-
| Assets | `assets/{file}` (flat) | `assets/
|
|
121
|
-
| Root-level CSS | `global_styles.css` at the theme root | — | Optional theme-wide stylesheet. |
|
|
122
|
+
| Assets | `assets/{file}` (flat) | `assets/styles.css`, `assets/global_styles.css`, `assets/logo.svg` | No sub-folders. Theme-level stylesheets live here too: `styles.css` (custom_stylesheet) and `global_styles.css` (global_stylesheet). Referenced from `layouts/theme.liquid` via `\| inline_asset_content` before `</head>`. |
|
|
122
123
|
| Theme thumbnail | `cover.png` at the theme root | — | — |
|
|
123
124
|
| Styleguide | `styleguide/index.liquid` | — | Optional dev-only preview. |
|
|
124
125
|
|
|
@@ -188,7 +189,7 @@ A layout missing either one is broken. Missing `content_for_header` breaks edito
|
|
|
188
189
|
| Component file with a `{% schema %}` block | `blocker` | Components don't have schemas. Move to `sections/`, or strip the schema. |
|
|
189
190
|
| Section file without `{% schema %}` | `blocker` | A section without a schema is just markup — make it a component (move to `components/{name}/index.liquid`). |
|
|
190
191
|
| Page template at `{type}/index.liquid` (missing variant dir) | `blocker` | Wrap in a variant directory: `{type}/default/index.liquid`. |
|
|
191
|
-
| Asset (`.css`, `.js`, image) outside `assets
|
|
192
|
+
| Asset (`.css`, `.js`, image) outside `assets/`, or `styles.css` / `global_styles.css` at the theme root, or `cover.png` outside root | `blocker` | Move to `assets/` and reference via `\| asset_url` (or `\| inline_asset_content` for the theme-level `styles.css` / `global_styles.css`). |
|
|
192
193
|
| Sub-folder inside `assets/` (e.g. `assets/icons/`) | `should` | Flatten: rename file to `assets/icon-{whatever}.svg`. |
|
|
193
194
|
| Sub-folder inside `sections/{name}/` or `components/{name}/` (e.g. `sections/hero/blocks/`) | `blocker` | Sections and components don't nest. A reusable block belongs in the top-level `blocks/{name}/` directory, not under a section. |
|
|
194
195
|
| Co-located `styles.css` / `style.css` next to a section, component, or page template variant | `blocker` for new files, `should` for existing | **Co-located stylesheets are deprecated** — all CSS lives under `assets/`. See [CSS hygiene §1a](references/css-js-hygiene.md). |
|
|
@@ -42,7 +42,8 @@ The earlier theme convention placed a `styles.css` next to each template, sectio
|
|
|
42
42
|
| New file `components/{name}/style.css` | `blocker` | Same — `assets/{name}.css` and `asset_url`. |
|
|
43
43
|
| New file under a page-variant directory like `{type}/{variant}/styles.css` | `blocker` | Move to `assets/{name}.css`. |
|
|
44
44
|
| Existing co-located stylesheet edited in the PR | `should` | Suggest migrating to `assets/` as part of the same PR if the diff is small, or a follow-up if not. |
|
|
45
|
-
|
|
|
45
|
+
| Theme-level `styles.css` or `global_styles.css` at the theme root (pre-migration shape) | `blocker` | Move to `assets/styles.css` / `assets/global_styles.css` and reference from `layouts/theme.liquid` via `\| inline_asset_content` before `</head>`. See the CLI skill `packages/cli/theme-dev/skills/template-stylesheet-to-asset-migration/SKILL.md` Part 2. |
|
|
46
|
+
| Global / custom stylesheets anywhere else outside `assets/` | `blocker` | Move to `assets/`. |
|
|
46
47
|
| Hardcoded path like `<link rel="stylesheet" href="/sections/{name}/styles.css">` (bypassing `asset_url`) | `blocker` | Move the file and switch to `asset_url`. |
|
|
47
48
|
|
|
48
49
|
Migration recipe (suggest in the comment when applicable):
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluid-app/fluid-cli-theme-dev",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.29",
|
|
4
4
|
"description": "Fluid CLI plugin for theme developer workflows — dev server, push, pull, init",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
"jest": "^29.7.0",
|
|
39
39
|
"tsdown": "^0.21.0",
|
|
40
40
|
"typescript": "^5",
|
|
41
|
-
"@fluid-app/themes-api-client": "0.1.0",
|
|
42
|
-
"@fluid-app/typescript-config": "0.0.0",
|
|
43
41
|
"@fluid-app/api-client-core": "0.1.0",
|
|
44
|
-
"@fluid-app/
|
|
42
|
+
"@fluid-app/themes-api-client": "0.1.0",
|
|
43
|
+
"@fluid-app/theme-schema": "0.1.0",
|
|
44
|
+
"@fluid-app/typescript-config": "0.0.0"
|
|
45
45
|
},
|
|
46
46
|
"engines": {
|
|
47
47
|
"node": ">=18.0.0"
|