qrohlf/trianglify
Algorithmically generated triangle art
Slowing — last commit 12mo ago
copyleft license (GPL-3.0) — review compatibility; no tests detected
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
last commit was 12mo ago; Scorecard "Token-Permissions" is 0/10
- ⚠Slowing — last commit 12mo ago
- ⚠Single-maintainer risk — top contributor 82% of recent commits
- ⚠GPL-3.0 is copyleft — check downstream compatibility
- ⚠No test directory detected
- ⚠Scorecard: marked unmaintained (0/10)
- ✓Last commit 12mo ago
- ✓10 active contributors
- ✓GPL-3.0 licensed
- ✓CI configured
What would improve this?
- →Use as dependency Concerns → Mixed if: relicense under MIT/Apache-2.0 (rare for established libs)
- →Deploy as-is Mixed → Healthy if: 1 commit in the last 180 days
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests + OpenSSF Scorecard
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.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/qrohlf/trianglify)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card
This card auto-renders when someone shares https://repopilot.app/r/qrohlf/trianglify on X, Slack, or LinkedIn.
Ask AI about qrohlf/trianglify
Grounded in the actual source code. Pick a starter question or write your own.
Onboarding doc
Onboarding: qrohlf/trianglify
Generated by RepoPilot · 2026-06-21 · Source
🎯Verdict
WAIT — Slowing — last commit 12mo ago
- Last commit 12mo ago
- 10 active contributors
- GPL-3.0 licensed
- CI configured
- ⚠ Slowing — last commit 12mo ago
- ⚠ Single-maintainer risk — top contributor 82% of recent commits
- ⚠ GPL-3.0 is copyleft — check downstream compatibility
- ⚠ No test directory detected
- ⚠ Scorecard: marked unmaintained (0/10)
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests + OpenSSF Scorecard</sub>
⚡TL;DR
Trianglify is a JavaScript library that algorithmically generates colorful low-poly triangle mesh art as SVG or Canvas output. It uses Delaunay triangulation on a grid of points, applies a color function to each triangle, and exports the result as SVG or PNG, commonly used for procedurally-generated background images. Single-file-focused architecture: src/trianglify.js is the main entry point returning a Pattern object. Utility functions live in src/utils/ (colorFunctions.js, geom.js, mulberry32.js PRNG). Build via Rollup produces dist/trianglify.js (Node) and dist/trianglify.bundle.js (browser bundle). Examples in examples/ demonstrate both browser and Node usage.
👥Who it's for
Web developers and designers who want to generate unique procedural background images for websites, dashboards, or applications without manual design work. Node.js users who need to batch-generate images server-side.
🌱Maturity & risk
Production-ready. Version 4.1.1 with complete test coverage (snapshots in src/snapshots/), CI pipeline via GitHub Actions (build.yml), and a stable 4.x release cycle. Active maintenance visible but not high-velocity—good for a stable utility library.
Low risk for core functionality. Only 3 production dependencies (chroma-js, delaunator, canvas), all reputable. Single maintainer (qr@qrohlf.com) is a mild concentration risk. GPLv3 license requires any consuming library to be open-source, which is a hard constraint for closed-source projects (though images generated are owned by the user).
Active areas of work
Project appears stable and minimally active—no specific milestones or open PRs visible from the provided data. The build pipeline and CI are well-established, suggesting maintenance focus rather than feature development.
🚀Get running
git clone https://github.com/qrohlf/trianglify.git && cd trianglify && npm install && npm run build && npm test
Daily commands: npm run dev (watch mode with Rollup), npm test (Jest), npm run build (production build), npm run lint (ESLint via Standard)
🗺️Map of the codebase
- src/trianglify.js: Main entry point containing the Pattern class and core triangulation + rendering logic
- src/utils/geom.js: Geometry utilities for point generation, triangle math, and coordinate transformations
- src/utils/colorFunctions.js: Color assignment strategies (gradient, function-based, fixed) used during triangle rendering
- src/pattern.js: Pattern object definition with toCanvas() and toSvg() export methods
- rollup.config.js: Build configuration producing both Node.js and browser bundle outputs
- src/snapshots/trianglify.browser.test.js.snap: Snapshot tests verify SVG and Canvas output hasn't regressed across builds
🛠️How to make changes
To add color schemes: edit src/utils/colorFunctions.js or src/utils/colorbrewer.js. To change geometry: modify src/utils/geom.js. To alter the core algorithm: edit src/trianglify.js (the Pattern class). To add examples: create .html files in examples/ or .js files for Node demos. Add tests to src/trianglify.browser.test.js or src/trianglify.node.test.js.
🪤Traps & gotchas
The canvas dependency requires build-time dependencies (cairo, node-gyp) that can fail on certain systems—ensure node-gyp prerequisites are installed before npm install. The library supports both browser (via unpkg CDN or bundlers) and Node.js, but examples use different APIs (canvas vs DOM)—check your environment. Color function parameter names are case-sensitive (cellSize, seed, colorFunction). The PRNG (mulberry32.js) is seeded but non-cryptographic—deterministic for demos but not for security.
💡Concepts to learn
- Delaunay triangulation — The core geometric algorithm that Trianglify uses to partition 2D space into non-overlapping triangles from random points; understanding this is essential to modifying geometry behavior
- Perlin noise / seeded PRNG — Trianglify uses mulberry32.js for seeded randomness to enable deterministic generation—the same seed always produces identical output, critical for reproducible demos
- Low-poly art / low-poly style — The visual aesthetic Trianglify targets—faceted, minimalist triangle-based imagery; understanding the style informs color function and cell size choices
- SVG rendering vs Canvas rendering — Trianglify outputs both SVG (scalable, editable) and Canvas (rasterized, performant); understanding the tradeoffs is critical for choosing export format
- Dual-build (Node.js + Browser) with Rollup — Trianglify uses Rollup to produce both a Node.js CommonJS module and a browser UMD bundle; understanding this dual-target build is necessary to modify dependencies or exports
- Canvas API (Node.js canvas module) — The Node.js version uses the 'canvas' npm package to provide a server-side Canvas-like API for PNG generation; differs subtly from browser Canvas
🔗Related repos
mapbox/delaunator— The underlying triangulation algorithm used by Trianglify; understanding delaunator.js is critical to modifying geometry behaviorjoblyon/verlet-js— Alternative physics-based procedural art generation; different algorithmic approach to generative backgroundsChartJS/Chart.js— Common companion library for users needing procedural backgrounds on data dashboards; Trianglify + Chart.js is a typical pairinggka/chroma.js— Direct dependency providing the color manipulation API; critical for understanding how colors are blended and generated
🪄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 src/utils/ modules
The utils directory contains critical functions (colorFunctions.js, geom.js, getScalingRatio.js, mulberry32.js) but there are no dedicated test files for these modules in src/snapshots. Currently only trianglify.browser.test.js and trianglify.node.test.js exist. Adding granular unit tests for each utility module would improve code reliability, catch regressions, and make future refactoring safer.
- [ ] Create src/utils/colorFunctions.test.js with tests for color palette selection and color function behavior
- [ ] Create src/utils/geom.test.js with tests for geometric calculations used in triangle generation
- [ ] Create src/utils/mulberry32.test.js to verify the PRNG produces consistent outputs for reproducible patterns
- [ ] Create src/utils/getScalingRatio.test.js to test DPI scaling behavior across different contexts
Add GitHub Actions workflow for cross-platform testing (Node.js + Canvas)
The build.yml workflow exists but the package.json 'ci' script suggests testing should run on canvas. The 'canvas' dependency (v2.6.1) is a native module that can have platform-specific issues. Adding a matrix workflow to test on Windows/macOS/Linux would catch platform-specific canvas rendering bugs before release.
- [ ] Update .github/workflows/build.yml to add a test matrix for Node.js 14/16/18 across ubuntu-latest, windows-latest, and macos-latest
- [ ] Ensure jest-canvas-mock is properly configured for each platform in the workflow
- [ ] Add a step to upload canvas rendering artifacts or logs on failure for debugging
Add integration tests for browser output formats (SVG and PNG)
The examples/ directory contains save-as-svg.js and save-as-png.js, but there are no tests validating that these examples actually work. The browser tests don't verify SVG/PNG generation. Adding integration tests would ensure the library correctly exports to different formats and that the examples in the repository actually function.
- [ ] Create src/integration.test.js or src/trianglify.integration.test.js to test SVG generation output validity
- [ ] Add a test that verifies generated SVG contains valid triangle path elements and styling
- [ ] Add a test for PNG export (if canvas context permits in test environment) or mock the PNG generation process
- [ ] Update the snapshot files (src/snapshots/) to include integration test expectations
🌿Good first issues
- Add TypeScript type definitions file (trianglify.d.ts) for better IDE support—the library has a simple API but currently lacks .d.ts exports in dist/
- Write integration test for examples/save-as-png.js and examples/save-as-svg.js Node.js workflows to verify file output—these files exist but no test coverage visible in snapshots
- Extend colorFunctions.js with new color palette strategies (e.g., random perlin noise blending, HSL saturation curves)—existing patterns are basic fixed/gradient/function types
⭐Top contributors
Click to expand
Top contributors
- @qrohlf — 82 commits
- @Saucistophe — 4 commits
- @TomEpsilon — 3 commits
- @arimgibson — 3 commits
- @dependabot[bot] — 2 commits
📝Recent commits
Click to expand
Recent commits
b959ccd— remove busted build status badge from readme (qrohlf)80aa64c— Merge pull request #152 from vikpe/patch-1 (qrohlf)a7593b5— Fix broken link to color functions in readme. (vikpe)ffa5d40— Merge pull request #147 from TomEpsilon/master (qrohlf)f345d1e— Update Readme.md (TomEpsilon)a29242b— Update Readme.md (TomEpsilon)d56e390— Update Readme.md (TomEpsilon)0d469f2— 4.1.1 (qrohlf)133ec6e— v4.1.0 (qrohlf)48b32ec— Merge pull request #135 from qrohlf/fix-destsvg (qrohlf)
🔒Security observations
The Trianglify codebase has a moderate security posture with primary concerns centered on outdated dependencies from 2020 that may contain unpatched vulnerabilities. The canvas and chroma-js dependencies require immediate updates. The CI/CD pipeline lacks automated security scanning (npm audit). No evidence of hardcoded secrets, injection vulnerabilities, or misconfigurations was found in the analyzed files. The project structure and code organization appear sound from a security perspective. Immediate actions: (1) update all dependencies, (2) add npm audit to CI/CD pipeline, (3) review and update build tools.
- High · Outdated Dependency: canvas@2.6.1 —
package.json - dependencies. The 'canvas' package version 2.6.1 is significantly outdated (released in 2020). This dependency may contain known security vulnerabilities. Current versions are much newer and include security patches. Fix: Update to the latest stable version of canvas. Run 'npm audit' to identify specific CVEs and update to canvas@latest or at least a recent 2.x version. - High · Outdated Dependency: chroma-js@2.1.0 —
package.json - dependencies. The 'chroma-js' package version 2.1.0 was released in 2020. Updating to the latest version ensures security patches and bug fixes are applied. Fix: Update chroma-js to the latest version. Run 'npm audit' to check for known vulnerabilities and update accordingly. - Medium · Outdated Dev Dependencies —
package.json - devDependencies. Multiple dev dependencies are significantly outdated (from 2020): @babel/preset-env@7.9.6, rollup@2.7.2, jest@25.5.4, standard@14.3.3, and babel-eslint@10.1.0. Outdated tooling can introduce security risks and lack security-relevant fixes. Fix: Update all dev dependencies to their latest stable versions. Run 'npm audit' and 'npm update' to remediate. Pay special attention to security tools like babel-eslint and standard. - Medium · No npm audit or Security Scanning in CI/CD —
.github/workflows/build.yml. The GitHub Actions workflow (build.yml) does not appear to include 'npm audit' or security scanning steps. This means vulnerable dependencies could be deployed without detection. Fix: Add 'npm audit --audit-level=moderate' to the CI pipeline before the build step. Consider integrating Dependabot or Snyk for automated vulnerability scanning. - Low · Missing package-lock.json Version Control Consideration —
package-lock.json. While package-lock.json is present, ensure it's always kept in sync with package.json to prevent dependency version mismatches across environments. Fix: Ensure package-lock.json is committed to version control and developers run 'npm ci' instead of 'npm install' during development to maintain consistency. - Low · GPL-3.0 License Compliance Risk —
LICENSE and package.json. The project is licensed under GPL-3.0, which has strict copyleft requirements. Users incorporating this library must comply with GPL-3.0 terms or face legal issues. Fix: Ensure clear documentation about GPL-3.0 requirements. Consider if a dual-licensing model would better serve your user base, or maintain explicit compliance documentation.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
🤖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:
- 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. - 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.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/qrohlf/trianglify 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.
✅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 qrohlf/trianglify
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/qrohlf/trianglify.
What it runs against: a local clone of qrohlf/trianglify — 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 qrohlf/trianglify | Confirms the artifact applies here, not a fork |
| 2 | License is still GPL-3.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | Last commit ≤ 394 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of qrohlf/trianglify. If you don't
# have one yet, run these first:
#
# git clone https://github.com/qrohlf/trianglify.git
# cd trianglify
#
# 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 qrohlf/trianglify and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "qrohlf/trianglify(\\.git)?\\b" \\
&& ok "origin remote is qrohlf/trianglify" \\
|| miss "origin remote is not qrohlf/trianglify (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(GPL-3\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"GPL-3\\.0\"" package.json 2>/dev/null) \\
&& ok "license is GPL-3.0" \\
|| miss "license drift — was GPL-3.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 394 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~364d)"
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/qrohlf/trianglify"
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).
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.
Embed this chat in your README →
Drop this iframe anywhere — the widget runs against the same live analysis cache as the main app.
<iframe src="https://repopilot.app/embed/qrohlf/trianglify" width="100%" height="500" style="border:1px solid #d0d7de; border-radius:8px;" allow="microphone" loading="lazy" ></iframe>