RepoPilotOpen in app →

metafizzy/zdog

Flat, round, designer-friendly pseudo-3D engine for canvas & SVG

Concerns

Stale and unlicensed — last commit 3y ago

weakest axis
Use as dependencyConcerns

no license — legally unclear; last commit was 3y ago…

Fork & modifyConcerns

no license — can't legally use code; no tests detected…

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isConcerns

no license — can't legally use code; last commit was 3y ago…

  • 5 active contributors
  • Stale — last commit 3y ago
  • Single-maintainer risk — top contributor 95% of recent commits
  • No license — legally unclear to depend on
  • No CI workflows detected
  • No test directory detected
What would change the summary?
  • Use as dependency ConcernsMixed if: publish a permissive license (MIT, Apache-2.0, etc.); 1 commit in the last 365 days
  • Fork & modify ConcernsMixed if: add a LICENSE file
  • Deploy as-is ConcernsMixed if: add a LICENSE file

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Earn the “Healthy” badge

Current signals for metafizzy/zdog are Concerns. The embed flow is reserved for repos showing Healthy signals — the rest stay informational on this page so we're not putting a public call-out on your README. Address the items in the What would change the summary? dropdown above, then return to grab the embed code.

Common quick wins: green CI on default branch, no Critical CVEs in dependencies, recent commits on the default branch, a permissive license, and a published README.md with a quickstart.

Onboarding doc

Onboarding: metafizzy/zdog

Generated by RepoPilot · 2026-05-07 · Source

Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/metafizzy/zdog shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

Verdict

AVOID — Stale and unlicensed — last commit 3y ago

  • 5 active contributors
  • ⚠ Stale — last commit 3y ago
  • ⚠ Single-maintainer risk — top contributor 95% of recent commits
  • ⚠ No license — legally unclear to depend on
  • ⚠ No CI workflows detected
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live metafizzy/zdog repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/metafizzy/zdog.

What it runs against: a local clone of metafizzy/zdog — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in metafizzy/zdog | Confirms the artifact applies here, not a fork | | 2 | Default branch master exists | Catches branch renames | | 3 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 4 | Last commit ≤ 1053 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>metafizzy/zdog</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of metafizzy/zdog. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/metafizzy/zdog.git
#   cd zdog
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of metafizzy/zdog and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "metafizzy/zdog(\\.git)?\\b" \\
  && ok "origin remote is metafizzy/zdog" \\
  || miss "origin remote is not metafizzy/zdog (artifact may be from a fork)"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "js/index.js" \\
  && ok "js/index.js" \\
  || miss "missing critical file: js/index.js"
test -f "js/illustration.js" \\
  && ok "js/illustration.js" \\
  || miss "missing critical file: js/illustration.js"
test -f "js/vector.js" \\
  && ok "js/vector.js" \\
  || miss "missing critical file: js/vector.js"
test -f "js/canvas-renderer.js" \\
  && ok "js/canvas-renderer.js" \\
  || miss "missing critical file: js/canvas-renderer.js"
test -f "js/shape.js" \\
  && ok "js/shape.js" \\
  || miss "missing critical file: js/shape.js"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1053 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~1023d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/metafizzy/zdog"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Zdog is a lightweight pseudo-3D rendering engine that uses flat 2D shapes (circles, rectangles, paths) drawn on canvas or SVG to create the illusion of 3D objects. It applies 3D rotation math to 2D primitives without a heavyweight graphics pipeline, enabling designers to build animated 3D models with minimal overhead. The engine handles coordinate transforms, z-sorting, and drag-based rotation interaction natively. Flat structure: source lives in js/ (compiled to dist/zdog.dist.js and minified to .min.js), demos/ contains ~20 standalone demo projects (each with its own .js, .html, and ESLint config), and a tasks/ folder handles bundling and versioning. Each demo is independently runnable and uses Zdog classes like Illustration, Ellipse, Rect, Shape, and Group from the main export.

Who it's for

