shopic 0.0.1

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.
Files changed (3) hide show
  1. package/README.md +160 -0
  2. package/dist/index.js +1 -0
  3. package/package.json +51 -0
package/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # shopic
2
+
3
+ Custom code bundle for the Shopic Webflow site. TypeScript, bundled with esbuild,
4
+ published to npm and served to Webflow over the jsDelivr CDN.
5
+
6
+ ## How the code reaches the site
7
+
8
+ ```
9
+ src/*.ts → esbuild → dist/*.js → npm publish → cdn.jsdelivr.net/npm/shopic@<version>/dist/index.js
10
+ ```
11
+
12
+ npm stores the versions; jsDelivr is the CDN that serves them. The published package
13
+ is public even though this repository is not — that is the price of a free CDN.
14
+
15
+ ## Local development
16
+
17
+ ```bash
18
+ pnpm install
19
+ pnpm dev
20
+ ```
21
+
22
+ `pnpm dev` serves the bundle at `http://localhost:3000` with live reload.
23
+
24
+ Put this in **Site Settings → Custom Code → Footer** once, and leave it there. It
25
+ loads the CDN build for everyone, and the local build only for a browser you have
26
+ flipped into dev mode:
27
+
28
+ ```html
29
+ <script>
30
+ (() => {
31
+ const PROD = 'https://cdn.jsdelivr.net/npm/shopic@0.0.1/dist/index.js';
32
+ const DEV = 'http://localhost:3000/index.js';
33
+
34
+ const load = (src, fallback) => {
35
+ const s = document.createElement('script');
36
+ s.src = src;
37
+ if (fallback) s.onerror = fallback;
38
+ document.head.appendChild(s);
39
+ };
40
+
41
+ if (localStorage.getItem('shopic-dev') === 'on') load(DEV, () => load(PROD));
42
+ else load(PROD);
43
+ })();
44
+ </script>
45
+ ```
46
+
47
+ Flip it on in the console on the staging domain, once:
48
+
49
+ ```js
50
+ localStorage.setItem('shopic-dev', 'on'); // off: localStorage.removeItem('shopic-dev')
51
+ ```
52
+
53
+ Without that gate every visitor's browser would probe your localhost. With it,
54
+ only yours does, and it falls back to the CDN the moment `pnpm dev` is not running.
55
+
56
+ Two things to know: Chrome and Firefox allow `http://localhost` from an HTTPS page,
57
+ **Safari blocks it** — work in Chrome. And the dev URL has no `/dist` in it, because
58
+ esbuild serves that directory as the root (`src/pages/home.ts` → `/pages/home.js`).
59
+
60
+ ## Releasing
61
+
62
+ Every release is run by hand from this folder. There is no CI — the GitHub
63
+ repository is history and backup, nothing publishes from it.
64
+
65
+ ```bash
66
+ pnpm changeset # describe the change, pick patch/minor/major
67
+ pnpm changeset version # bumps the version, writes CHANGELOG.md
68
+ git commit -am "release: 0.0.1"
69
+
70
+ npm publish --access public # browser opens, confirm with the passkey
71
+ git tag v0.0.1
72
+ git push --follow-tags
73
+ ```
74
+
75
+ **Publish with `npm`, not `pnpm changeset publish`.** Changesets detects the pnpm
76
+ lockfile and hands the publish to `pnpm publish`, and its only 2FA path is a typed
77
+ six-digit code (`Enter one-time password:`). This account uses a passkey, where no
78
+ such code exists — the prompt is a dead end. `changeset version` still does the real
79
+ work; `changeset publish` would only have added the git tag, which the command above
80
+ does directly.
81
+
82
+ This needs **npm CLI 11.9 or newer**; older versions cannot drive the WebAuthn
83
+ browser hand-off and fall back to asking for a code that does not exist.
84
+
85
+ `prepublishOnly` runs `check`, `lint` and `build` before npm packs anything, so a
86
+ published tarball can never contain a stale `dist`. If any of the three fails, the
87
+ publish stops.
88
+
89
+ That guard matters because **npm versions are immutable**. You cannot replace a
90
+ published version — a mistake costs you a new one.
91
+
92
+ Provenance is off. npm only signs builds from public source repositories, and this
93
+ one is private.
94
+
95
+ **Always pin the version in the script tag.** jsDelivr caches unversioned and
96
+ branch URLs for hours; `@latest` will serve stale code and cost you an afternoon.
97
+
98
+ ## Animations
99
+
100
+ GSAP is **not bundled**. It loads from Webflow's native Site Settings toggle, and this
101
+ bundle reads the global. `src/lib/gsap.ts` throws a named error if the toggle is off —
102
+ a site transfer wipes Site Settings, and a silent failure would ship a site with no motion.
103
+
104
+ Animations are driven by the `data-anim` attribute so the client can move markup around
105
+ in the Designer without breaking motion:
106
+
107
+ ```html
108
+ <div data-anim="hero-reveal">…</div>
109
+ ```
110
+
111
+ Register the handler under the same name:
112
+
113
+ ```ts
114
+ // src/anim/hero-reveal.ts
115
+ import { registerAnimation } from '$anim/registry';
116
+
117
+ registerAnimation('hero-reveal', (element, { gsap, reducedMotion }) => {
118
+ if (reducedMotion) return;
119
+ gsap.from(element, { autoAlpha: 0, y: 24, duration: 0.6 });
120
+ });
121
+ ```
122
+
123
+ Import the file in `src/anim/index.ts`. An unregistered `data-anim` value warns in the
124
+ console instead of throwing.
125
+
126
+ ## Entry points
127
+
128
+ - `src/index.ts` — ships on every page.
129
+ - `src/pages/*.ts` — one file per page, picked up automatically, ships only where you
130
+ add its script tag.
131
+
132
+ ## Layout
133
+
134
+ | Path | Contents |
135
+ | --- | --- |
136
+ | `src/lib` | Shared helpers — GSAP access, environment checks |
137
+ | `src/anim` | `data-anim` registry and one file per animation |
138
+ | `src/pages` | Per-page entry points |
139
+ | `tests` | Playwright measurement specs (Chromium, one viewport) |
140
+
141
+ ## Commands
142
+
143
+ | Command | Does |
144
+ | --- | --- |
145
+ | `pnpm dev` | Watch, rebuild, serve on :3000 with live reload |
146
+ | `pnpm build` | Minified production build into `dist` |
147
+ | `pnpm check` | TypeScript, no emit |
148
+ | `pnpm lint` | ESLint + Prettier, read-only |
149
+ | `pnpm lint:fix` | ESLint with `--fix` |
150
+ | `pnpm format` | Prettier, writes |
151
+ | `pnpm test` | Playwright measurement specs against `STAGING_URL` |
152
+ | `pnpm test:ui` | The same specs in Playwright's UI runner |
153
+ | `pnpm changeset` | Record a pending change and its version bump |
154
+ | `pnpm changeset version` | Apply pending changesets, write `CHANGELOG.md` |
155
+ | `npm publish` | Upload to npm (passkey in the browser) — see Releasing |
156
+
157
+ `prepublishOnly` chains `check`, `lint` and `build`; it runs on publish, not by hand.
158
+
159
+ The Playwright specs measure the published site, not the local dev server — set
160
+ `STAGING_URL` or they fall back to `https://shopic.webflow.io`.
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";(()=>{var c=new Map;var i=(e,t=document)=>{let p=t.querySelectorAll("[data-anim]");for(let o of p){let r=o.dataset.anim;if(!r)continue;let n=c.get(r);if(!n){console.warn(`[shopic] No animation registered for data-anim="${r}".`,o);continue}n(o,e)}};var a=()=>{let{gsap:e,ScrollTrigger:t}=window;if(!e)throw new Error("[shopic] GSAP is not on the page. Enable it in Webflow \u2192 Site Settings \u2192 Custom Code \u2192 GSAP.");return t&&e.registerPlugin(t),{gsap:e,ScrollTrigger:t}},s=()=>window.matchMedia("(prefers-reduced-motion: reduce)").matches;window.Webflow||(window.Webflow=[]);window.Webflow.push(()=>{let{gsap:e,ScrollTrigger:t}=a();i({gsap:e,ScrollTrigger:t,reducedMotion:s()})});})();
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "shopic",
3
+ "version": "0.0.1",
4
+ "description": "Custom code bundle for the Shopic Webflow site.",
5
+ "license": "UNLICENSED",
6
+ "private": false,
7
+ "type": "module",
8
+ "main": "dist/index.js",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "dev": "cross-env NODE_ENV=development node ./bin/build.js",
14
+ "build": "cross-env NODE_ENV=production node ./bin/build.js",
15
+ "prepublishOnly": "npm run check && npm run lint && npm run build",
16
+ "lint": "eslint ./src && prettier --check ./src",
17
+ "lint:fix": "eslint ./src --fix",
18
+ "check": "tsc --noEmit",
19
+ "format": "prettier --write ./src",
20
+ "test": "playwright test",
21
+ "test:ui": "playwright test --ui",
22
+ "update": "pnpm update -i -L -r"
23
+ },
24
+ "devDependencies": {
25
+ "@changesets/changelog-git": "^0.2.0",
26
+ "@changesets/cli": "^2.27.12",
27
+ "@eslint/js": "^9.19.0",
28
+ "@finsweet/eslint-config": "^3.0.3",
29
+ "@finsweet/ts-utils": "^0.40.0",
30
+ "@finsweet/tsconfig": "^1.4.2",
31
+ "@playwright/test": "^1.50.1",
32
+ "cross-env": "^7.0.3",
33
+ "esbuild": "^0.24.2",
34
+ "eslint": "^9.19.0",
35
+ "eslint-config-prettier": "^10.0.1",
36
+ "eslint-plugin-prettier": "^5.2.3",
37
+ "eslint-plugin-simple-import-sort": "^12.1.1",
38
+ "gsap": "^3.13.0",
39
+ "prettier": "^3.4.2",
40
+ "typescript": "^5.7.3",
41
+ "typescript-eslint": "^8.23.0"
42
+ },
43
+ "engines": {
44
+ "pnpm": ">=10"
45
+ },
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/wlrx/shopic.git"
49
+ },
50
+ "packageManager": "pnpm@11.5.3+sha512.7ac1c919341c213a34dc0d02afb7143c5c26ac26ee8c4782deea821b8ac64d2134a081fd8941dae6e29bbb48f58dfc2b7fbceeccc07cb2f09d219d342a4969ed"
51
+ }