OpenSCAD WASM for 3D Preview Rendering¶
- Date: 2026-02-24
- Author: Architecture Research
- Status: Draft
- Audience: Engineering team, product stakeholders
Table of Contents¶
- 1. Executive Summary
- 2. Current Architecture
- 3. What is OpenSCAD WASM?
- 4. How GridFlock's Web Editor Works
- 5. Architecture Options
- 6. Benefits
- 7. Risks and Challenges
- 8. Licensing Analysis
- 9. Comparison Matrix
- 10. Recommended Approach
- 11. Implementation Plan
- 12. References
1. Executive Summary¶
Our current 3D preview pipeline reimplements GridFlock geometry in JSCAD (@jscad/modeling),
serializes to STL on the server, and renders via Three.js on the client. This approach suffers from
geometry artifacts (internal faces from CSG operations), difficulty matching connector geometry, and
ongoing maintenance burden as GridFlock evolves upstream.
This document evaluates replacing the JSCAD geometry layer with OpenSCAD compiled to
WebAssembly (WASM), allowing us to use the original gridflock.scad source directly. Three
architectural options are assessed: client-side WASM rendering, server-side OpenSCAD rendering,
and embedding/linking to the existing GridFlock web editor.
Recommendation: A hybrid approach — use OpenSCAD server-side (CLI in Docker) for STL generation to avoid GPL contamination of our client bundle, while keeping Three.js for rendering. This provides pixel-perfect GridFlock output with minimal architecture change and no licensing risk.
2. Current Architecture¶
Data Flow¶
User Input (Shopify Theme)
│
▼
POST /api/v1/gridflock/preview { widthMm, heightMm }
│
▼
GridflockPreviewService
├── calculatePlateSet() → PlateSpec[]
├── For each plate:
│ └── generateGridFlockPlate()
│ ├── JSCAD: base-plate.ts (rounded rectangle)
│ ├── JSCAD: grid-cells.ts (cell cutters)
│ ├── JSCAD: intersection-puzzle.ts (connectors)
│ ├── JSCAD: magnet-holes.ts (cavities)
│ └── serializeToStl() → Buffer
└── combineStlBuffers() → Combined STL
│
▼
Binary STL → Client
│
▼
configurator-3d.js
├── STLParser.parse() → THREE.BufferGeometry
└── MeshStandardMaterial → Three.js Scene
Key Files¶
| Layer | File | Purpose |
|---|---|---|
| Server | libs/gridflock-core/src/lib/generator.ts |
Orchestrates JSCAD geometry |
| Server | libs/gridflock-core/src/lib/serializer.ts |
JSCAD → binary STL |
| Server | libs/gridflock-core/src/lib/geometry/*.ts |
Individual geometry modules |
| Server | libs/gridflock-core/src/lib/stl-combiner.ts |
Merges plate STLs |
| Server | apps/gridflock-service/src/gridflock/ |
Preview REST endpoint |
| Client | deployment/shopify-theme/assets/configurator-3d.js |
Three.js rendering |
| Client | deployment/shopify-theme/sections/configurator.liquid |
Shopify Liquid template |
Known Issues¶
- Internal faces/artifacts: JSCAD CSG operations create internal geometry visible in
Three.js when faces overlap. Simplification hacks (e.g., omitting lip details in
base-plate.ts) reduce but don't eliminate these. - Connector fidelity: The intersection puzzle connectors in JSCAD are approximations of GridFlock's SVG-derived puzzle shapes. Getting exact geometry match is difficult.
- Maintenance burden: Every upstream GridFlock feature (edge puzzle, click latch, ClickGroove, vertical screws, thumb screws, filler algorithms) must be manually reimplemented.
- Rendering quality: The preview does not match the quality users see when they import the actual GridFlock STL into a slicer.
3. What is OpenSCAD WASM?¶
Overview¶
OpenSCAD is a programmable CAD modeler that creates 3D models from
script files (.scad). It uses Constructive Solid Geometry (CSG) with an exact geometry kernel
(historically CGAL, now with optional Manifold backend).
OpenSCAD WASM is a full port of the OpenSCAD engine to WebAssembly, enabling it to run in modern web browsers or any WASM runtime (Node.js, Deno, server-side).
Key Projects¶
| Project | Repository | Description | Stars |
|---|---|---|---|
| openscad-wasm | openscad/openscad-wasm | Official WASM port, npm package openscad-wasm |
~360 |
| OpenSCAD Playground | openscad/openscad-playground | Full web IDE (Monaco editor + 3D viewer) | ~200 |
| Web OpenSCAD Customizer | vector76/Web_OpenSCAD_Customizer | Lightweight parametric customizer UI | ~44 |
| DSchroer/openscad-wasm | DSchroer/openscad-wasm | Earlier independent WASM port | — |
NPM Package¶
- Package:
openscad-wasm(version 0.0.4) - License: GPL-2.0
- Distribution: Available via npm and jsDelivr CDN
- Format: ES6 module with
.wasmbinary
API Surface¶
The WASM module exposes an Emscripten-based API:
import OpenSCAD from 'openscad-wasm';
const instance = await OpenSCAD();
// Write .scad source to the virtual filesystem
instance.FS.writeFile('/model.scad', scadSource);
// Write dependency files (libraries, SVGs, etc.)
instance.FS.writeFile('/puzzle.svg', svgContent);
instance.FS.mkdir('/gridfinity-rebuilt-openscad');
instance.FS.writeFile('/gridfinity-rebuilt-openscad/gridfinity-rebuilt-utility.scad', ...);
// Run OpenSCAD with command-line arguments
instance.callMain([
'/model.scad',
'-o', '/output.stl',
'-D', 'plate_size=[200,200]',
'-D', 'bed_size=[256,256]',
'-D', 'connector_intersection_puzzle=true',
]);
// Read the generated STL
const stlData = instance.FS.readFile('/output.stl');
Maturity Assessment¶
| Aspect | Status |
|---|---|
| Core functionality | Stable — full OpenSCAD feature set |
| Browser compatibility | Chrome, Firefox, Safari (modern) |
| Manifold backend | Supported — 10-100x faster than CGAL for unions |
| Font support | Included (bundled fonts add to size) |
| Community adoption | Growing — used by Perplexing Labs, Gridfinity tools |
| npm releases | Infrequent (v0.0.4), but repo is active |
| Documentation | Minimal — mostly examples and blog posts |
4. How GridFlock's Web Editor Works¶
Architecture¶
The GridFlock web editor at gridflock.yawk.at is powered by the Perplexing Labs Gridfinity Generator platform, which is a general-purpose OpenSCAD WASM customizer. The flow:
- The
editor.tomlfile in the GridFlock repo defines the parametric UI - The platform reads
editor.tomland generates HTML form controls - User changes are encoded in the URL fragment (Base64 JSON) for shareability
- Parameter values are passed to OpenSCAD WASM via
-Dflags - OpenSCAD WASM renders the
.scadfile to STL in a Web Worker - The STL is displayed in a 3D viewer (model-viewer / Three.js)
- Users can download the generated STL
The editor.toml Format¶
The editor.toml file is a configuration schema that drives the parametric editor UI. Key
sections:
[project]
name = "GridFlock"
uri = "https://github.com/yawkat/GridFlock"
export-filename-prefix = "GridFlock"
mode = "single"
[[model]]
file = "gridflock.scad"
# Parameter metadata controls UI rendering
[model.param-metadata.bed_size.presets]
text = "Printer Presets"
[model.param-metadata.bed_size.presets.values]
"Bambu Lab X1/P1/P2/A1" = [256, 256]
"Prusa Core One/+/MK4/S" = [250, 220]
# ...more presets
# Tab grouping with conditional visibility
[model.tab-metadata."Magnets"]
control-boolean = "magnets"
help-link = "https://github.com/yawkat/GridFlock/blob/main/README.md#magnets"
[model.param-metadata.magnet_style]
display-condition = {js = "magnets"}
Notable features of editor.toml:
- Printer presets: Dropdown with bed sizes for ~20 printer models
- Tab groups: Collapsible sections (Magnets, Connectors, Filler, etc.)
- Conditional visibility: Parameters show/hide based on other parameter values
- Help links: Each parameter links to README documentation
- Analytics tracking: Umami event tracking on render/export actions
Dependencies¶
GridFlock's .scad file requires:
- gridfinity-rebuilt-openscad — Git submodule (MIT license) for baseplate cutter geometry
- puzzle.svg — SVG file containing the intersection puzzle connector paths
- extract_paths.py — Python script to convert SVG paths to OpenSCAD polygon data
The web editor bundles all dependencies into the WASM virtual filesystem before rendering.
5. Architecture Options¶
Option A: Client-Side OpenSCAD WASM¶
Run the full OpenSCAD WASM engine in the user's browser.
User Input (Shopify Theme)
│
▼
JavaScript: collect parameters
│
▼
Web Worker: OpenSCAD WASM
├── Load gridflock.scad + dependencies into FS
├── callMain([...params]) → generates STL
└── Return STL ArrayBuffer
│
▼
Three.js: parse STL → render scene
| Factor | Assessment |
|---|---|
| Complexity | High — must bundle WASM + .scad + dependencies in Shopify theme |
| Bundle size | ~15-30 MB (WASM binary + fonts), ~1.7 MB with LZMA compression |
| Performance | 5-60 seconds render depending on model complexity and device |
| UX | Loading spinner during render; responsive UI via Web Worker |
| Server load | None — all computation client-side |
| Licensing | GPL-2.0 WASM bundle in our client code — significant concern |
| Shopify CSP | Requires wasm-unsafe-eval directive; may conflict with theme policies |
| Offline capable | Yes, after initial load |
Option B: Server-Side OpenSCAD (CLI or WASM)¶
Run OpenSCAD on the server, keep Three.js on the client for rendering.
User Input (Shopify Theme)
│
▼
POST /api/v1/gridflock/preview { params }
│
▼
Server: OpenSCAD CLI (Docker container)
├── Write params to .scad variables
├── Execute: openscad gridflock.scad -o output.stl -D "..."
└── Return STL binary
│
▼
Three.js: parse STL → render scene
Sub-option B1: OpenSCAD CLI in Docker
- Use the official
openscad/openscadDocker image - Execute as a subprocess with timeout
- Well-understood deployment pattern
Sub-option B2: OpenSCAD WASM in Node.js
- Run the WASM module server-side in Node.js/Deno
- No Docker overhead, same process
- Less battle-tested in production
| Factor | Assessment |
|---|---|
| Complexity | Medium — replaces JSCAD generator; keeps existing API/client |
| Bundle size | No client impact — WASM stays on server |
| Performance | 5-30s server-side (faster hardware than client); can cache results |
| UX | Same as current — loading indicator while server generates |
| Server load | Higher CPU per request; mitigated by caching |
| Licensing | GPL stays server-side; output STL files are not GPL-encumbered |
| Shopify CSP | No changes needed |
| Caching | Deterministic output — same params = same STL; excellent cache hit rate |
Option C: Embed GridFlock Web Editor¶
Use the existing GridFlock editor at gridflock.yawk.at via iframe or direct link.
User Input (Shopify Theme)
│
▼
<iframe src="https://gridflock.yawk.at/?params=...">
│
▼
GridFlock editor handles everything
├── OpenSCAD WASM rendering
├── 3D preview
└── STL download
| Factor | Assessment |
|---|---|
| Complexity | Low — just embed an iframe |
| Bundle size | Zero — external resource |
| Performance | Dependent on GridFlock's infrastructure |
| UX | Poor — no Forma3D branding, separate UI, no integration with order flow |
| Server load | None |
| Licensing | No code integration — just linking |
| Customization | Very limited — can only pass URL parameters |
| Business risk | High — dependency on external service availability |
6. Benefits¶
Pixel-Perfect Output¶
OpenSCAD uses the same geometry kernel as the original GridFlock project. The generated STL will be mathematically identical to what users produce with the GridFlock editor or CLI. No approximation artifacts, no internal faces, no geometry mismatch.
No Geometry Reimplementation¶
Our current JSCAD layer (libs/gridflock-core/src/lib/geometry/) reimplements every GridFlock
feature from scratch. With OpenSCAD, we use gridflock.scad directly:
| Feature | Current (JSCAD) | With OpenSCAD |
|---|---|---|
| Base plate | base-plate.ts (custom) |
Built into gridflock.scad |
| Grid cells | grid-cells.ts (custom) |
Gridfinity Rebuilt (exact) |
| Intersection puzzle | intersection-puzzle.ts (approximation) |
puzzle.svg (exact) |
| Edge puzzle | edge-puzzle.ts (custom) |
gridflock.scad (exact) |
| Magnet holes | magnet-holes.ts (custom) |
gridflock.scad (exact) |
| Click latch | Not implemented | gridflock.scad (exact) |
| ClickGroove | Not implemented | gridflock.scad (exact) |
| Vertical screws | Not implemented | gridflock.scad (exact) |
| Thumb screws | Not implemented | gridflock.scad (exact) |
| Filler algorithms | Not implemented | gridflock.scad (exact) |
| Numbering | numbering.ts (simplified) |
gridflock.scad (full fonts) |
Automatic Upstream Updates¶
When GridFlock adds new features or fixes bugs, we can update by pulling the latest .scad
files. No reverse-engineering or manual reimplementation required.
Community Alignment¶
GridFlock is actively developed (48 stars, regular commits) and used by the broader Gridfinity community. Using the same geometry engine ensures our output is compatible with community expectations and slicer profiles.
Reduced Maintenance Surface¶
Eliminating the JSCAD geometry layer removes ~1,500 lines of custom geometry code and associated tests. The remaining integration code (parameter mapping, STL serving) is simpler and less error-prone.
7. Risks and Challenges¶
Bundle Size (Client-Side Only)¶
The OpenSCAD WASM binary is substantial:
| Component | Raw Size | Compressed (gzip) | Compressed (LZMA) |
|---|---|---|---|
openscad.wasm |
~25 MB | ~8 MB | ~1.7 MB |
| Fonts | ~5 MB | ~3 MB | ~1.5 MB |
| JS glue code | ~500 KB | ~150 KB | ~100 KB |
| Total | ~30 MB | ~11 MB | ~3.3 MB |
This is prohibitive for a Shopify storefront where page load time directly impacts conversion. Mitigation: Use server-side rendering (Option B) to keep the client bundle unchanged.
Render Time¶
OpenSCAD rendering is computationally expensive. Estimated times for GridFlock baseplates:
| Model Complexity | Desktop (native) | WASM (browser) | WASM (server) |
|---|---|---|---|
| Simple 2×2 plate | 2-5s | 5-15s | 3-8s |
| Medium 4×4 plate | 5-15s | 15-45s | 8-20s |
| Complex 6×6 with magnets | 15-45s | 45-120s | 20-50s |
The Manifold backend (enabled by default in recent builds) provides 10-100x speedup over the legacy CGAL kernel for union operations, significantly reducing these times.
Mitigation strategies:
- Aggressive caching (parameter hash → STL)
- Background pre-generation for common configurations
- Use Manifold backend for fastest rendering
- Limit preview to single segments, not full plate sets
GridFlock Dependencies¶
Running gridflock.scad requires bundling:
- The
gridflock.scadfile itself - The
gridfinity-rebuilt-openscadlibrary (Git submodule) - The
puzzle.svgfile (connector paths) - Pre-extracted polygon data from
extract_paths.py
These must be loaded into the WASM virtual filesystem before rendering. The extraction step
(just paths) converts SVG to OpenSCAD polygon data and must be run during the build process.
Customization Constraints¶
Adding Forma3D-specific features (custom branding, proprietary geometry) to gridflock.scad
requires understanding OpenSCAD syntax. While OpenSCAD is programmable, it has a steeper learning
curve than JSCAD/JavaScript for our team.
External Dependency Risk¶
| Dependency | Risk | Mitigation |
|---|---|---|
openscad-wasm |
npm package updates lag behind OpenSCAD releases | Pin version; build from source if needed |
GridFlock |
Upstream breaking changes | Pin to specific commit/tag |
gridfinity-rebuilt-openscad |
API changes in library | Pinned via GridFlock's submodule |
| OpenSCAD itself | Major version changes | Use specific WASM build |
Shopify Theme Constraints (Client-Side Only)¶
| Constraint | Impact |
|---|---|
CSP: wasm-unsafe-eval required |
Must be explicitly allowed in theme headers |
| Asset size limits | Shopify themes have 50MB total asset limits |
| CDN caching | WASM files are not typical Shopify assets |
| Mobile performance | WASM execution on mobile devices is significantly slower |
8. Licensing Analysis¶
License Summary¶
| Component | License | Implications |
|---|---|---|
| OpenSCAD engine | GPL-2.0 | Copyleft — derivative works must be GPL |
| openscad-wasm | GPL-2.0 | Same as above — compiled from GPL source |
| GridFlock (gridflock.scad) | MIT | Permissive — can use freely |
| Gridfinity Rebuilt | MIT | Permissive — can use freely |
| Generated STL output | Not covered by GPL | Output of GPL tools is not GPL-encumbered |
Key Legal Considerations¶
Client-side WASM (Option A):
Bundling openscad-wasm (GPL-2.0) into our client JavaScript creates a GPL-encumbered
distribution. Our entire client-side codebase would arguably need to be released under GPL-2.0.
This is the most restrictive interpretation and represents a significant legal risk for a
commercial product.
The wasm-unsafe-eval CSP question adds technical complexity but does not resolve the licensing
concern.
Server-side execution (Option B): Running OpenSCAD as a tool on the server (CLI in Docker or WASM in Node.js) to generate STL output is analogous to using GCC (GPL) to compile code — the output is not GPL-encumbered. The GPL applies to the tool itself, not its output. This is the safest approach and is the standard interpretation for GPL build tools.
Our server code calls OpenSCAD as an external process, does not link against it, and does not distribute the GPL binary to end users. This approach has strong precedent and is widely practiced.
Embedding/linking (Option C):
Linking to gridflock.yawk.at via iframe carries no licensing obligations. We are not
distributing GPL software — we are linking to a third-party service.
Recommendation¶
Use Option B (server-side) to avoid any GPL contamination of our commercial codebase. The .scad
source files (MIT-licensed) and generated STL output are both freely usable.
9. Comparison Matrix¶
| Criterion | Current (JSCAD) | Option A (Client WASM) | Option B (Server OpenSCAD) | Option C (Embed Editor) |
|---|---|---|---|---|
| Geometry fidelity | Approximate | Exact | Exact | Exact |
| Feature coverage | Partial (~40%) | Complete (100%) | Complete (100%) | Complete (100%) |
| Bundle size impact | None | +11-30 MB | None | None |
| Server CPU cost | Medium | None | High (cacheable) | None |
| Initial load time | Fast | Slow (WASM load) | Fast | Medium (iframe) |
| Render latency | 1-5s | 5-120s | 3-50s | 5-120s |
| Caching potential | Low | Browser-side | Excellent (deterministic) | N/A |
| GPL risk | None | High | None | None |
| Shopify compatibility | Good | Problematic | Good | Moderate |
| Customization | Full (JS) | Full (SCAD) | Full (SCAD) | Limited (URL params) |
| UX integration | Seamless | Seamless | Seamless | Poor (iframe) |
| Maintenance burden | High | Low | Low | Very low |
| Upstream sync effort | High (reimpl.) | Low (file update) | Low (file update) | Zero |
| Mobile performance | Good | Poor | Good | Poor |
| Offline capability | No | Yes (after load) | No | No |
10. Recommended Approach¶
Primary Recommendation: Option B — Server-Side OpenSCAD CLI¶
Run OpenSCAD inside a Docker container on the server. Replace the JSCAD geometry pipeline with
direct execution of gridflock.scad. Keep the existing Three.js client and API contract.
Why this option:
- Zero client-side impact — no bundle size increase, no CSP changes, no mobile perf concern
- Zero GPL risk — OpenSCAD runs as a server-side tool, output STLs are not encumbered
- Pixel-perfect geometry — identical output to GridFlock editor
- Excellent caching — deterministic params → deterministic STL; Redis/disk cache
- Minimal API change — same endpoint, same binary STL response
- Future-proof — as GridFlock adds features, we update
.scadfiles
Caching Strategy¶
Given that OpenSCAD rendering is expensive (5-50s per plate), caching is critical:
Request: { widthMm: 450, heightMm: 320, magnets: false, connector: 'intersection-puzzle' }
│
▼
Cache key: SHA256(canonical JSON of all OpenSCAD params)
│
├── Cache HIT → return cached STL (< 50ms)
│
└── Cache MISS → run OpenSCAD → cache result → return STL
- L1 cache: In-memory LRU (hot configs, ~100 entries)
- L2 cache: Redis/disk (all generated STLs, TTL 7 days)
- Pre-warm: Generate common configurations on deploy
Preview Optimization¶
To reduce perceived latency for uncached configurations:
- Render a single representative segment instead of the full plate set
- Use a simplified
.scadvariant with reduced$fnfor faster preview - Show a low-poly placeholder immediately, upgrade when full render completes
- Return rendering progress via Server-Sent Events or WebSocket
11. Implementation Plan¶
Phase 1: Proof of Concept (T-shirt: S — 1-2 weeks)¶
Goal: Validate that gridflock.scad can run in Docker and produce correct STL output.
- Set up OpenSCAD Docker container with required dependencies
- Bundle
gridflock.scad,gridfinity-rebuilt-openscad, andpuzzle.svg - Run
extract_paths.pyto generate polygon data in build step - Execute OpenSCAD with sample parameters and verify STL output
- Compare output to GridFlock web editor output (binary diff or visual)
- Measure rendering times for various plate configurations
- Document parameter mapping between our API and OpenSCAD variables
Deliverable: Working Docker container that generates GridFlock STLs from parameters.
Phase 2: API Integration (T-shirt: M — 2-3 weeks)¶
Goal: Replace JSCAD geometry pipeline with OpenSCAD execution.
- Create
OpenScadGeneratorServiceinapps/gridflock-service - Implement parameter mapping: API DTO → OpenSCAD
-Dflags - Add subprocess execution with timeout and error handling
- Implement STL caching layer (Redis or disk-based)
- Update
PreviewControllerto use new service - Add health check for OpenSCAD container availability
- Write integration tests comparing output to known-good STLs
- Feature flag to toggle between JSCAD and OpenSCAD backends
Deliverable: Preview endpoint generating STLs via OpenSCAD behind a feature flag.
Phase 3: Production Hardening (T-shirt: M — 2-3 weeks)¶
Goal: Make the OpenSCAD pipeline production-ready.
- Add resource limits (CPU, memory, timeout) to OpenSCAD subprocess
- Implement request queuing to prevent server overload
- Add cache pre-warming for common printer presets
- Add monitoring and alerting for render times and failures
- Load test with concurrent requests
- Update Docker Compose / Kubernetes manifests
- Configure CI/CD pipeline for OpenSCAD container builds
- Remove feature flag and deprecate JSCAD pipeline
Deliverable: Production-grade OpenSCAD preview pipeline.
Phase 4: Enhanced Features (T-shirt: L — 3-5 weeks)¶
Goal: Leverage full GridFlock feature set in our product.
- Expose additional GridFlock parameters in the configurator UI
- Connector type selection (intersection puzzle, edge puzzle)
- Magnet options (press-fit, glued, none)
- Filler algorithm selection
- Click latch options
- Add STL download for production printing (not just preview)
- Implement progress feedback (SSE/WebSocket) for long renders
- Evaluate client-side WASM for an "advanced editor" mode (separate page, not storefront)
- Consider contributing Forma3D-specific features upstream to GridFlock
Deliverable: Full-featured configurator with all GridFlock capabilities.
Total Estimated Effort¶
| Phase | Size | Duration | Dependencies |
|---|---|---|---|
| Phase 1: PoC | S | 1-2 weeks | Docker, OpenSCAD |
| Phase 2: Integration | M | 2-3 weeks | Phase 1 |
| Phase 3: Hardening | M | 2-3 weeks | Phase 2 |
| Phase 4: Features | L | 3-5 weeks | Phase 3 |
| Total | 8-13 weeks |
12. References¶
OpenSCAD WASM¶
- openscad/openscad-wasm — Official WASM port
- openscad/openscad-playground — Web IDE
- OpenSCAD Playground (live) — Try it in the browser
- vector76/Web_OpenSCAD_Customizer — Lightweight customizer
- Build an OpenSCAD WASM Configurator — Tutorial
- openscad-wasm npm package — jsDelivr CDN
- WASM size discussion — Bundle optimization
GridFlock¶
- yawkat/GridFlock — Source repository
- GridFlock Generator — Live web editor
- Perplexing Labs Generator — Alternative host
- editor.toml — Parametric UI config
- gridflock.scad — Main OpenSCAD source
Performance¶
- OpenSCAD Fast CSG — 10x rendering speedup
- Manifold library — Modern CSG kernel used by OpenSCAD
- OpenSCAD benchmarks — Performance comparison
Licensing¶
- GPL and WASM (StackExchange) — Legal discussion
- Licensing and OpenSCAD — Practical guide
- OpenSCAD license — GPL-2.0 text
Shopify / CSP¶
- WASM CSP policy (W3C) —
wasm-unsafe-evalspec - Shopify CSP docs — Hydrogen CSP setup