Web designers and interactive developers who want to create simple 3D animated scenes (product demos, data visualizations, games) without learning WebGL or complex game engines. The API is intentionally designer-friendly with properties like diameter, width, height, color, and translate rather than matrix algebra.

Maturity & risk

Zdog v1.1.3 is a stable beta-release (maintained since ~2018) with a small but complete feature set. The project is actively maintained—it has published npm/bower distributions (zdog.dist.min.js), documented demos, and an issue tracker. However, Dave DeSandro explicitly states in the README that v1 is 'beta-release' and 'Expect lots of changes for v2,' indicating it is production-ready for simple use cases but not yet at major-version stability. No CI/test suite is visible in the repo structure.

This is a single-maintainer project (Dave DeSandro) with minimal dependencies (only ESLint and UglifyJS for build tooling). The lack of visible test suite or CI pipeline means regressions could slip through. The codebase is relatively small (~57KB JavaScript) so the surface area for bugs is bounded, but the statement that 'I probably got some stuff wrong' in the README signals the author's own awareness of potential issues. No breaking-change policy is documented.

Active areas of work

The repo is in low-activity maintenance mode. Package.json shows v1.1.3; the version script triggers bundling and minification on releases. Contributing guidelines exist (.github/contributing.md) and an issue template (.github/issue_template.md) is set up to guide bug reports. No PRs or active milestones are visible in the file list, suggesting the v1 feature set is considered complete.

Get running

git clone https://github.com/metafizzy/zdog.git
cd zdog
npm install
npm run lint

Then open any demo (e.g., demos/hello-world-canvas/index.html) in a browser, or run npm run bundle to rebuild dist/zdog.dist.js from source.

Daily commands: For development: npm run bundle rebuilds the dist files from js/ sources. For production: npm run dist runs both bundle and uglify tasks. To view demos, serve the repo root with any static HTTP server (e.g., npx http-server) and navigate to demos/<demo-name>/index.html. Each demo is self-contained and includes a <script src="../../dist/zdog.dist.js"></script> tag.

Map of the codebase

  • js/index.js — Main entry point that exports all Zdog classes; every contributor must understand what's publicly exposed
  • js/illustration.js — Core Illustration class that manages rendering, animation loops, and drag interactions; backbone of the engine
  • js/vector.js — Vector math primitives for 3D coordinate transformations; used throughout all shape and transform logic
  • js/canvas-renderer.js — Canvas rendering pipeline that projects 3D shapes to 2D; critical for visual output on canvas elements
  • js/shape.js — Abstract base class for all drawable objects (circles, rectangles, polygons); defines rendering contract
  • js/group.js — Container for hierarchical scene graphs; handles transform propagation and child rendering order
  • tasks/bundle.js — Build script that bundles all JS modules into distributable artifacts; required for release workflow

Components & responsibilities

  • Illustration — Scene container and animation orchestrator; manages element

How to make changes

Add a new 3D primitive shape

  1. Create js/your-shape.js extending from Shape class; implement render() method that creates polygons for each face (js/your-shape.js)
  2. Add export statement to js/index.js: assign class to Zdog namespace (js/index.js)
  3. Create demo in demos/your-shape/ with index.html and your-shape.js showing the shape in action (demos/your-shape/index.html)
  4. Run npm run dist to rebuild and bundle the distribution files (tasks/bundle.js)

Add a new rendering backend (e.g., WebGL)

  1. Create js/webgl-renderer.js with a render(shapes) method that iterates shape list (js/webgl-renderer.js)
  2. Modify js/illustration.js to accept a renderer option and dispatch render calls to it (js/illustration.js)
  3. Export new renderer class in js/index.js (js/index.js)

Add a new demo

  1. Create demos/your-demo/index.html with canvas or svg element and script tag (demos/your-demo/index.html)
  2. Create demos/your-demo/your-demo.js with Zdog.Illustration instance and shape definitions (demos/your-demo/your-demo.js)
  3. No build step required; demo loads bundled zdog from dist/ or via CDN (demos/your-demo/your-demo.js)

