Discover developers through their skills, projects, technologies, companies, and professional connections.
DevGraph is a graph-powered developer discovery application built with CognoDB.
Users can search for developers using natural-looking queries such as:
Find Rust developers with PostgreSQL experience in fintech
The application resolves known skills, technologies, projects, companies, and domains from the graph, then uses parameterized Cypher queries to traverse the relationships and return matching developers.
Users can then open a developer profile and explore their projects, technologies, skills, domain experience, and connections to other developers.
The important questions in DevGraph are about relationships, not only individual records.
For example:
Developer
├── HAS_SKILL ──────────────> Skill
│
└── WORKED_ON ──────────────> Project
├── USES ──────────────> Technology
├── REQUIRES_SKILL ────> Skill
├── IN_DOMAIN ─────────> Domain
└── FOR_COMPANY ───────> Company
A question such as:
Find developers with Rust and PostgreSQL experience who worked on Fintech projects.
requires traversing multiple relationships.
A relational database can represent this data, but relationship-heavy questions become increasingly join-oriented as the number of relationships and traversal hops grows. In DevGraph, those relationships are first-class graph structures, so the query can follow the paths directly.
Another example is discovering developers who worked on the same project:
Developer
↓ WORKED_ON
Project
↑ WORKED_ON
Developer
This connection does not need a separate artificial CONNECTED_TO relationship. It can be derived by traversing the existing graph.
Search the developer network using natural-looking queries.
Results show matching developers together with the graph criteria used for the search.
A developer profile exposes connected skills, projects, technologies, required skills, domains, companies, and shared-project connections.
User
│
▼
React Search UI
│
│ POST /api/search
▼
Fastify Route
│
▼
Search Service
│
▼
Entity Resolver
│
│ Structured search filters
▼
Developer Repository
│
│ Parameterized Cypher
▼
Neo4j JavaScript Driver
│
│ Bolt
▼
CognoDB
│
▼
Developer Results
│
▼
React UI
The frontend sends the user's search text to the backend. The backend resolves known graph entities into structured filters, then executes fixed Cypher queries with parameters.
User input is never concatenated directly into Cypher.
Developer
Project
Skill
Technology
Company
Domain
Developer ──HAS_SKILL──────────────> Skill
Developer ──WORKED_ON──────────────> Project
Developer ──WORKS_AT───────────────> Company
Developer ──HAS_DOMAIN_EXPERIENCE──> Domain
Project ──USES─────────────────────> Technology
Project ──REQUIRES_SKILL───────────> Skill
Project ──IN_DOMAIN────────────────> Domain
Project ──FOR_COMPANY──────────────> Company
Developer
id
name
title
location
yearsExperience
Project
id
name
description
Skill
id
name
category
Technology
id
name
category
Company
id
name
industry
Domain
id
name
The main search can combine optional graph filters:
skills
technologies
domains
projects
companies
The query traverses:
Developer
├── HAS_SKILL ──> Skill
│
└── WORKED_ON ──> Project
├── USES ──────> Technology
├── IN_DOMAIN ─> Domain
└── FOR_COMPANY > Company
Example:
Developer
↓ WORKED_ON
Project
↓ IN_DOMAIN
Domain
This supports searches such as:
Rust developers with Fintech project experience.
Developer
↓ WORKED_ON
Project
↓ USES
Technology
For example:
Find developers with Axum experience.
Developer
↓ WORKED_ON
Project
↑ WORKED_ON
Developer
This allows the application to discover developers who worked on the same projects.
A developer's project can be explored through additional relationships:
Project
├── USES ──────────────> Technology
├── REQUIRES_SKILL ────> Skill
├── IN_DOMAIN ─────────> Domain
└── FOR_COMPANY ───────> Company
All user-derived values are passed separately as query parameters through the official Neo4j JavaScript driver.
Example:
MATCH (d:Developer)
OPTIONAL MATCH (d)-[:HAS_SKILL]->(skill:Skill)
OPTIONAL MATCH (d)-[:WORKED_ON]->(project:Project)
OPTIONAL MATCH (project)-[:USES]->(technology:Technology)
OPTIONAL MATCH (project)-[:IN_DOMAIN]->(domain:Domain)
OPTIONAL MATCH (project)-[:FOR_COMPANY]->(company:Company)
WITH
d,
collect(DISTINCT skill.name) AS developerSkills,
collect(DISTINCT project.name) AS projectNames,
collect(DISTINCT technology.name) AS technologyNames,
collect(DISTINCT domain.name) AS domainNames,
collect(DISTINCT company.name) AS companyNames
WHERE
(
size($skills) = 0
OR all(skill IN $skills WHERE skill IN developerSkills)
)
AND
(
size($technologies) = 0
OR all(technology IN $technologies WHERE technology IN technologyNames)
)
AND
(
size($domains) = 0
OR any(domain IN $domains WHERE domain IN domainNames)
)
AND
(
size($projects) = 0
OR any(project IN $projects WHERE project IN projectNames)
)
AND
(
size($companies) = 0
OR any(company IN $companies WHERE company IN companyNames)
)
RETURN
d.id AS id,
d.name AS name,
d.title AS title,
d.location AS location,
d.yearsExperience AS yearsExperienceParameters are supplied independently:
session.run(query, {
skills,
technologies,
domains,
projects,
companies,
});This keeps the Cypher structure separate from user data.
- React
- TypeScript
- Vite
- CSS
- Node.js
- TypeScript
- Fastify
- CognoDB
- openCypher
- Bolt
- Official Neo4j JavaScript driver
The backend follows a simple layered structure:
HTTP Route
↓
Service
↓
Repository
↓
Neo4j Driver
↓
CognoDB
Environment-specific settings are loaded from environment variables.
Database and API failures are caught by the backend and returned as user-safe responses. The frontend displays dedicated error states instead of exposing internal database errors.
- Routes handle HTTP concerns.
- Services coordinate application logic.
- Repositories own Cypher and database operations.
- Database layer owns the Neo4j driver connection.
- Configuration owns environment variables and startup validation.
devgraph/
├── docs/
│ ├── graph-model.png
│ └── screenshots/
│ ├── search.png
│ ├── results.png
│ └── developer-profile.png
│
├── backend/
│ ├── scripts/
│ │ ├── seed.ts
│ │ └── test-search.ts
│ │
│ ├── src/
│ │ ├── config/
│ │ │ └── env.ts
│ │ ├── db/
│ │ │ └── neo4j.ts
│ │ ├── repositories/
│ │ │ └── developer.repository.ts
│ │ ├── routes/
│ │ │ ├── search.ts
│ │ │ └── developers.ts
│ │ ├── services/
│ │ │ └── search.service.ts
│ │ ├── utils/
│ │ │ └── entity-resolver.ts
│ │ └── server.ts
│ │
│ ├── .env.example
│ ├── package.json
│ └── tsconfig.json
│
├── frontend/
│ ├── src/
│ │ ├── api/
│ │ ├── components/
│ │ ├── types/
│ │ ├── App.tsx
│ │ ├── App.css
│ │ └── index.css
│ └── package.json
│
└── README.md
POST /api/search
Content-Type: application/jsonExample request:
{
"query": "Find Rust developers with PostgreSQL experience in fintech"
}GET /api/developers/:idGET /api/developers/:id/connectionsGET /healthThe repository includes a reproducible seed script.
The dataset contains:
- Developers
- Skills
- Projects
- Technologies
- Companies
- Domains
- Relationships connecting those entities
Example:
Invoice SaaS
├── USES ──────────────> Axum
├── USES ──────────────> Tokio
├── REQUIRES_SKILL ────> Rust
├── REQUIRES_SKILL ────> PostgreSQL
├── IN_DOMAIN ─────────> Fintech
└── FOR_COMPANY ───────> Acme Technologies
Create a free CognoDB instance and save the generated Bolt URI and password.
CognoDB uses a Bolt endpoint and can be accessed with the official Neo4j drivers.
Create:
backend/.env
COGNODB_URI=bolt+s://<instance-id>.databases.cognodb.cloud
COGNODB_USERNAME=cognodb
COGNODB_PASSWORD=<your-password>
PORT=3000Do not commit .env.
The repository contains:
backend/.env.example
as a template.
cd backend
npm install
npm run seed
npm run devBackend:
http://localhost:3000
cd frontend
npm install
npm run devOpen the Vite URL shown in the terminal.
The application includes:
Searching the developer network...
Exploring developer connections...
No developers found.
No shared-project connections found.
Unable to search the developer network.
Unable to load developer details.


