You hire a developer as "Senior". Three months later you discover they can't do code reviews or mentor juniors. In the interview they said they had 6 years of experience, and technically that was true. But experience is not the same as level. A developer can spend 6 years writing the same CRUD code without developing architecture, technical leadership, or system design competencies.
The problem is that "Senior" means nothing concrete. For a 5-person startup, senior is whoever has been there more than 2 years. For a BigTech, senior starts at 5-7 years with a specific catalog of demonstrated competencies. When you post a "Senior Backend Developer" job, each candidate interprets something different. When you do a salary review, you have no objective criteria to justify promotions.
The HR department usually manages an Excel table with generic titles: Junior, Mid, Senior, Lead. No definition of what competencies correspond to each level. No criteria to evaluate if someone is ready for promotion. No clear path that the employee themselves can follow to grow.
This generates frustration on both sides. The employee doesn't know what they need to learn to level up. The manager has no objective arguments to defend a promotion to leadership. HR can't compare roles between departments because each team uses different criteria.
Why I created this package
At SPARRING we needed to evaluate technical candidates objectively. The platform generates automated interviews, but to evaluate responses you need to know what competencies to expect from a Backend Developer L3 versus an L5. You can't ask the same questions to a junior as to a senior.
I looked for existing technical level frameworks. I found Rent the Runway's Engineering Ladder published on GitHub, Dropbox levels leaked on Levels.fyi, Spotify's framework circulating on LinkedIn. All useful as inspiration, but none structured as a consumable code library. They were PDF documents or web pages, not APIs.
The alternative was manually creating JSON with the roles I needed. The problem is maintenance. When you add a new role, you have to define 9 levels with their competencies. When you modify the data structure, you have to update all files. Without automatic validation, inconsistencies easily slip through.
I decided to build a complete library that would serve as a single source of truth for technical roles. 78 roles organized in 7 categories. 9 levels per role, from L1 (Trainee) to L9 (VP/CTO). Each level with core competencies, complementary competencies, performance indicators, and typical years of experience range. Bilingual support because we operate in both Spanish and English-speaking markets.
The result is @sparring/tech-roles-library: 702 unique role-level definitions with complete API for search, filtering, career path analysis, and level comparison.
Installation and basic structure
npm install @sparring/tech-roles-library
The library exports a main class that you initialize with the desired language:
const TechRolesLibrary = require('@sparring/tech-roles-library');
// English by default
const library = new TechRolesLibrary();
// Spanish
const libraryES = new TechRolesLibrary({ language: 'es' });
The language affects all text: role names, level names, competencies, indicators. A "Backend Developer" in English is "Desarrollador Backend" in Spanish. Competencies are professionally translated, not Google Translated.
The data structure for each role-level entry includes:
{
category: 'Software Engineering',
role: 'Backend Developer',
level: 'L5 - Mid-level II',
code: 'BE-L5',
levelNumber: 5,
yearsRange: { min: 5, max: 7 },
coreCompetencies: [
'Scalable RESTful API design',
'Complex SQL query optimization',
'Microservices pattern implementation',
// ... more competencies
],
complementaryCompetencies: [
'Knowledge of messaging systems',
'Experience with containers',
// ... more competencies
],
indicators: [
'Leads medium-high complexity features',
'Mentors junior developers',
'Actively participates in architecture decisions'
]
}
The code (BE-L5) is a unique identifier combining role abbreviation and level number. It's useful for quick references in databases or URLs.
Basic access to roles and levels
Get the list of all available roles:
const roles = library.getRoles();
console.log(`Total roles: ${roles.length}`); // 78
// Shows: ['AI Engineer', 'Backend Developer', 'Data Analyst', ...]
Get a specific role-level by its code:
const role = library.getRole('BE-L5');
console.log(role.role); // 'Backend Developer'
console.log(role.level); // 'L5 - Mid-level II'
console.log(role.yearsRange); // { min: 5, max: 7 }
Get all levels for a specific role:
const backendLevels = library.getLevelsForRole('Backend Developer');
backendLevels.forEach(entry => {
console.log(`${entry.code}: ${entry.level} (${entry.yearsRange.min}-${entry.yearsRange.max || '15+'} years)`);
});
// Output:
// BE-L1: L1 - Trainee (0-1 years)
// BE-L2: L2 - Junior I (1-2 years)
// BE-L3: L3 - Junior II (2-3 years)
// BE-L4: L4 - Mid-level I (3-5 years)
// BE-L5: L5 - Mid-level II (5-7 years)
// BE-L6: L6 - Senior I (7-10 years)
// BE-L7: L7 - Senior II (10-12 years)
// BE-L8: L8 - Staff/Principal (12-15 years)
// BE-L9: L9 - VP/CTO (15+ years)
Role categories
The 78 roles are organized into 7 categories that reflect typical tech team structures:
| Category | Roles | Description |
|---|---|---|
| Software Engineering | 33 | Full-stack, backend, frontend, mobile, QA |
| AI/ML | 16 | Machine learning, data science, MLOps |
| Data | 15 | Data engineering, analytics, BI |
| Product | 7 | Product management, ownership, analysis |
| Security | 4 | Security engineering, DevSecOps |
| Infrastructure | 2 | Platform, SRE, cloud |
| Sales | 1 | Technical sales, solutions engineering |
Filter roles by category:
const categories = library.getCategories();
console.log(categories);
// ['AI/ML', 'Data', 'Infrastructure', 'Product', 'Sales', 'Security', 'Software Engineering']
const aiRoles = library.filterByCategory('AI/ML');
console.log(`AI/ML roles: ${aiRoles.length / 9}`); // 16 roles × 9 levels = 144 entries
Filter all roles at a specific level:
const allSeniors = library.filterByLevel('L6');
console.log(`Senior I roles: ${allSeniors.length}`); // 78 (one per role)
Role search
When building a role selector in a UI, you need text search. The search() method finds roles by name or category:
const results = library.search('fullstack', { limit: 5 });
results.forEach(result => {
console.log(`${result.role} (${result.category}) - Score: ${result.matchScore}`);
});
// Output:
// Full-Stack Developer (Software Engineering) - Score: 10
// Full-Stack Engineer (Software Engineering) - Score: 10
The matchScore indicates relevance: 10 points if it matches role name, 5 points if it matches category. Results are sorted by descending score.
// Search by category
const dataResults = library.search('data');
// Finds: Data Analyst, Data Engineer, Data Scientist, etc.
// Also finds roles in "Data" category
Career path analysis
This is the most powerful functionality for career planning. Given a role and current level, you can get the complete career path view.
What you need to level up
const nextLevel = library.getNextLevel('Backend Developer', 'L5');
console.log(`Current level: ${nextLevel.current.level}`);
console.log(`Next level: ${nextLevel.next.level}`);
console.log(`Typical years: ${nextLevel.next.yearsRange.min}-${nextLevel.next.yearsRange.max}`);
console.log(`New competencies to develop: ${nextLevel.newCompetenciesCount}`);
nextLevel.newCompetencies.forEach(comp => {
console.log(` - ${comp}`);
});
// Output:
// Current level: L5 - Mid-level II
// Next level: L6 - Senior I
// Typical years: 7-10
// New competencies to develop: 8
// - Technical leadership of small teams
// - Code standards definition
// - Technology evaluation and selection
// - ...
This answers the question every developer has: "what do I need to learn to get promoted?"
Complete career path view
const career = library.getCareerPathComplete('Backend Developer', 'L5');
console.log('=== Mastered levels ===');
career.masteredLevels.forEach(level => {
console.log(`${level.code}: ${level.coreCompetencies.length} competencies`);
});
console.log('\n=== Current level ===');
console.log(`${career.currentLevel.code}: ${career.currentLevel.level}`);
console.log('\n=== Growth path ===');
career.growthPath.forEach(level => {
console.log(`${level.code}: ${level.level}`);
});
console.log('\n=== Summary ===');
console.log(`Mastered competencies: ${career.summary.totalMasteredCompetencies}`);
console.log(`Current level competencies: ${career.summary.currentLevelCompetencies}`);
console.log(`Remaining to learn: ${career.summary.remainingToLearn}`);
console.log(`Progress: ${career.summary.progressPercentage}%`);
This view is useful for:
- Employees: See where they are and what's missing
- Managers: Plan team development
- HR: Design training plans based on real gaps
Accumulated competencies
Competencies are cumulative. An L5 should master everything from L1-L4 plus L5 specifics:
const accumulated = library.getAccumulatedCompetencies('Backend Developer', 'L5');
accumulated.levels.forEach(level => {
console.log(`\n${level.level}:`);
level.coreCompetencies.forEach(comp => {
console.log(` ✓ ${comp}`);
});
});
This generates the complete catalog of competencies someone at that level should demonstrate.
Find level by years of experience
If you only know someone's years of experience, you can estimate their level:
const level = library.getByExperience('Backend Developer', 6);
console.log(level.level); // 'L5 - Mid-level II'
console.log(level.yearsRange); // { min: 5, max: 7 }
This is an estimate based on typical ranges. 6 years of experience falls in L5 range (5-7 years). But remember: years don't equal level. A developer with 6 years doing the same thing might be at L3 by actual competencies.
Catalog statistics
For dashboards or reports:
const stats = library.getStatistics();
console.log(`Total roles: ${stats.totalRoles}`); // 78
console.log(`Total entries: ${stats.totalEntries}`); // 702
console.log(`Categories: ${stats.totalCategories}`); // 7
console.log('By category:', stats.byCategory);
// { 'Software Engineering': 297, 'AI/ML': 144, 'Data': 135, ... }
Complete catalog with metadata:
const catalog = library.getAllRolesWithMetadata();
catalog.roles.forEach(roleInfo => {
console.log(`${roleInfo.role} (${roleInfo.category})`);
console.log(` Levels: ${roleInfo.levelCount}`);
console.log(` Total competencies: ${roleInfo.statistics.totalCompetencies}`);
});
Bilingual support
All translations are professional with correct technical terminology. No language mixing or literal translations that make no sense in tech context.
const libEN = new TechRolesLibrary({ language: 'en' });
const libES = new TechRolesLibrary({ language: 'es' });
const roleEN = libEN.getRole('BE-L5');
const roleES = libES.getRole('BE-L5');
console.log(roleEN.role); // 'Backend Developer'
console.log(roleES.role); // 'Desarrollador Backend'
console.log(roleEN.level); // 'L5 - Mid-level II'
console.log(roleES.level); // 'L5 - Mid-level II'
// Competencies are also translated
console.log(roleEN.coreCompetencies[0]); // 'Scalable RESTful API design'
console.log(roleES.coreCompetencies[0]); // 'Diseño de APIs RESTful escalables'
Spanish uses neutral Spanish without regionalisms. "Desarrollador" instead of "Programador". "Competencias" instead of "Habilidades". Terminology that works equally in Spain, Mexico, Argentina, or Colombia.
The 9 levels explained
The framework uses 9 standardized levels that map to typical tech company structures:
| Level | Name | Typical Years | Description |
|---|---|---|---|
| L1 | Trainee | 0-1 | Fresh graduate, in training |
| L2 | Junior I | 1-2 | Executes defined tasks with supervision |
| L3 | Junior II | 2-3 | Autonomy on low complexity tasks |
| L4 | Mid-level I | 3-5 | Full autonomy on medium features |
| L5 | Mid-level II | 5-7 | Leads features, starts mentoring |
| L6 | Senior I | 7-10 | Technical leadership, architecture decisions |
| L7 | Senior II | 10-12 | Team's technical reference |
| L8 | Staff/Principal | 12-15 | Cross-team impact, defines standards |
| L9 | VP/CTO | 15+ | Strategic leadership, technical vision |
Years are indicative. An exceptional developer can reach L6 in 5 years. One who stagnates can remain at L4 with 10 years of experience. What matters is demonstrated competencies, not the calendar.
Real use cases
Candidate evaluation system
// Candidate claims Senior level (L6)
const expectedCompetencies = library.getCompetencies('Backend Developer', 'L6');
// Compare with competencies demonstrated in interview
const demonstrated = evaluateInterview(candidate);
const gaps = expectedCompetencies.core.filter(
comp => !demonstrated.includes(comp)
);
if (gaps.length > 3) {
console.log('Candidate does not meet L6 level, gaps:', gaps);
// Suggest L5 or L4 based on gaps
}
Individual development plan
const employee = { role: 'Frontend Developer', currentLevel: 'L4' };
const nextLevel = library.getNextLevel(employee.role, employee.currentLevel);
// Generate development plan
const developmentPlan = {
currentLevel: employee.currentLevel,
targetLevel: nextLevel.next.level,
timeframe: `${nextLevel.next.yearsRange.min - 3} - ${nextLevel.next.yearsRange.max - 3} years`,
competenciesToDevelop: nextLevel.newCompetencies,
suggestedTraining: mapCompetenciesToCourses(nextLevel.newCompetencies)
};
Salary comparison by level
// Your salary database by level
const salaryBands = {
'L4': { min: 35000, max: 45000 },
'L5': { min: 45000, max: 55000 },
'L6': { min: 55000, max: 70000 }
};
// Employee requests raise
const employee = library.getRole('FE-L5');
const band = salaryBands['L5'];
console.log(`Salary band for ${employee.level}: €${band.min} - €${band.max}`);
Technical org charts
const team = [
{ name: 'Ana', roleCode: 'BE-L6' },
{ name: 'Carlos', roleCode: 'BE-L4' },
{ name: 'María', roleCode: 'FE-L5' },
{ name: 'Pedro', roleCode: 'BE-L3' }
];
team.forEach(member => {
const role = library.getRole(member.roleCode);
console.log(`${member.name}: ${role.role} ${role.level}`);
});
// Ana: Backend Developer L6 - Senior I
// Carlos: Backend Developer L4 - Mid-level I
// María: Frontend Developer L5 - Mid-level II
// Pedro: Backend Developer L3 - Junior II
Validation and data quality
The library passed 99 tests before publication:
- Structural integrity: All valid JSON, no missing fields
- Level consistency: Each role has exactly 9 levels L1-L9
- Translation validation: 0% contamination between languages (no English words in ES files or vice versa)
- Coherent year ranges: L1 < L2 < L3... without overlaps
- Unique codes: No duplicates in the 702 role-level codes
Each release runs complete validation. If you add a new role via PR, tests verify it has correct structure, 9 levels, complete translations, and codes following existing pattern.
TypeScript: complete types
The package includes TypeScript definitions. No additional @types/ needed:
import TechRolesLibrary from '@sparring/tech-roles-library';
import type { RoleEntry, CareerPath, SearchResult } from '@sparring/tech-roles-library';
const library = new TechRolesLibrary({ language: 'es' });
// TypeScript knows return types
const role: RoleEntry = library.getRole('BE-L5');
const career: CareerPath = library.getCareerPathComplete('Backend Developer', 'L5');
const results: SearchResult[] = library.search('frontend');
Types are complete: RoleEntry, CareerPath, SearchResult, LibraryStatistics, configuration options. VS Code autocompletion works perfectly.
Zero dependencies
The package has no runtime dependencies. package.json only lists devDependencies for testing and build. This means:
- Minimal bundle size
- No version conflicts with other libraries
- No inherited vulnerabilities from dependencies
- Works in any Node.js 16+ environment
Translation files are loaded with lazy loading. If you use the package in Spanish, English files don't load until you switch languages.
Interactive demo
You can explore the complete catalog in the web demo:
https://686f6c61.github.io/npm-tech-roles-library/demo/
The demo allows:
- Browse roles by category
- View all 9 levels for each role
- Explore competencies for each level
- Switch between English and Spanish
Source code is on GitHub: github.com/686f6c61/npm-tech-roles-library
Package published on NPM: @sparring/tech-roles-library
Contributions welcome to add missing roles, improve translations, or correct competencies that don't reflect current market reality.