Fix or extend vector math

  1. Edit js/vector.js to add new methods (e.g., dot product, cross product) or modify existing transform logic (js/vector.js)
  2. Verify all shape classes that use Vector still work; check demos/box-cross/, demos/shapes/ (demos/box-cross/box-cross.js)
  3. Run npm run lint to ensure code style; then npm run dist to rebuild (tasks/bundle.js)

Why these technologies

  • Canvas 2D & SVG — Designer-friendly output formats that work in all browsers; avoid WebGL complexity for pseudo-3D use cases
  • Vector math (translate, rotate, scale) — Fundamental to 3D graphics; enables transform composition and hierarchical scene graphs
  • UMD bundling (CommonJS + AMD + global) — Supports npm, bower, and direct <script> tag usage; maximizes distribution reach
  • ESLint (no TypeScript) — Lightweight code style enforcement; library is small and self-documenting enough without type annotations

Trade-offs already made

  • Pseudo-3D (orthographic projection) instead of true perspective 3D

    • Why: Simplifies math, favors flat design aesthetic, enables designer control
    • Consequence: Shapes do not converge to vanishing points; suitable for illustrations but not photorealistic rendering
  • Flat scene graph (no z-buffer): depth sorting by painters algorithm

    • Why: Avoids 3D context overhead; compatible with SVG and 2D canvas
    • Consequence: Overlapping shapes must be reordered manually; not suitable for complex occlusion
  • Single Illustration per element; no nested canvases/SVG

    • Why: Simplifies rendering pipeline and event handling
    • Consequence: Cannot easily compose multiple independent scenes on one page
  • Immediate-mode rendering (redraw every frame) vs. retained-mode

    • Why: Simplicity; animation-first design
    • Consequence: Higher CPU usage if many shapes; not optimized for static scenes

