Migrating from CrinGraph
This page is for operators moving an existing CrinGraph database — or any of its popular derivatives — to modernGraphTool v2.
The good news: the core data (FR .txt files, phone_book.json, target files) is format-compatible and carries over without modification. The work is mostly in restructuring the data/ folder, regenerating the config in v2's format, and re-applying page metadata.
For a feature-level overview of what v2 brings to the table, see What's New in v2 — especially useful if you're deciding whether to migrate at all.
Which fork are you coming from?
CrinGraph has a long history and several actively maintained forks. The migration steps are largely the same, but each fork has structural quirks worth naming up front.
| Vanilla CrinGraph | squiglink lab | PublicGraphTool | |
|---|---|---|---|
| Config file | config.js (root) | config.js (root), config_hp.js for HP variant | assets/js/config.js |
| Phone FR files | data/*.txt (flat) | data/*.txt (flat) | data/*.txt (flat) |
| Target files | data/*.txt (mixed with phones) | data/*.txt (mixed with phones) | Split: some in data/*Target.txt, more in data/targets/ |
phone_book.json | Optional (often absent) | data/phone_book.json | data/phone_book.json |
| Preference bounds | None | None | assets/pref_bounds/Bounds L.txt + Bounds R.txt |
| Theme CSS | style*.css at root | style*.css + styles/dark.css + styles/white.css | assets/css/extra.css + style*.css |
| Headphones variant | Usually a separate install | data_hp/ folder + config_hp.js | data_hp/ folder + headphones.html + config_hp.js |
| External scripts | None | None | squigsites.js, reinvented-color-wheel.min.js, 90inclusion.js, audio tags |
If your fork isn't listed here, it almost certainly behaves like one of these three. The steps below call out fork-specific differences inline as Lab, PublicGraphTool, and Vanilla notes.
Compatibility
Format-compatible, carries over unchanged:
- FR measurement
.txtfiles (tab/space-separatedfreq dBcolumns) - Target
.txtfiles (same format) phone_book.jsonschema (see Managing Data if you need to create one)- Watermark images, logos, favicon images
Not compatible, needs regeneration:
config.js— CrinGraph uses top-levelconstbindings (const init_phones = [...], DIR = "data/"); v2 uses a single structuredCONFIG = { ... }object. The fields are mostly equivalent but the format is entirely different.- Theme/stylesheet CSS — CrinGraph's styles are scattered across multiple files with hard-coded hex values; v2 uses a single
theme.csswith CSS custom properties (OKLCH-based). - Folder layout — CrinGraph keeps phones and targets mixed in a single
data/folder; v2 expects them split intodata/phones/anddata/target/.
Does not carry over at all:
- CrinGraph's JS files (
graphtool.js,equalizer.js,listAugment.js,saveSvgAsPng.js,graphAnalytics.js) - Bundled libraries (
d3.v5.min.js,fuse.min.js,reinvented-color-wheel.min.js) - External scripts pulled from
squig.link/squigsites.js— v2 has native squig.link integration via theSQUIGLINKconfig section. Remove the script tag.
Migration Steps
-
Download the latest modernGraphTool v2 release and extract it.
-
Restructure your
data/folder. v2 expects phones and targets in separate subfolders:data/├── phones/ # all your phone FR .txt files│ ├── IEM A L.txt│ ├── IEM A R.txt│ └── ...├── target/ # all your target curve .txt files│ ├── Harman IE 2019v2 Target.txt│ └── ...└── phone_book.json # unchangedMove every non-target FR file into
data/phones/, and every target file intodata/target/. Targets are usually easy to identify — they end inTarget.txt, or they appear by name in thetargetsarray of your old CrinGraph config.- Lab note: All files in your old flat
data/folder need to be sorted. Thedata/phone_book.jsonmoves as-is. - PublicGraphTool note: You have a partial split already —
data/targets/contains many of your target files. Mergedata/targets/*.txtand anydata/*Target.txtfiles at the root ofdata/into v2'sdata/target/. Everything else goes intodata/phones/. - Vanilla CrinGraph note: If you don't already have a
phone_book.json, you'll need to create one. See Managing Data for the schema and a minimal example.
- Lab note: All files in your old flat
-
Move Preference Bound files (PublicGraphTool only) — v2 expects bound data files at
data/Bounds U.txtanddata/Bounds D.txt(upper/lower). PublicGraphTool stored them atassets/pref_bounds/Bounds L.txtandBounds R.txt(left/right). Copy them over and rename:assets/pref_bounds/Bounds L.txt→data/Bounds U.txtassets/pref_bounds/Bounds R.txt→data/Bounds D.txt
Also make sure your compensation baseline (usually a KEMAR DF or similar) is present in
data/target/, and record its filename (without extension) — you'll setPREFERENCE_BOUND.BASE_DF_TARGET_FILEto it in the next step. -
Generate a new
config.js— CrinGraph's config format is incompatible with v2, so the cleanest approach is to build a fresh one using the Config Editor, referencing your old config for the values. A few common field mappings to speed you along:CrinGraph (old) modernGraphTool v2 (new) init_phones = [...]INITIAL_PHONES: [...]targets = [{ type, files }]TARGET_MANIFEST: [{ type, files }]DIR = "data/"PATH.PHONE_MEASUREMENT,PATH.TARGET_MEASUREMENT,PATH.PHONE_BOOKdefault_normalization = "Hz" / "dB"NORMALIZATION.TYPE("Hz"or"Avg")default_norm_hz = 500NORMALIZATION.HZ_VALUE: 500default_y_scale = "40db"VISUALIZATION.DEFAULT_Y_SCALE: 40watermark_text,watermark_image_urlWATERMARK: [{ TYPE, CONTENT, ... }]rig_descriptionVISUALIZATION.RIG_DESCRIPTIONlabelsPosition = "bottom-left"VISUALIZATION.LABEL.LOCATION: "BOTTOM_LEFT"headerLinks = [...]TOPBAR.LINK_LIST: [...]page_title,page_descriptionSet in index.html<title>/<meta>(step 6)themingEnabled,alt_layout,alt_*flagsNot needed — v2's theme and layout are always on extraEQBands,extraEQpluginsNot needed — v2 has built-in Interactive EQ and Device PEQ preference_bounds_dir,preference_bounds_namePREFERENCE_BOUND.BASE_DF_TARGET_FILE+ file location indata/tiltableTargets,compTargetsTARGET_CUSTOMIZER.CUSTOMIZABLE_TARGETSdefault_tilt,default_bass_shelf,default_ear,default_trebleTARGET_CUSTOMIZER.INITIAL_TARGET_FILTERSallowSquigDownload,analyticsEnabledSQUIGLINK.ENABLE_*fieldsdefault_DF_nameUsed as the name in PREFERENCE_BOUND.BASE_DF_TARGET_FILEFor the field-by-field reference of every v2 option, see Customizing the Page →
config.js. -
Generate a new
theme.css— use the Theme Generator to build a v2-compatible theme visually. You can eyeball the colors from your old stylesheets:- Lab: start from
styles/dark.css/styles/white.cssfor the dark/light palettes andstyle-alt-theme.cssfor accent colors. - PublicGraphTool:
assets/css/extra.cssholds most of the custom CSS variables (look for--accent-color-contrast,--background-color);dark.css/theme-*.csshold the rest. - Vanilla:
style.cssandstyle-alt.css.
Drop the generated
theme.cssalongside your newindex.htmlandconfig.js. - Lab: start from
-
Migrate page metadata (
index.html) — v2 ships with its ownindex.html; the edits you made to your CrinGraphindex.htmldo not carry over automatically. Re-apply them:<title>and<meta name="title">(CrinGraphpage_title)<meta name="description">(CrinGraphpage_description)- Open Graph tags:
<meta property="og:title">,<meta property="og:description">,<meta property="og:url">,<meta property="og:image"> <link rel="canonical">- Favicons:
<link rel="icon">,<link rel="shortcut icon">,<link rel="apple-touch-icon">— repoint these to your own image files (copy them intoassets/images/first) <meta name="apple-mobile-web-app-title">- Web app manifest:
<link rel="manifest">(if you have one)
The Customizing the Page → Changing Page Metadata section has the full field-by-field reference.
Things that should NOT be carried over from your CrinGraph
index.html:<script src="https://squig.link/squigsites.js"></script>— v2 has native squig.link integration. Enable it via theSQUIGLINKsection inconfig.jsinstead. Cross-site search, sponsor banner, and multi-GA4 analytics are all built in.<script src="assets/js/graphAnalytics.js"></script>— v2 analytics are routed throughSQUIGLINK.ANALYTICS_MEASUREMENT_IDS(an array, so multi-tag support works out of the box).<script src="assets/js/reinvented-color-wheel.min.js"></script>+reinvented-color-wheel.min.css— v2 has a built-in color picker on every curve's color swatch.<audio id="pinkNoiseAudio">/<audio id="scarletFIRE">tags — not a v2 feature.<script src="assets/js/90inclusion.js"></script>— PublicGraphTool-specific; not applicable to v2.- Google Fonts
<link>tags for Open Sans / Source Sans Pro — v2 ships with the Pretendard Variable font by default. Keep them only if you're intentionally replacing the font stack.
Source buildersIf you build from source, edit
src/app.htmlinstead ofindex.html. The outputdist/index.htmlis generated from that template. -
Delete CrinGraph-specific files — once steps 1–6 are complete, your old CrinGraph files are no longer needed in the v2 folder. Safe to remove:
graphtool.js,equalizer.js,listAugment.js,saveSvgAsPng.js,graphAnalytics.jsd3.v5.min.js,d3-selection-multi.v1.min.js,fuse.min.js,reinvented-color-wheel.min.jsstyle.css,style-alt.css,style-alt-theme.css,styles/(folder),extra.css, any CrinGraph-specific theme CSScringraph-favicon.png,cringraph-icon*.png,cringraph-logo.svg(keep your own branding images)90inclusion.js, audio asset files if they were only used by the old<audio>tagsdevicePEQ/plugin folder — v2 has built-in Device PEQ- Old
config.js,config_hp.js,headphones.html,graph_*.html,iframe.html
Keep your
data/folder, your newconfig.js, your newtheme.css, your favicon/watermark images, and v2's own files. -
Test locally and deploy.
headphones.html in v2PublicGraphTool ships a dual-instance layout with headphones.html + data_hp/ + config_hp.js, and squiglink lab has a similar config_hp.js + data_hp/ pattern. modernGraphTool v2 intentionally does not reproduce this.
The squig.link service model hosts earphone and headphone databases as separate sibling directories on the same (sub)domain — e.g. username.squig.link/ for earphones and username.squig.link/headphones/ for headphones — each one a standalone deployment with its own data/, config.js, and theme.css. This keeps each instance single-purpose and simpler to reason about, and it's how squig.link service expects deployments to be structured for features like cross-instance search and unified analytics.
If you're migrating from a dual-instance CrinGraph setup, treat it as two separate migrations: one earphone deployment and one headphone deployment, each following the steps on this page independently. For the headphone instance in a subdirectory, see the BASE_PATH note below.
Picking a Deployment Option
modernGraphTool v2 offers three deployment paths:
- Pre-built Release — Closest to how you deploy CrinGraph today. Download the release, drop your
data/,config.js, andtheme.cssin, upload. NoBASE_PATHto worry about. - CDN Deployment — Recommended, and a thinner drop: only your
index.html,config.js,theme.css,data/, andassets/live on your server; the app bundle loads from jsDelivr and auto-updates with new v2 releases. - Building from Source — For developers and forks.
Instead of hosting the full pre-built release, consider the CDN deployment mode. You don't need to manage the app code, and future updates apply automatically with it.
If you pick CDN mode, watch out for BASE_PATH
In v2 CDN mode, any deployment not at the root of its (sub)domain requires CDN_MODE.BASE_PATH in config.js. Without it, the home page loads fine but every share link 404s. The fix is one config line. For a site at example.com/headphones/:
CDN_MODE: {
MAJOR_VERSION: 2,
BASE_PATH: "/headphones",
},
Full explanation and worked examples: Why BASE_PATH is almost always required.
This matters most for the headphone sibling deployment mentioned above — your earphone instance at the subdomain root doesn't need BASE_PATH, but the headphone instance at /headphones/ does.
Already running CrinGraph alongside another tool?
If you want to keep CrinGraph as the primary front page and run modernGraphTool in a subfolder (or vice versa), the Dual-hosting guide walks through that layout end-to-end — including how to share a single data/ folder between both tools.