I Built a Free Cypher Query Formatter for Neo4j — Here's Why and How
If you've worked with Neo4j for any length of time, you've probably stared at a wall of unformatted Cypher that looks something like this:
MATCH (p:Person {name: 'Alice'})-[:FRIENDS_WITH]->(friend:Person)-[:WORKS_AT]->(c:Company) WHERE friend.age > 25 AND c.name STARTS WITH 'Neo' WITH p, friend, c, count(*) AS cnt ORDER BY cnt DESC LIMIT 10 OPTIONAL MATCH (friend)-[:LIVES_IN]->(city:City) WHERE city.population > 100000 RETURN p.name AS person, collect(DISTINCT friend.name) AS friends, c.name AS company, city.name AS city ORDER BY person ASC
Not exactly readable. I kept copy-pasting queries from logs, Slack messages, and Stack Overflow answers that looked like this — and manually reformatting them was eating into my time. So I built a tool to fix it.
What I Built
Cypher Query Formatter — a free, browser-based tool that takes a messy Cypher query and formats it instantly with proper indentation, line breaks, and syntax highlighting.
The same query from above becomes:
MATCH (p:Person {name: 'Alice'})-[:FRIENDS_WITH]->(friend:Person)-[:WORKS_AT]->(c:Company)
WHERE friend.age > 25
AND c.name STARTS WITH 'Neo'
WITH p, friend, c, count(*) AS cnt
ORDER BY cnt DESC
LIMIT 10
OPTIONAL MATCH (friend)-[:LIVES_IN]->(city:City)
WHERE city.population > 100000
RETURN p.name AS person,
collect(DISTINCT friend.name) AS friends,
c.name AS company,
city.name AS city
ORDER BY person ASC
Much better.
Features
-
Instant formatting — paste your query, click Format (or hit
Ctrl+Enter) - Syntax highlighting — keywords, functions, labels, properties, strings and parameters all highlighted in distinct colors
- Configurable indent — 2 spaces, 4 spaces, or tabs
- Keyword case conversion — UPPERCASE, lowercase, or Capitalize
- Dark and light theme
-
Copy to clipboard or download as
.cypherfile - 100% client-side — your queries are never sent to any server
How It Works — The Technical Side
This was a fun vanilla JS project. Here's the approach I took:
Tokenizer
The core is a hand-written tokenizer that walks the query character by character and emits typed tokens: clause, sub_clause, function, string, number, comment, parameter, operator, bracket, etc.
The tricky part was handling multi-word clauses correctly. Cypher has things like OPTIONAL MATCH, ON CREATE SET, ORDER BY, STARTS WITH, and IS NOT NULL. A naive word-by-word approach would break STARTS WITH into the operator STARTS and the major clause WITH — which is wrong.
The solution was to match multi-word sub-clauses before checking major clauses, using a longest-match-first sorted list:
const MULTI_WORD_SUB_CLAUSES_SORTED = [
'IS NOT NULL',
'STARTS WITH',
'ENDS WITH',
'WITH HEADERS',
'IS NULL'
];
By checking these first, STARTS WITH is correctly identified as a sub-clause operator before WITH can be matched as a major clause.
Formatter
After tokenization and classification, the formatter rebuilds the query string with:
- A newline before each major clause (
MATCH,WHERE,RETURN, etc.) - An indent + newline before
AND,OR,XORinsideWHEREblocks - An indent + newline after commas in
RETURN,WITH, andSETclauses - Proper spacing around operators and brackets
Syntax Highlighter
The highlighter runs the same tokenizer on the already formatted output and wraps each token type in a <span> with a CSS class. Context matters here — an identifier after a : is a label (red), after a . is a property (blue), otherwise it's a variable (pink).
What I Learned
Writing a tokenizer from scratch is surprisingly fun. The edge cases are where it gets interesting — escaped quotes inside strings, backtick-escaped identifiers, block comments, parameters starting with $.
Multi-word keyword matching needs careful ordering. This tripped me up early on and produced some very wrong formatting before I got it right.
Cloudflare Pages is a great free host for static tools like this. Zero config, instant deploys from git, generous free tier.
Try It
It's free, open to everyone, and works in any modern browser. If you hit a query, it formats incorrectly. I'd genuinely love to hear about it in the comments. Edge cases in Cypher are plentiful, and I'm sure I've missed some.
Built with vanilla JavaScript. No frameworks, no dependencies, no server.
Top comments (0)