Non-goals (don't propose these)

  • Real-time 3D rendering with lighting and shading (orthographic pseudo-3D only)
  • Physics simulation or collision detection
  • Animation timeline/keyframe system (user must implement via requestAnimationFrame)
  • Text rendering or typography (shapes only)
  • Accessibility features (SVG fallback exists but ARIA not built-in)
  • Mobile touch gesture abstractions beyond basic drag (pinch zoom, multi-touch not included)

Traps & gotchas

No hidden traps are obvious from the repo structure. The build system is simple (Node.js bundler + UglifyJS, no transpiler or polyfill logic required). No environment variables, secrets, or service dependencies are needed. One minor quirk: the tasks/bundle script path is listed but not shown; consult that file to understand how js/ is concatenated into dist/. The demo .eslintrc.js differs from the root one, so demo code has its own linting rules (likely more permissive for example code).

Architecture

Concepts to learn

  • Isometric and dimetric projection — Zdog uses a form of flat 3D projection where shapes are rotated in 3D space but rendered as 2D primitives; understanding projection matrices helps debug visual distortion
  • Z-order sorting / Painter's algorithm — Zdog must sort and render shapes back-to-front (by z-depth) to show occlusion correctly; this is core to why updateRenderGraph() exists
  • Rotation matrices (3D affine transforms) — The rotate and translate properties apply 3D rotation matrices to 2D shapes; Zdog's core math comes from 3D rotation principles, not 2D CSS transforms
  • Sprite-based pseudo-3D rendering — Zdog uses the same technique as the 1995 game Dogz: flat 2D sprites (circles, rects) positioned in 3D space to create an illusion of 3D geometry without mesh rendering
  • Canvas vs SVG rendering contexts — Zdog supports both canvas 2D and SVG DOM rendering; choosing between them affects performance (canvas is raster, SVG is vector and interactive via DOM)
  • Graph scene graph and hierarchical transforms — Zdog's Group class builds a scene graph; child shapes inherit parent rotations and translations, enabling articulated models like the Kirby parasol demo
  • Stroke and fill rendering (canvas/SVG styling) — Zdog exposes stroke, color, fill properties on shapes; understanding how canvas strokeStyle/fillStyle and SVG stroke/fill attributes map is key to customizing visuals

Related repos

  • mrdoob/three.js — Industry-standard WebGL 3D engine; Zdog's lightweight alternative for designers who find Three.js overly complex
  • jnordberg/MotionFramework — Another designer-friendly animation framework; different approach but targets similar use cases (simple animated visuals without game engine overhead)
  • jaames/zfont — Official community plugin for Zdog that adds text rendering; extends core Zdog with typography capability
  • niklasvh/html2canvas — Complements Zdog for capturing rendered scenes as images (useful for exporting Zdog animations to PNG/JPEG)
  • metafizzy/isotope — By the same author (David DeSandro); uses similar class-based design and designer-friendly API patterns that influenced Zdog

PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add unit tests for core shape classes (Box, Cone, Cylinder, Hemisphere, Ellipse)

The repo has no visible test directory despite having complex geometric shape classes in js/box.js, js/cone.js, js/cylinder.js, js/hemisphere.js, and js/ellipse.js. These shapes are fundamental to the library and would benefit from unit tests covering instantiation, property mutations, and rendering. This would improve maintainability and catch regressions early.

  • [ ] Create a test/ directory with test infrastructure (Jest or similar)
  • [ ] Add unit tests for js/box.js covering constructor, position/rotation properties, and bounds calculation
  • [ ] Add unit tests for js/cone.js, js/cylinder.js, js/hemisphere.js covering shape-specific geometry
  • [ ] Add unit tests for js/ellipse.js covering diameter, stroke, and fill properties
  • [ ] Add test script to package.json (separate from lint-only 'test' command)
  • [ ] Integrate tests into preversion hook in package.json

Add GitHub Actions workflow for automated builds and distribution validation

The repo has npm scripts for bundling (bundle, dist, uglify) but no CI pipeline to validate that dist files are correctly generated on each commit. The dist/ folder is committed to git (per the version script), so ensuring the build artifacts are always valid is critical. This prevents accidental commits of stale or malformed minified files.

  • [ ] Create .github/workflows/build.yml
  • [ ] Add job to run 'npm run lint' on every push and PR
  • [ ] Add job to run 'npm run dist' and verify dist/ files match expected output (checksums or diff)
  • [ ] Add job to verify dist files can be imported as ES modules and UMD
  • [ ] Configure workflow to block PRs if build or validation fails

Document and test SVG renderer feature parity with Canvas renderer

The codebase has both js/canvas-renderer.js and SVG rendering capabilities (seen in demos/hello-world-svg), but there's no documentation matrix showing which shapes/features work in SVG vs Canvas. The file list suggests incomplete SVG coverage. A contribution could document supported features per renderer and add integration tests.

  • [ ] Create docs/renderer-support.md matrix showing Canvas vs SVG support for each shape (Box, Cone, Cylinder, Hemisphere, Ellipse, Path)
  • [ ] Add test cases in test/renderers/ covering the same demo (e.g., box rendering in both Canvas and SVG)
  • [ ] Identify any shape classes missing SVG renderer implementations and document as 'not yet supported'
  • [ ] Add a demo template or utility in demos/ that renders the same scene to both Canvas and SVG side-by-side for visual regression testing

Good first issues

  • Add unit tests for shape rotation and coordinate transforms (e.g., test that a 90° rotation around y-axis moves z to x correctly). Currently no test/ directory exists; mocha + assert or jest could be added.
  • Write a demo showing SVG text rendering with Zdog (demos/no-illo-svg and demos/no-illo-canvas show raw rendering, but no typography example exists). Check if Zfont is a blocker or if native SVG <text> can be added to an Illustration.
  • Document the internal class hierarchy and 3D math assumptions in a ARCHITECTURE.md file (README links to Khan Academy source but no local reference). Add examples of custom Shape subclasses in docs/extending.md.

Top contributors

Recent commits

  • dde8684 — 1.1.3 (desandro)
  • 5dfedd0 — 📦 greenkeep dependencies (desandro)
  • a9c2dad — Bump lodash from 4.17.15 to 4.17.19 (dependabot[bot])
  • 72c3c0d — 👕 use eslint-plugin-metafizzy; pt 1 (desandro)
  • 517e993 — 1.1.2 (desandro)
  • 8ea7603 — 📦 bump acorn dep; 2020 copyright (desandro)
  • 74e2861 — 🐶 v1.1.1 (desandro)
  • 0711558 — 📦 update deps: eslint & uglify-js (desandro)
  • d23ee65 — 🏗 Remove Makefile in favor of npm scripts (desandro)
  • f91e46a — Merge branch 'master' of github.com:metafizzy/zdog (desandro)

Security observations

The Zdog codebase has a moderate security posture with no critical vulnerabilities in the code itself, but faces significant risks from outdated development dependencies. The main concerns are: (1) ESLint and UglifyJS are 2-4 years outdated with unpatched vulnerabilities, (2) potential XSS risks in SVG/canvas rendering if user input isn't sanitized, and (3) lack of automated security scanning in the build pipeline. The library is a graphics engine focused on rendering, not data handling, which reduces injection attack surface. Recommendations include immediate dependency updates, implementing input validation for SVG/canvas operations, and adding security-focused npm scripts to the CI/CD pipeline.

  • High · Outdated ESLint Dependency — package.json - devDependencies.eslint. ESLint is pinned to version ^8.7.0, which is significantly outdated. ESLint 8.7.0 was released in January 2022. Current versions (9.x and above) contain multiple security patches and bug fixes. Using outdated tools increases exposure to known vulnerabilities in the linting infrastructure. Fix: Update ESLint to the latest stable version (^9.0.0 or higher) to receive security patches and improvements. Run 'npm update eslint' and test the codebase for any breaking changes.
  • High · Outdated UglifyJS Dependency — package.json - devDependencies.uglify-js. UglifyJS is pinned to version ^3.6.3, released in 2019. This is a 4+ year old version with potentially unpatched security vulnerabilities. UglifyJS is used for production minification, making it critical to the build pipeline. Newer versions provide better security and performance. Fix: Update UglifyJS to ^3.17.0 or consider migrating to modern alternatives like Terser (^5.x), which is actively maintained and provides better ES6+ support and security.
  • Medium · Missing Dependency Integrity Checks — package.json and project root. The package.json lacks a lock file specification or integrity verification mechanism. While a package-lock.json exists, there's no evidence of hash verification or signed commits for dependency management, increasing risk of supply chain attacks. Fix: Ensure package-lock.json is committed to version control and used consistently. Consider enabling npm audit via 'npm audit' regularly and configure CI/CD to fail on moderate/high vulnerabilities. Consider using npm's --audit-level flag in CI/CD pipelines.
  • Medium · Potential XSS Vulnerability in Canvas/SVG Rendering — js/svg-renderer.js, js/canvas-renderer.js. The codebase includes SVG rendering capabilities (svg-renderer.js) and canvas rendering (canvas-renderer.js). If user input is directly used in SVG path generation or element attributes without sanitization, XSS attacks could occur. No evidence of input validation or sanitization in the file structure. Fix: Implement strict input validation for all user-provided data that affects SVG/canvas rendering. Sanitize SVG attributes and path data. Consider using DOMPurify or similar libraries if DOM manipulation is involved. Document safe usage patterns for developers.
  • Low · Missing npm Audit Configuration — package.json - scripts section. The package.json does not include audit-level configuration or security-focused npm scripts. There's no evidence of automated security scanning in the build pipeline. Fix: Add 'npm audit' to CI/CD pipeline. Add a security script: '"audit": "npm audit --audit-level=moderate"' to package.json and integrate into the preversion hook to catch vulnerabilities before releases.
  • Low · No Content Security Policy Documentation — README.md, documentation. Being a pseudo-3D graphics engine with canvas/SVG support, the library could be vulnerable to CSP bypasses if users don't implement proper headers when embedding it in web applications. No CSP guidance in documentation. Fix: Add security guidelines to README.md or documentation covering: recommended CSP headers, safe usage patterns, input validation requirements, and warnings about user-generated content handling.

LLM-derived; treat as a starting point, not a security audit.

Where to read next


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Concerning signals · metafizzy/zdog — RepoPilot