@struq/skill 0.2.2 → 0.4.0
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.
- package/README.md +23 -35
- package/package.json +3 -2
- package/skills/struq/SKILL.md +148 -212
- package/skills/struq/blocks/CATALOG.md +426 -0
- package/skills/struq/blocks/backgrounds/background-aurora.tsx +818 -0
- package/skills/struq/blocks/backgrounds/background-facets.tsx +1283 -0
- package/skills/struq/blocks/backgrounds/background-silk.tsx +906 -0
- package/skills/struq/blocks/catalog.json +1302 -0
- package/skills/struq/blocks/footers/footer-contact.tsx +789 -0
- package/skills/struq/blocks/footers/footer-reveal.tsx +313 -0
- package/skills/struq/blocks/headers/header-bar.tsx +652 -0
- package/skills/struq/blocks/headers/menu-curtain.tsx +790 -0
- package/skills/struq/blocks/heroes/hero-framed.tsx +627 -0
- package/skills/struq/blocks/heroes/hero-index.tsx +855 -0
- package/skills/struq/blocks/heroes/hero-poster.tsx +1086 -0
- package/skills/struq/blocks/heroes/hero-split.tsx +685 -0
- package/skills/struq/blocks/heroes/hero-still.tsx +862 -0
- package/skills/struq/blocks/kit/Cursor.tsx +117 -0
- package/skills/struq/blocks/kit/HeroCanvas.tsx +278 -0
- package/skills/struq/blocks/kit/HorizontalGallery.tsx +106 -0
- package/skills/struq/blocks/kit/MagneticButton.tsx +92 -0
- package/skills/struq/blocks/kit/MediaFrame.tsx +96 -0
- package/skills/struq/blocks/kit/PinnedZoom.tsx +89 -0
- package/skills/struq/blocks/kit/Reveal.tsx +64 -0
- package/skills/struq/blocks/kit/SmoothScroll.tsx +57 -0
- package/skills/struq/blocks/kit/SplitHeadline.tsx +68 -0
- package/skills/struq/blocks/kit/blocks.css +2102 -0
- package/skills/struq/blocks/kit/gsap.ts +21 -0
- package/skills/struq/blocks/kit/images.ts +17 -0
- package/skills/struq/blocks/kit/photo-read.ts +102 -0
- package/skills/struq/blocks/kit/scenes/contours.ts +161 -0
- package/skills/struq/blocks/kit/scenes/dots.ts +110 -0
- package/skills/struq/blocks/kit/scenes/ripple.ts +99 -0
- package/skills/struq/blocks/kit/scenes/types.ts +114 -0
- package/skills/struq/blocks/page-transitions/page-transition-gate.tsx +706 -0
- package/skills/struq/blocks/page-transitions/page-transition-slices.tsx +469 -0
- package/skills/struq/blocks/page-transitions/page-transition-stack.tsx +583 -0
- package/skills/struq/blocks/preloaders/preloader-gate.tsx +358 -0
- package/skills/struq/blocks/preloaders/preloader-slices-uncovered.ts +50 -0
- package/skills/struq/blocks/preloaders/preloader-slices.tsx +289 -0
- package/skills/struq/blocks/preloaders/preloader-stack.tsx +367 -0
- package/skills/struq/blocks/preloaders/preloader-wordmark.tsx +568 -0
- package/skills/struq/blocks/sections/about-studio.tsx +436 -0
- package/skills/struq/blocks/sections/approach.tsx +661 -0
- package/skills/struq/blocks/sections/contact-form.tsx +664 -0
- package/skills/struq/blocks/sections/cta-closing.tsx +763 -0
- package/skills/struq/blocks/sections/fanned-cards.tsx +547 -0
- package/skills/struq/blocks/sections/film-strip.tsx +385 -0
- package/skills/struq/blocks/sections/grid-assembly.tsx +616 -0
- package/skills/struq/blocks/sections/hover-list.tsx +467 -0
- package/skills/struq/blocks/sections/image-trail.tsx +432 -0
- package/skills/struq/blocks/sections/manifesto.tsx +691 -0
- package/skills/struq/blocks/sections/panel-accordion.tsx +380 -0
- package/skills/struq/blocks/sections/reveals.tsx +416 -0
- package/skills/struq/blocks/sections/split-pair.tsx +670 -0
- package/skills/struq/blocks/sections/sticky-chapters.tsx +256 -0
- package/skills/struq/blocks/sections/velocity-type.tsx +269 -0
- package/skills/struq/blocks/showpieces/fill-rows.tsx +74 -0
- package/skills/struq/blocks/showpieces/hero-opener.tsx +128 -0
- package/skills/struq/blocks/showpieces/image-to-fullbleed.tsx +89 -0
- package/skills/struq/blocks/showpieces/manifesto-scrub.tsx +48 -0
- package/skills/struq/blocks/showpieces/panel-wipe.tsx +89 -0
- package/skills/struq/blocks/showpieces/pixel-resolve.tsx +107 -0
- package/skills/struq/blocks/showpieces/project-stack.tsx +86 -0
- package/skills/struq/blocks/showpieces/scrub-connector.tsx +307 -0
- package/skills/struq/blocks/showpieces/wordmark-finale.tsx +105 -0
- package/skills/struq/blocks/transitions/zoom-through.tsx +613 -0
- package/skills/struq/canon/canon.json +627 -0
- package/skills/struq/cinematic/README.md +7 -18
- package/skills/struq/cinematic/examples/code/nextjs/app/components/LenisRoot.tsx +1 -1
- package/skills/struq/cinematic/examples/code/shared/styles.css +1 -1
- package/skills/struq/cinematic/examples/code/vite/src/LenisRoot.tsx +1 -1
- package/skills/struq/cinematic/references/01-core-mental-model.md +1 -1
- package/skills/struq/cinematic/references/02-vocabulary.md +1 -1
- package/skills/struq/cinematic/references/07-stack-integration.md +2 -2
- package/skills/struq/recipes/app/fonts.ts +12 -0
- package/skills/struq/recipes/app/globals.css +42 -0
- package/skills/struq/recipes/app/layout.tsx +30 -0
- package/skills/struq/references/craft.md +77 -0
- package/skills/struq/references/iconography.md +28 -230
- package/skills/struq/references/stack-targets.md +23 -74
- package/skills/struq/references/tells.md +52 -0
- package/skills/struq/references/triage.md +6 -7
- package/skills/struq/scripts/blocks.mjs +156 -0
- package/skills/struq/scripts/canon.mjs +134 -0
- package/skills/struq/scripts/check.mjs +513 -0
- package/skills/struq/scripts/images.mjs +360 -0
- package/skills/struq/scripts/log.mjs +75 -0
- package/skills/struq/scripts/packs.mjs +156 -0
- package/skills/struq/scripts/tokens.mjs +222 -0
- package/skills/struq/references/anti-patterns.md +0 -265
- package/skills/struq/references/baseline-prompt.md +0 -118
- package/skills/struq/references/brand.md +0 -143
- package/skills/struq/references/brief-router.md +0 -219
- package/skills/struq/references/composition.md +0 -191
- package/skills/struq/references/depth-parallax.md +0 -235
- package/skills/struq/references/direction.md +0 -188
- package/skills/struq/references/feel-layer.md +0 -107
- package/skills/struq/references/gsap-api.md +0 -293
- package/skills/struq/references/imagery.md +0 -144
- package/skills/struq/references/loaders.md +0 -287
- package/skills/struq/references/micro-interactions.md +0 -270
- package/skills/struq/references/mobile-composition.md +0 -70
- package/skills/struq/references/nav-header.md +0 -296
- package/skills/struq/references/page-architecture.md +0 -134
- package/skills/struq/references/page-entrances.md +0 -198
- package/skills/struq/references/performance.md +0 -235
- package/skills/struq/references/pinning-scrub.md +0 -341
- package/skills/struq/references/pitfalls.md +0 -290
- package/skills/struq/references/route-transitions.md +0 -281
- package/skills/struq/references/scaling.md +0 -151
- package/skills/struq/references/scroll-reveals.md +0 -280
- package/skills/struq/references/seo.md +0 -219
- package/skills/struq/references/setup.md +0 -397
- package/skills/struq/references/showcase.md +0 -87
- package/skills/struq/references/struq-imagery.md +0 -107
- package/skills/struq/references/svg-motion.md +0 -390
- package/skills/struq/references/transitions.md +0 -160
- package/skills/struq/references/typography.md +0 -720
- package/skills/struq/references/vibe-presets.md +0 -287
- package/skills/struq/references/webgl-r3f.md +0 -274
- package/skills/struq/references/webgl-scenes.md +0 -593
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Award-tier web design for your coding agent.**
|
|
4
4
|
|
|
5
|
-
Struq is a design skill for Claude Code, Codex, Cursor and OpenCode. Give it a brief and it builds a
|
|
5
|
+
Struq is a design skill for Claude Code, Codex, Cursor and OpenCode. Give it a brief and it builds a studio-grade site from Struq's catalogue of admitted blocks: preloaders, page transitions, headers, heroes, WebGL backgrounds, showpieces, sections and footers, each judged against an award-tier reference and shipped as real files with three variants. Your agent picks the direction and the order, writes the copy and joins the blocks; the blocks carry the motion.
|
|
6
6
|
|
|
7
7
|
The icon set the skill uses by default, Struq Icons, is browsable at [struq.nl/iconen](https://struq.nl/iconen).
|
|
8
8
|
|
|
@@ -26,16 +26,7 @@ It finds the AI tools on your machine and installs the skill into each of them.
|
|
|
26
26
|
|
|
27
27
|
## Same brief, with and without Struq
|
|
28
28
|
|
|
29
|
-
Three briefs, each built twice by the same model with the same materials: once as a plain coding agent, once with `/struq`.
|
|
30
|
-
|
|
31
|
-
| Brief | Without | With Struq | Invented facts (without / with) | Template tells (without / with) |
|
|
32
|
-
|---|---|---|---|---|
|
|
33
|
-
| Ceramicist portfolio, no logo, no photos | 56 | **79** | 14 / 5 | 6 / 3 |
|
|
34
|
-
| E-bike launch, existing brand, wants 3D | 66 | **76** | 11 / 3 | 6 / 3 |
|
|
35
|
-
| Open-source dev-tool landing page | 50 | **76** | 11 / 2 | 10 / 2 |
|
|
36
|
-
| **Average** | **57** | **77** | **36 / 10** | **22 / 8** |
|
|
37
|
-
|
|
38
|
-
Scored out of 100 on typography, composition, color, concept, motion, content honesty, craft and distinctiveness. "Invented facts" counts claims the brief never gave: quotes, bios, stats, specs, API names.
|
|
29
|
+
Three briefs, each built twice by the same model with the same materials: once as a plain coding agent, once with `/struq`.
|
|
39
30
|
|
|
40
31
|
**Dev-tool landing page.** Without: the dark developer-tool template, item for item. With: a light page built around a trace waterfall that assembles as you scroll.
|
|
41
32
|
|
|
@@ -59,39 +50,34 @@ Where Struq lost points: craft. The plain builds are less ambitious and break le
|
|
|
59
50
|
|
|
60
51
|
## What you get
|
|
61
52
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
| Layer | Tooling |
|
|
53
|
+
| Part | What it is |
|
|
65
54
|
|---|---|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
| Direction | A directed mode for full WebGL experiences: chapters, camera shots, handoffs, ownership |
|
|
75
|
-
|
|
76
|
-
Stack: Next.js App Router and Tailwind by default, Vite supported. It reads the versions your project has installed and adapts to them; nothing is pinned. Every GSAP plugin used is free on npm. Icons: [Struq Icons](https://struq.nl/iconen) (`@struq/icons`, MIT) by default.
|
|
55
|
+
| Blocks | 44 admitted blocks in `skills/struq/blocks/` ([catalogue](skills/struq/blocks/CATALOG.md)): 4 preloaders, 3 page transitions, 2 headers, 5 heroes, 3 WebGL backgrounds, 9 showpieces, a scene transition, 15 sections and 2 footers, with the kit they stand on. A copy of Struq's own set, refreshed at every release. |
|
|
56
|
+
| Direction | Struq's palettes and type pairings, written as the one token block the blocks read (surface ladder, contrast scenes, the accent's ink) with each face loaded at its real weights. Offline, no account. |
|
|
57
|
+
| Photos | Art-directed CC0 packs from the Struq beeldbank, picked by the brief and filtered to what fits the client. |
|
|
58
|
+
| Craft | The rules that make the blocks feel high end, for the code between them: clips from numbers, whole pixels, decode before show, scroll-tied and reversing, a gate with a 3 s fallback, type on the measured calm side of a photo. |
|
|
59
|
+
| Check | `check.mjs`: the tell list (eyebrows, pills, gradients, glow, mono, Inter, default purple, numbered steps, icon grids, dashes) and what a page owes its blocks. |
|
|
60
|
+
| MCP | With the Struq MCP connected, the same four jobs come from `struq_richting`, `struq_blokken`, `struq_blok` and `struq_controle`. Without it the skill works from its own copy. |
|
|
61
|
+
|
|
62
|
+
Stack: Next.js App Router and Tailwind v4 (Vite by hand, see `references/stack-targets.md`). Every GSAP plugin used is free on npm. Icons: [Struq Icons](https://struq.nl/iconen) (`@struq/icons`, MIT) by default.
|
|
77
63
|
|
|
78
64
|
## Commands
|
|
79
65
|
|
|
80
66
|
| Command | What it does |
|
|
81
67
|
|---|---|
|
|
82
|
-
| `/struq <brief>` | Plans the site into one `STRUQ.md`, stops once for your
|
|
83
|
-
| `/struq redesign <path>` | Keeps your brand, copy and components;
|
|
84
|
-
| `/struq audit <path-or-url>` | Changes nothing. Returns
|
|
68
|
+
| `/struq <brief>` | Plans the site into one `STRUQ.md`, stops once for your approval, builds it, then runs its own check and, with a browser tool, screenshots it and fixes what it sees |
|
|
69
|
+
| `/struq redesign <path>` | Keeps your brand, copy and components; swaps in blocks where the page is weakest |
|
|
70
|
+
| `/struq audit <path-or-url>` | Changes nothing. Returns every tell with its fix and the three highest-payoff changes |
|
|
85
71
|
| `/struq direct <brief>` | Directed mode for one continuous 3D experience across chapters |
|
|
86
72
|
|
|
87
73
|
In Codex, use `$struq` instead of `/struq`; as a Claude Code plugin the command is `/struq:struq`.
|
|
88
74
|
|
|
89
75
|
## How a build runs
|
|
90
76
|
|
|
91
|
-
1. **
|
|
92
|
-
2. **One stop.** It shows the
|
|
93
|
-
3. **
|
|
94
|
-
4. **
|
|
77
|
+
1. **Direction.** A palette, a type pairing and a photo pack from Struq's canon, and the order of the site from the catalogue: arrival, header, hero, manifesto, about, approach, work, closing call to action, footer. All in one `STRUQ.md`. It never invents testimonials or stats.
|
|
78
|
+
2. **One stop.** It shows the plan and asks once: approve, and send a logo, photos or real numbers if you have them.
|
|
79
|
+
3. **Blocks.** It installs each block with everything it imports, writes the tokens and fonts, and composes the page with your real copy.
|
|
80
|
+
4. **Check.** `check.mjs` runs until it passes; with a browser tool it also looks at the page at phone and desktop width and fixes what it sees.
|
|
95
81
|
|
|
96
82
|
## Install options
|
|
97
83
|
|
|
@@ -131,10 +117,12 @@ npm install @struq/icons
|
|
|
131
117
|
|
|
132
118
|
## What it fetches and sends
|
|
133
119
|
|
|
134
|
-
Struq is instructions and
|
|
120
|
+
Struq is instructions, the block files and five small Node scripts (`blocks.mjs`, `canon.mjs`, `images.mjs`, `check.mjs`, `log.mjs`) that your agent runs in your project. They read and write files in your project, including a build log (`STRUQ-LOG.md`).
|
|
135
121
|
|
|
136
|
-
- **
|
|
137
|
-
- **
|
|
122
|
+
- **Blocks and canon.** Shipped inside the skill. Nothing is fetched to install a block or write the tokens.
|
|
123
|
+
- **Fonts.** The site links Google Fonts (or Fontshare for a face that lives there) from the visitor's browser, as any site with web fonts does.
|
|
124
|
+
- **Photos, for every slot your own photos do not fill.** `images.mjs` reads the public pack list at `https://struq.nl/api/media/packs` and downloads the chosen images from `https://struq.nl/media/packs/` into your project. Offline it writes plates graded to your palette instead.
|
|
125
|
+
- **The MCP, if you connect it.** Your agent calls Struq's tools with your brief; nothing else leaves your machine.
|
|
138
126
|
- **The installer.** `npx @struq/skill@latest` downloads the package from npm, looks for the AI tools' folders in your home folder and copies the skill into them. It sends nothing.
|
|
139
127
|
|
|
140
128
|
## License
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@struq/skill",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Install the free Struq skill into Claude Code, Cursor, Codex and other AI coding tools: websites at the level of a design studio, built by your own AI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Struq (https://struq.nl)",
|
|
@@ -35,7 +35,8 @@
|
|
|
35
35
|
"node": ">=18"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
|
-
"test": "node --test test/install.test.mjs"
|
|
38
|
+
"test": "node --test test/install.test.mjs test/check.test.mjs test/packs.test.mjs test/tokens.test.mjs test/blocks.test.mjs",
|
|
39
|
+
"release:blocks": "node scripts/release-blocks.mjs"
|
|
39
40
|
},
|
|
40
41
|
"publishConfig": {
|
|
41
42
|
"access": "public"
|
package/skills/struq/SKILL.md
CHANGED
|
@@ -1,237 +1,173 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: struq
|
|
3
|
-
description: "Award-tier
|
|
3
|
+
description: "Award-tier studio websites for coding agents, built from Struq's catalogue of admitted blocks: preloaders, page transitions, headers, heroes, WebGL backgrounds, showpieces, sections and footers, each with three real variants, judged at FWA level and shipped as files. Struq's palettes and type pairings as one token block, art-directed CC0 photos from the Struq beeldbank, Lenis on one GSAP clock, and a self-check against the AI tells. Works offline from its own copy; uses the Struq MCP (struq_richting, struq_blokken, struq_blok, struq_controle) when connected. Use when designing, building, redesigning, animating or auditing a marketing, studio, agency or portfolio site that must feel cinematic and custom instead of templated. Stack: Next.js App Router + Tailwind v4."
|
|
4
4
|
argument-hint: "[brief] | redesign <path> | audit <path-or-url> | direct <brief>"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Struq
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
A site looks like a template because every choice in it is the likeliest one. Struq replaces those choices with
|
|
10
|
+
blocks a studio would ship: each one built, reviewed against a named award-tier reference and admitted by hand. Your
|
|
11
|
+
job is the direction, the order, the copy and the seams between blocks. Do not rebuild what a block already does.
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
`<skill-dir>` is the folder this file is in. The catalogue is [blocks/CATALOG.md](blocks/CATALOG.md); the craft that
|
|
14
|
+
makes the blocks feel high end is [references/craft.md](references/craft.md); the tell list is
|
|
15
|
+
[references/tells.md](references/tells.md).
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
| Invocation | Mode |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `/struq <brief>` | **Build**: the checklist below, start to finish. |
|
|
20
|
+
| `/struq redesign <path>` | Keep the brand, copy and components ([references/triage.md](references/triage.md)); swap in blocks where the page is weakest, then run the checklist from step 3. |
|
|
21
|
+
| `/struq audit <path-or-url>` | Change nothing. Run `check.mjs` (and `struq_controle` when connected), report every FAIL and WARN and the three fixes with the most visual payoff. Never a numeric score. |
|
|
22
|
+
| `/struq direct <brief>` | One continuous WebGL experience across chapters: steps 1 to 4, then [cinematic/README.md](cinematic/README.md). |
|
|
16
23
|
|
|
17
|
-
|
|
18
|
-
|---|---|---|
|
|
19
|
-
| `/struq <brief>` (or no argument) | **Build** | Run the Direction phases into `STRUQ.md`, stop once for a veto, build, verify. |
|
|
20
|
-
| `/struq redesign <path>` | **Redesign** | Audit assets and performance, triage the current site ([references/triage.md](references/triage.md)), then Direction with the brand kept, then build. |
|
|
21
|
-
| `/struq audit <path-or-url>` | **Audit** | No code changes. Screenshot, run the tell scan and feel audit, return a scored report (see Audit below). |
|
|
22
|
-
| `/struq direct <brief>` | **Directed** | One continuous WebGL experience across chapters (persistent stage, camera shots, handoffs). Run Direction phases 0 to 3 into `STRUQ.md`, then enter [cinematic/README.md](cinematic/README.md), which appends its direction to the same file. Use only when the brief is genuinely an "experience", not a site with a 3D hero. |
|
|
24
|
+
For a dashboard or product UI keep the tokens, faces and tells; drop the preloader, Lenis and the pinned pieces.
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
## Three rules that never bend
|
|
25
27
|
|
|
26
|
-
**
|
|
28
|
+
1. **Never an empty frame.** Every image slot holds a real photo: the client's, else the beeldbank pack (free, CC0,
|
|
29
|
+
no permission needed). A photo shows the world around the client, never their own room, team or product unless it
|
|
30
|
+
is theirs; captions are written from the alt.
|
|
31
|
+
2. **Never invent facts.** No testimonials, logos, stats, awards, prices, addresses, hours, bios or quotes the brief
|
|
32
|
+
did not give. Leave them out and list them under Assumptions in STRUQ.md.
|
|
33
|
+
3. **Never the tells** ([references/tells.md](references/tells.md)): no eyebrows, pills, gradients or gradient text,
|
|
34
|
+
glow, mono on marketing, Inter or the other generator faces, default purple or blue, numbered steps, icon grids,
|
|
35
|
+
stat banners, generic CTAs, em or en dashes.
|
|
27
36
|
|
|
28
|
-
## The
|
|
37
|
+
## The MCP, or the skill's own copy
|
|
29
38
|
|
|
30
|
-
|
|
39
|
+
The Struq MCP and this skill serve the same blocks and the same derivation. Use the tool when it is connected; the
|
|
40
|
+
offline column does the same from the skill's copy.
|
|
31
41
|
|
|
32
|
-
|
|
|
33
|
-
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
| Smooth scroll | Lenis, driven by `gsap.ticker` | One requestAnimationFrame for the whole page | [setup.md](references/setup.md), [feel-layer.md](references/feel-layer.md) |
|
|
39
|
-
| Scroll motion | GSAP + ScrollTrigger | Scrub for scroll-tied values; masked reveals over fades | [scroll-reveals.md](references/scroll-reveals.md) |
|
|
40
|
-
| Text motion | SplitText | Masked line rise, char stagger, scroll color fill | [typography.md](references/typography.md) |
|
|
41
|
-
| SVG motion | DrawSVG, MorphSVG, MotionPath | Draw-on-scroll paths, logo morphs, signature marks | [svg-motion.md](references/svg-motion.md) |
|
|
42
|
-
| Showpieces | Pinned scrub, horizontal galleries, sticky stacks | One or two per site, placed at act breaks | [showcase.md](references/showcase.md), [pinning-scrub.md](references/pinning-scrub.md) |
|
|
43
|
-
| Icons | Struq Icons (`@struq/icons`) by default, after the brand's own set; else Phosphor (light), else Iconoir or Tabler | One icon family per site, never mixed, never Lucide by reflex | [iconography.md](references/iconography.md) |
|
|
44
|
-
| Hover and pointer | GSAP `quickTo` (magnetic, cursor), CSS + GSAP hover scenes | Garnish, applied last | [micro-interactions.md](references/micro-interactions.md) |
|
|
45
|
-
| React lifecycle | Motion (`motion/react`) | Mount/unmount, `layoutId`, gesture state | GSAP vs Motion below |
|
|
46
|
-
| Overlays | Radix primitives (Dialog for menus and modals) | Focus trap, Escape, scroll lock paired with `lenis.stop()` | [nav-header.md](references/nav-header.md) |
|
|
47
|
-
| Page flow | Full-screen cover, swap, reveal transitions; session-gated loader | Every route change is a designed moment | [route-transitions.md](references/route-transitions.md), [loaders.md](references/loaders.md) |
|
|
48
|
-
| 3D moments | Three.js, R3F, Drei, postprocessing | Lazy island, poster fallback, driven from the same ticker | [webgl-r3f.md](references/webgl-r3f.md), [webgl-scenes.md](references/webgl-scenes.md) |
|
|
49
|
-
| Findability | Metadata API, an OG image per route, sitemap, robots, JSON-LD | One h1 per page; loaders and reveals never hide content from the HTML | [seo.md](references/seo.md) |
|
|
50
|
-
| Performance | ffmpeg, next/image, gltf-transform, next/font | Assets first: budgets per role, posters always, WebGL never in the first-load bundle | [performance.md](references/performance.md) |
|
|
42
|
+
| Need | MCP connected | Offline |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| A direction: palette, pairing, photo pack as tokens and fonts | `struq_richting(brief)` (or with `palette`, `type` ids) | `canon.mjs list`, then `canon.mjs palette <id>` and `canon.mjs type <id>`; `images.mjs --brief` |
|
|
45
|
+
| What blocks exist | `struq_blokken(kind?, query?)` | `blocks.mjs list [kind]`, [blocks/CATALOG.md](blocks/CATALOG.md) |
|
|
46
|
+
| A block as files | `struq_blok(slug, variant?)` | `blocks.mjs add <slug>` |
|
|
47
|
+
| The tell check | `struq_controle()`: run its detectors on your own files | `check.mjs` |
|
|
51
48
|
|
|
52
|
-
|
|
49
|
+
Put `struq_richting`'s token block in `app/globals.css` in place of the STRUQ TOKENS block and its font URLs in
|
|
50
|
+
`app/fonts.ts`; drop `struq_blok`'s files into `components/struq/` at the paths it gives. Log each tool call:
|
|
51
|
+
`node <skill-dir>/scripts/log.mjs mcp <tool> --note "<what you took>"`. Run `check.mjs` either way.
|
|
53
52
|
|
|
54
|
-
##
|
|
53
|
+
## Build checklist
|
|
55
54
|
|
|
56
|
-
|
|
55
|
+
Copy this into `STRUQ.md` under the plan and tick each line as you finish it. Keep `STRUQ-LOG.md` from the first
|
|
56
|
+
step: append only, one entry per step (`node <skill-dir>/scripts/log.mjs "Step N Name" "what" "why"`; the scripts log
|
|
57
|
+
their own). `check.mjs` fails while a line is open or a ticked step has no entry.
|
|
57
58
|
|
|
58
59
|
```
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
heavy display only as a declared genre (the Brutalist appendix), never a
|
|
69
|
-
reflex. Tracking per face, never one tracking-tight on every size: sans
|
|
70
|
-
display about -0.025 to -0.03em, serif display about -0.01 to -0.025em, h2
|
|
71
|
-
about half that. Body 1rem to 1.0625rem at 400, leading 1.6+, 55 to 75ch;
|
|
72
|
-
emphasis 500, never 700. Hierarchy from scale contrast, not medium sizes.
|
|
73
|
-
ROLES: every string takes a role token, never text-xs, text-lg or text-5xl:
|
|
74
|
-
font-display text-display, font-display text-h2, type-h3 text-h3,
|
|
75
|
-
text-lead, text-body, text-small, eyebrow text-eyebrow, font-ui text-ui,
|
|
76
|
-
stat text-stat, and font-display text-statement for the one Orient line
|
|
77
|
-
or manifesto. Eyebrows: uppercase 0.75rem (the 12px floor), tracked 0.12
|
|
78
|
-
to 0.18em per face, ink-muted, one per section, never ink-faint.
|
|
79
|
-
FLOOR: body at least 1rem, muted at least 0.875rem, nothing under 12px.
|
|
80
|
-
CONTRAST: body at least 4.5:1, large text at least 3:1. ink-faint is never
|
|
81
|
-
text: hairlines and disabled states only.
|
|
82
|
-
SIGNATURE: every STRUQ.md declares one typographic signature move
|
|
83
|
-
(typography.md §5: weight-in, soft-scrub, type-mask-media,
|
|
84
|
-
fit-width-wordmark, a cropped display). The masked line rise is a
|
|
85
|
-
technique, not the default hero. Mono only for literal code. Headings get
|
|
86
|
-
text-wrap: balance; body gets text-wrap: pretty.
|
|
87
|
-
|
|
88
|
-
SPACING: Base-8 rhythm with deliberate asymmetry. Section padding varies by
|
|
89
|
-
role: hero 12 to 20rem, dense content 6 to 8rem, breathers 16 to 24rem. NEVER
|
|
90
|
-
uniform py-16 on every section. Whitespace is a material: at least one section
|
|
91
|
-
should feel "too empty" by SaaS standards.
|
|
92
|
-
|
|
93
|
-
SCALING: One fluid root-rem knob, not per-breakpoint size ladders:
|
|
94
|
-
html { font-size: clamp(1rem, 0.92rem + 0.2vw, 1.125rem); }
|
|
95
|
-
16px at 390, about 17.6px at 1440, frozen at 18px from about 1640. Every
|
|
96
|
-
clamp() keeps a rem term in its middle so zoom works; a vw-only middle is a
|
|
97
|
-
bug. Author everything in rem; px only for 1px hairlines. Breakpoints change
|
|
98
|
-
LAYOUT (columns, stack or row), never size. Display roles carry their own
|
|
99
|
-
clamp() on top.
|
|
100
|
-
|
|
101
|
-
SURFACE: Elevation is a tonal step, not a drop shadow. Dark mode: each layer
|
|
102
|
-
steps LIGHTER (#0A0A0B, #111113, #19191C, #232328). Light mode: pick one
|
|
103
|
-
direction and keep it (panels a shade deeper than a toned page, or white lifted
|
|
104
|
-
off a toned page). Hairline borders about 8 to 12% off the surface; in light
|
|
105
|
-
mode a border is the ink at low alpha (rgb(<ink> / 0.08 to 0.14)), never a
|
|
106
|
-
flat gray hex. Shadows only for true floating elements, then large, soft and faint
|
|
107
|
-
(0 24px 80px -12px rgb(0 0 0 / 0.4)). Never shadow-md or shadow-lg.
|
|
108
|
-
|
|
109
|
-
COLOR: One accent, used sparingly (links, the key CTA, one highlight per
|
|
110
|
-
viewport). Neutrals are temperature-shifted (warm cream and off-black, or cool
|
|
111
|
-
charcoal), never pure #FFF and #000 with gray-500 text. A second accent is a
|
|
112
|
-
declared genre choice with its own token and the same budget. No blue to
|
|
113
|
-
purple gradients, no gradient text, no glassmorphism cards.
|
|
114
|
-
|
|
115
|
-
MOTION: Lenis smooth scroll (lerp 0.09 to 0.11) on one gsap.ticker clock,
|
|
116
|
-
unless the genre calls for native scroll. Every entrance animates opacity AND
|
|
117
|
-
transform (y 24 to 80px, or a clip or overflow mask). Opacity-only fades are
|
|
118
|
-
forbidden. Stagger siblings 0.06 to 0.1s. Durations: micro 0.2 to 0.3s,
|
|
119
|
-
standard UI 0.3 to 0.6s, reveals 0.6 to 1.0s, hero and cinematic 1.0 to 1.6s;
|
|
120
|
-
exits run about 60% of their entrance. Eases: entrances expo-out
|
|
121
|
-
cubic-bezier(0.16, 1, 0.3, 1) (expo.out); exits power2.in; position swaps
|
|
122
|
-
quart-in-out cubic-bezier(0.76, 0, 0.24, 1) (power3.inOut); curtains and
|
|
123
|
-
panels quint-in-out cubic-bezier(0.83, 0, 0.17, 1) (power4.inOut). Never
|
|
124
|
-
default ease-in-out everywhere.
|
|
125
|
-
Scroll-tied effects scrub; they do not fire time-based tweens at a threshold.
|
|
126
|
-
prefers-reduced-motion: gate transforms, keep opacity.
|
|
127
|
-
|
|
128
|
-
COMPOSITION: Break the grid at least twice per page: an image bleeding off
|
|
129
|
-
the viewport, an element overlapping two sections, oversized type running off
|
|
130
|
-
canvas, a sticky element. No three identical icon cards in a row. Vary section
|
|
131
|
-
layout: after a 50/50 split comes full-bleed or an asymmetric 1/3 and 2/3.
|
|
132
|
-
Icons: ONE coherent family chosen for the brand, one stroke and size,
|
|
133
|
-
ink-colored. Never emoji, never the AI-cliche icons (Sparkles, Rocket, Zap),
|
|
134
|
-
never icons in colored chips. Animated icons run under 500ms on click and
|
|
135
|
-
never loop in standard UI.
|
|
136
|
-
|
|
137
|
-
DETAILS THAT SELL IT: Real running copy. Tracked uppercase eyebrows as
|
|
138
|
-
wayfinding, not 01/02/03 stamped on every section (one deliberate oversized
|
|
139
|
-
numeral is fine). The footer is designed as hard as the hero. Custom
|
|
140
|
-
::selection color. Visible, designed focus-visible states. Every route change
|
|
141
|
-
is a designed transition, not a hard cut.
|
|
60
|
+
## Build checklist
|
|
61
|
+
- [ ] 1 Project: Next.js App Router + Tailwind v4; blocks.mjs init printed OK
|
|
62
|
+
- [ ] 2 Direction and approval: palette, pairing, pack and the block order in STRUQ.md; the one stop sent and answered
|
|
63
|
+
- [ ] 3 Canon: the token block and fonts written (canon.mjs palette and type, or struq_richting)
|
|
64
|
+
- [ ] 4 Images: images.mjs --brief printed OK; only photos whose alt fits the client
|
|
65
|
+
- [ ] 5 Blocks: every block on the order installed and composed in app/page.tsx with real copy
|
|
66
|
+
- [ ] 6 Build: npm run build passes
|
|
67
|
+
- [ ] 7 Look: 390 and 1440 screenshots and one full scroll, fixes made (or "Verify: not seen, no browser")
|
|
68
|
+
- [ ] 8 Check: check.mjs prints RESULT: PASS
|
|
142
69
|
```
|
|
143
70
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
1. **Page architecture.** Which sections exist, in what order, and where the showpiece sits. Free, and it decides everything downstream. A perfect section inside a template arc still reads as a template. [references/page-architecture.md](references/page-architecture.md)
|
|
151
|
-
2. **Typography.** The Signature pairing, the light display weight, the role tokens, the eyebrow system, the one signature move. This is 70% of "looks designed". Set the root-rem knob ([references/scaling.md](references/scaling.md)) first, then the type system ([references/typography.md](references/typography.md)).
|
|
152
|
-
3. **Palette and surfaces.** Kills the "Tailwind default" look instantly. [references/vibe-presets.md](references/vibe-presets.md)
|
|
153
|
-
4. **Masked, staggered scroll reveals.** The single highest-payoff motion technique, including the curtain section reveal. [references/scroll-reveals.md](references/scroll-reveals.md)
|
|
154
|
-
5. **The feel layer.** Lenis lerp, scrub smoothing, ease selection. Wrong values make good techniques feel cheap. [references/feel-layer.md](references/feel-layer.md)
|
|
155
|
-
6. **Nav and header.** On screen for the whole session; the fullscreen menu is often the most art-directed moment on the site. [references/nav-header.md](references/nav-header.md)
|
|
156
|
-
7. **Imagery and art direction.** One grade, declared ratios, treated assets. Ungraded mixed stock undoes everything above it. [references/imagery.md](references/imagery.md). No photos of their own? Struq's beeldbank comes before stock: [references/struq-imagery.md](references/struq-imagery.md)
|
|
157
|
-
8. **Composition: overlap, bleed, z-choreography.** [references/composition.md](references/composition.md), and how each technique translates at 360 to 430px: [references/mobile-composition.md](references/mobile-composition.md)
|
|
158
|
-
9. **Showpieces.** Pinned scrub timelines, horizontal galleries, sticky stacks, path journeys. High cost; one or two per site at act breaks. Pick by id from [references/showcase.md](references/showcase.md).
|
|
159
|
-
10. **Page flow.** Full-screen route transitions ([references/route-transitions.md](references/route-transitions.md)), a session-gated first-load loader ([references/loaders.md](references/loaders.md)), per-zone entrances ([references/page-entrances.md](references/page-entrances.md)), section curtains and match cuts ([references/transitions.md](references/transitions.md)). Loader invariant: the pre-paint revisit gate and the live animation phase are separate state machines. A persistent `seen` flag must never hide a curtain that is still playing.
|
|
160
|
-
11. **Text and SVG choreography.** SplitText beyond the line reveal, DrawSVG, MorphSVG. [references/typography.md](references/typography.md), [references/svg-motion.md](references/svg-motion.md)
|
|
161
|
-
12. **Hover and pointer.** Magnetic buttons, cursor followers, hover scenes. Garnish, not the meal. [references/micro-interactions.md](references/micro-interactions.md)
|
|
162
|
-
13. **WebGL moments.** Highest cost of all; only when a section genuinely calls for it. Integration first ([references/webgl-r3f.md](references/webgl-r3f.md)), then Drei, postprocessing and interaction ([references/webgl-scenes.md](references/webgl-scenes.md)). If the whole page is one 3D experience, switch to Directed mode.
|
|
163
|
-
|
|
164
|
-
Before and after pairs for every category, the cheap reflex against the agency version: [references/anti-patterns.md](references/anti-patterns.md). **If output drifts generic, read that file first.**
|
|
71
|
+
**1 Project.** Empty folder: `npx create-next-app@latest . --ts --tailwind --app --eslint --yes`, then
|
|
72
|
+
`node <skill-dir>/scripts/blocks.mjs init`. It copies the kit to `components/struq/kit/`, writes the layout (the
|
|
73
|
+
`sq-js` script before paint, the font links, `data-blocks` on `<body>`, `SmoothScroll`), `globals.css` (the kit
|
|
74
|
+
import, the theme names, the STRUQ TOKENS block) and `fonts.ts` over a starter, and installs gsap, @gsap/react and
|
|
75
|
+
lenis. Your own layout or stylesheet is never overwritten: merge from `recipes/app/`.
|
|
165
76
|
|
|
166
|
-
**
|
|
77
|
+
**2 Direction and the one stop.** Pick from the canon, never invent a palette or pairing while one fits. Palette by
|
|
78
|
+
the brief's mood, then its sector; a palette marked "kept out" (blue, purple, teal) only for a brand that is that
|
|
79
|
+
colour, declared as `Cool hue: declared because <brand colour>`. The brand's own colours and faces beat the canon:
|
|
80
|
+
write them into the same token names. Pairing by temperament: Fraunces (serif-editorial) warm and premium, Newsreader
|
|
81
|
+
literate, Sora calm and architectural, Urbanist soft and current, Bodoni Moda for fashion, Big Shoulders
|
|
82
|
+
(condensed-poster) for a campaign at poster scale, Unbounded for a wide agency voice. Then choose the order (below)
|
|
83
|
+
and write the top of STRUQ.md:
|
|
167
84
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
- `text-ink-faint` on any text
|
|
180
|
-
- `shadow-md` or `shadow-lg` as the elevation system on gray-50 cards
|
|
181
|
-
- Opacity-only fade-ins, all fired at once, with default `ease-in-out` and `duration-300`
|
|
182
|
-
- `bg-white` page, `text-gray-500` body, `border-gray-200` everywhere
|
|
183
|
-
- Emoji as icons, the cliche trio (Sparkles, Rocket, Zap) as decoration, icons in colored circles
|
|
184
|
-
- Monospace as decoration on eyebrows, labels, stats or badges
|
|
185
|
-
- `01 / 02 / 03` stamped on every section or row
|
|
186
|
-
- Hero = centered h1, subhead, two buttons and a dashboard screenshot in browser chrome
|
|
187
|
-
- Untreated mixed-grade stock at random ratios, glossy AI-render blobs, floating purple spheres
|
|
188
|
-
- `backdrop-blur` glass cards on a mesh-gradient background
|
|
189
|
-
- Hard cuts between routes on a multi-page site
|
|
190
|
-
- Lorem ipsum, "John Doe", "Acme Inc.", "Your journey starts here"
|
|
191
|
-
|
|
192
|
-
## GSAP vs Motion: the decision rule
|
|
193
|
-
|
|
194
|
-
Both are installed. Never animate the same property on the same element with both, and never with GSAP and a CSS `transition` either: one owner per property per element ([references/pitfalls.md](references/pitfalls.md) §3). **GSAP owns everything that runs every frame or is tied to scroll; Motion owns React lifecycle, layout and gesture state.** The reason is the single clock: the whole build runs on one requestAnimationFrame (Lenis driven by `gsap.ticker`, [references/setup.md](references/setup.md) §2). High-frequency pointer work belongs on that same ticker via `quickTo`. Pushing it onto a competing spring loop is exactly what makes good motion feel subtly off.
|
|
85
|
+
```
|
|
86
|
+
# STRUQ.md: <name>
|
|
87
|
+
Brief: <one line: what, for whom, where>
|
|
88
|
+
Idea: <the one idea the site is about>
|
|
89
|
+
Palette: <id> (<mood>)
|
|
90
|
+
Type: <pairing id>: <display> + <body>
|
|
91
|
+
Images: pack <slug> (or the client's photos, then pack <slug>)
|
|
92
|
+
Order: <block slug:variant>, <block slug:variant>, ...
|
|
93
|
+
Assumptions: <every drafted line and every fact left out>
|
|
94
|
+
Verify: <filled in at step 7>
|
|
95
|
+
```
|
|
195
96
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
97
|
+
Then **stop once**, in the user's language: the plan in five lines (idea, palette, type, pack, order) and
|
|
98
|
+
"Akkoord? Heb je een logo, foto's of echte cijfers, stuur ze nu." (English: "Approve? If you have a logo, photos or
|
|
99
|
+
real numbers, send them now."). The build request is not the approval. Log the reply word for word:
|
|
100
|
+
`log.mjs "Step 2 Approval" "Asked: ..." "Reply: \"<their words>\""`. Any yes builds the plan; what they send replaces
|
|
101
|
+
the matching pick; a veto changes only what it names. Never ask a second time. When no pack shows the client's own
|
|
102
|
+
product, add: "Ik heb geen foto's van je <product>: stuur ze, dan komen ze in de hero."
|
|
103
|
+
|
|
104
|
+
**3 Canon.** `canon.mjs palette <id>` and `canon.mjs type <id>` rewrite the one STRUQ TOKENS block and `app/fonts.ts`:
|
|
105
|
+
the surface ladder, the field and inverse roles, `--photo-ground`, the accent's ink, the pairing's display weight and
|
|
106
|
+
faces, and each Google face asked for its real weights. It is the block Struq's lab judged every block in.
|
|
107
|
+
|
|
108
|
+
**4 Images.** `node <skill-dir>/scripts/images.mjs --brief "<the brief, in the user's words>"` picks the pack, keeps
|
|
109
|
+
only the photos whose alt fits the client, downloads and verifies them to `public/images/` and writes
|
|
110
|
+
`lib/struq-images.ts` (`images.hero`, `.band`, `.card`, `.column`, `.detail`, `.backdrop`, `imageCredit`, `imageFit`).
|
|
111
|
+
`images.mjs --list` shows every pack. Read the alts before you place a photo; with `imageFit` "none" use no photos and
|
|
112
|
+
let a background block carry the hero. Offline it writes plates graded to the palette. Set the title, description and
|
|
113
|
+
`lang` in the layout.
|
|
114
|
+
|
|
115
|
+
**5 Blocks.** Install the order with `blocks.mjs add <slug> ...` (or `struq_blok`), read each block's file header for
|
|
116
|
+
its props, variants and how it mounts, and compose `app/page.tsx` with the brief's real copy. Glue between blocks uses
|
|
117
|
+
the kit (`Reveal`, `MediaFrame`, `SplitHeadline`, `MagneticButton`) and the craft rules, never a fresh motion system.
|
|
118
|
+
|
|
119
|
+
**6 to 8.** `npm run build` passes (fix your code, never delete a block to get green). Look at the production build
|
|
120
|
+
(`npx next start -p 4321`) at 390 and 1440 and scroll it once: the preloader lands on the hero, every frame fills, each
|
|
121
|
+
pin engages and releases without a jump, nothing overflows at 390, scrolling back reverses. Never claim you saw what
|
|
122
|
+
you did not. Then `check.mjs` until `RESULT: PASS`.
|
|
123
|
+
|
|
124
|
+
## The order of a studio site
|
|
125
|
+
|
|
126
|
+
Read top to bottom; each line is a slot with the blocks that fill it. Seven to nine slots, not all of them every time.
|
|
127
|
+
|
|
128
|
+
1. **Arrival, once:** a preloader on the first visit (`preloader-wordmark`, `-slices`, `-gate`, `-stack`) and the
|
|
129
|
+
page transition of the same language on every navigation (`page-transition-slices`, `-gate`, `-stack`; mount it in
|
|
130
|
+
the layout). Slices with slices, gate with gate, stack with stack: they share one handover.
|
|
131
|
+
2. **Header:** `header-bar` (quiet, settle, split) or `menu-curtain` for a full-screen menu. Sections under it say
|
|
132
|
+
their ground with `data-bar-tone`.
|
|
133
|
+
3. **Hero:** `hero-still` (one photo, calm side measured), `hero-framed` (the print on the wall), `hero-split` (a
|
|
134
|
+
seam), `hero-index` (the work list as the first screen), `hero-poster` (type as poster), `hero-opener` (full bleed
|
|
135
|
+
with the WebGL layer), or a background block (`background-aurora`, `-silk`, `-facets`) when the hero is type on a
|
|
136
|
+
live field.
|
|
137
|
+
4. **Manifesto:** `manifesto`, `manifesto-scrub`, `velocity-type` or `reveals`: the one statement, given a screen.
|
|
138
|
+
5. **About:** `about-studio` or `split-pair`.
|
|
139
|
+
6. **Approach:** `approach`, `sticky-chapters`, `panel-accordion` or `fill-rows`. Never numbered steps.
|
|
140
|
+
7. **Work:** `project-stack`, `hover-list`, `image-trail`, `film-strip`, `grid-assembly`, `fanned-cards`, or a scene
|
|
141
|
+
move (`image-to-fullbleed`, `panel-wipe`, `zoom-through`, `scrub-connector`, `pixel-resolve`) between two slots.
|
|
142
|
+
8. **Closing call to action:** `cta-closing`, with `contact-form` when the site asks for input.
|
|
143
|
+
9. **Footer:** `footer-reveal`, `footer-contact` or `wordmark-finale`.
|
|
144
|
+
|
|
145
|
+
**Picking.** One lead move per page, the hero or a work piece, and the rest quieter around it. Never two pinned
|
|
146
|
+
pieces back to back: a plain slot breathes between them. One contrast scene, at most two: wrap a slot in
|
|
147
|
+
`scene-inverse` or `scene-field`. Choose the variant by the brief and the photos, not by novelty: a variant is a
|
|
148
|
+
different composition of the same idea, and every variant works light and dark. Name a block the user asks for first.
|
|
149
|
+
A studio with real project photos leads with work (`hero-index`, `project-stack`); a studio without them leads with
|
|
150
|
+
type and one photo (`hero-poster`, `hero-still`, `manifesto`).
|
|
151
|
+
|
|
152
|
+
## What makes it feel high end
|
|
153
|
+
|
|
154
|
+
The blocks hold this already; your glue must too. Detail in [references/craft.md](references/craft.md).
|
|
155
|
+
|
|
156
|
+
- Reveals clip from numbers (inset values tweened as numbers), never scale a box; positions in whole pixels.
|
|
157
|
+
- Photos are decoded before they show, cut or swap.
|
|
158
|
+
- Scroll effects are scroll-tied and reverse when the visitor scrolls back; key frames hold.
|
|
159
|
+
- The gate: `sq-js` on `<html>` before paint hides only what will animate, and shows it anyway after 3 s.
|
|
160
|
+
- Type on a photo sits on the measured calm side over the lightest flat veil that reaches 3:1.
|
|
161
|
+
- Display faces run light (300, or the poster pairing's own weight); fitted lines are measured with the real face
|
|
162
|
+
after `document.fonts.ready`.
|
|
163
|
+
- Tokens only, mixes in oklab, a surface step and a hairline instead of a shadow, one accent.
|
|
164
|
+
- Icons: Struq Icons (`@struq/icons`), functional only ([references/iconography.md](references/iconography.md)).
|
|
165
|
+
|
|
166
|
+
## When something goes wrong
|
|
167
|
+
|
|
168
|
+
- **Nothing scrolls:** an overlay called `getLenis()?.stop()` without `start()`, or `SmoothScroll` is not mounted.
|
|
169
|
+
- **Content stays invisible for 3 s:** the block never set `data-ready`; usually it threw. Read the console.
|
|
170
|
+
- **Blocks render in the wrong colours or faces:** `data-blocks` is missing on `<body>`, or the STRUQ TOKENS block
|
|
171
|
+
sits before the kit import in `globals.css`.
|
|
172
|
+
- **A fitted line overflows or jumps:** the face did not load (check `app/fonts.ts` and the links in the layout).
|
|
173
|
+
- **Vite:** [references/stack-targets.md](references/stack-targets.md).
|