What this app does, why it exists, and how it's built.
SkillGraph was built for Wexa AI's CognoDB take-home assignment: build a small, complete application backed by a graph database, using CognoDB (a managed graph database speaking openCypher over the Bolt protocol) as the data layer.
The brief left the use case entirely open, with the evaluation focused on data modeling judgment, engineering architecture, and UI/UX polish rather than any specific feature list.
Developers typically have several skills, and jobs typically require several skills — the relationship between the two is naturally many-to-many, and it doesn't stop there: jobs belong to companies, companies post many jobs, and jobs and developers both relate to locations.
SkillGraph represents all of that as a graph and lets a developer:
The primary matching query walks a 3-hop pattern: Developer -[HAS_SKILL]-> Skill <-[REQUIRES]- Job <-[POSTS]- Company. In Cypher that's one pattern match. In SQL it's four tables, three join conditions, and a GROUP BY to get the matching-skill count back out.
The skill explorer's co-occurrence query (which other skills tend to appear alongside a given skill) is a self-join of a junction table against itself in SQL — in Cypher it's the same one-line pattern, and each additional hop is just one more relationship segment.
"Similar jobs" (jobs sharing required skills) is the same story: a job-to-job similarity signal that only exists because two jobs point at the same skill nodes. The graph makes that connection a first-class thing you can pattern-match on.
In short: the relationships are the product here, not incidental foreign keys. The UI's "why does this job match" explanation, the graph explorer, and the skill explorer are all direct renderings of graph traversals — there's no translation layer between how the data is stored and how the feature is explained.
(:Developer)-[:HAS_SKILL]->(:Skill) (:Job)-[:REQUIRES]->(:Skill) (:Company)-[:POSTS]->(:Job) (:Job)-[:LOCATED_IN]->(:Location) (:Developer)-[:PREFERS]->(:Location)