Contratas a un desarrollador como "Senior". Tres meses después descubres que no sabe hacer code reviews ni mentorizar juniors. En la entrevista dijo que tenía 6 años de experiencia, y técnicamente era cierto. Pero experiencia no es lo mismo que nivel. Un desarrollador puede pasar 6 años escribiendo el mismo código CRUD sin desarrollar competencias de arquitectura, liderazgo técnico o diseño de sistemas.
El problema es que "Senior" no significa nada concreto. Para una startup de 5 personas, senior es quien lleva más de 2 años. Para una BigTech, senior empieza a los 5-7 años con un catálogo específico de competencias demostradas. Cuando publicas una oferta de "Senior Backend Developer", cada candidato interpreta algo diferente. Cuando haces una revisión salarial, no tienes criterios objetivos para justificar promociones.
El departamento de HR suele manejar una tabla Excel con títulos genéricos: Junior, Mid, Senior, Lead. Sin definición de qué competencias corresponden a cada nivel. Sin criterios para evaluar si alguien está listo para promocionar. Sin itinerario claro que el propio empleado pueda seguir para crecer.
Esto genera frustración en ambos lados. El empleado no sabe qué necesita aprender para subir de nivel. El manager no tiene argumentos objetivos para defender una promoción ante dirección. HR no puede comparar roles entre departamentos porque cada equipo usa criterios diferentes.
Por qué creé este paquete
En SPARRING necesitábamos evaluar candidatos técnicos de forma objetiva. La plataforma genera entrevistas automatizadas, pero para evaluar respuestas necesitas saber qué competencias esperar de un Backend Developer L3 versus un L5. No puedes preguntar lo mismo a un junior que a un senior.
Busqué frameworks de niveles técnicos existentes. Encontré el Engineering Ladder de Rent the Runway publicado en GitHub, los niveles de Dropbox filtrados en Levels.fyi, el framework de Spotify que circula por LinkedIn. Todos útiles como inspiración, pero ninguno estructurado como librería consumible por código. Eran documentos PDF o páginas web, no APIs.
La alternativa era crear JSON manualmente con los roles que necesitaba. El problema es el mantenimiento. Cuando añades un rol nuevo, tienes que definir 9 niveles con sus competencias. Cuando modificas la estructura de datos, tienes que actualizar todos los archivos. Sin validación automática, es fácil que se cuelen inconsistencias.
Decidí construir una librería completa que sirviera como fuente única de verdad para roles técnicos. 78 roles organizados en 7 categorías. 9 niveles por rol, desde L1 (Trainee) hasta L9 (VP/CTO). Cada nivel con competencias core, competencias complementarias, indicadores de desempeño, y rango de años de experiencia típico. Soporte bilingüe porque operamos en mercados hispanohablantes y anglófonos.
El resultado es @sparring/tech-roles-library: 702 definiciones únicas de rol-nivel con API completa para búsqueda, filtrado, análisis de career paths y comparación entre niveles.
Instalación y estructura básica
npm install @sparring/tech-roles-library
La librería exporta una clase principal que inicializas con el idioma deseado:
const TechRolesLibrary = require('@sparring/tech-roles-library');
// Inglés por defecto
const library = new TechRolesLibrary();
// Español
const libraryES = new TechRolesLibrary({ language: 'es' });
El idioma afecta todos los textos: nombres de roles, nombres de niveles, competencias, indicadores. Un "Backend Developer" en inglés es "Desarrollador Backend" en español. Las competencias están traducidas profesionalmente, no con Google Translate.
La estructura de datos de cada entrada de rol-nivel incluye:
{
category: 'Software Engineering',
role: 'Backend Developer',
level: 'L5 - Mid-level II',
code: 'BE-L5',
levelNumber: 5,
yearsRange: { min: 5, max: 7 },
coreCompetencies: [
'Diseño de APIs RESTful escalables',
'Optimización de consultas SQL complejas',
'Implementación de patrones de microservicios',
// ... más competencias
],
complementaryCompetencies: [
'Conocimiento de sistemas de mensajería',
'Experiencia con contenedores',
// ... más competencias
],
indicators: [
'Lidera features de complejidad media-alta',
'Mentoriza desarrolladores junior',
'Participa activamente en decisiones de arquitectura'
]
}
El código (BE-L5) es un identificador único que combina abreviatura del rol y número de nivel. Es útil para referencias rápidas en bases de datos o URLs.
Acceso básico a roles y niveles
Obtener la lista de todos los roles disponibles:
const roles = library.getRoles();
console.log(`Total roles: ${roles.length}`); // 78
// Muestra: ['AI Engineer', 'Backend Developer', 'Data Analyst', ...]
Obtener un rol-nivel específico por su código:
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 }
Obtener todos los niveles de un rol específico:
const backendLevels = library.getLevelsForRole('Backend Developer');
backendLevels.forEach(entry => {
console.log(`${entry.code}: ${entry.level} (${entry.yearsRange.min}-${entry.yearsRange.max || '15+'} años)`);
});
// Salida:
// BE-L1: L1 - Trainee (0-1 años)
// BE-L2: L2 - Junior I (1-2 años)
// BE-L3: L3 - Junior II (2-3 años)
// BE-L4: L4 - Mid-level I (3-5 años)
// BE-L5: L5 - Mid-level II (5-7 años)
// BE-L6: L6 - Senior I (7-10 años)
// BE-L7: L7 - Senior II (10-12 años)
// BE-L8: L8 - Staff/Principal (12-15 años)
// BE-L9: L9 - VP/CTO (15+ años)
Categorías de roles
Los 78 roles están organizados en 7 categorías que reflejan la estructura típica de equipos tech:
| Categoría | Roles | Descripción |
|---|---|---|
| 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 |
Filtrar roles por categoría:
const categories = library.getCategories();
console.log(categories);
// ['AI/ML', 'Data', 'Infrastructure', 'Product', 'Sales', 'Security', 'Software Engineering']
const aiRoles = library.filterByCategory('AI/ML');
console.log(`Roles de AI/ML: ${aiRoles.length / 9}`); // 16 roles × 9 niveles = 144 entradas
Filtrar todos los roles de un nivel específico:
const allSeniors = library.filterByLevel('L6');
console.log(`Roles Senior I: ${allSeniors.length}`); // 78 (uno por cada rol)
Búsqueda de roles
Cuando construyes un selector de roles en una UI, necesitas búsqueda por texto. El método search() encuentra roles por nombre o categoría:
const results = library.search('fullstack', { limit: 5 });
results.forEach(result => {
console.log(`${result.role} (${result.category}) - Score: ${result.matchScore}`);
});
// Salida:
// Full-Stack Developer (Software Engineering) - Score: 10
// Full-Stack Engineer (Software Engineering) - Score: 10
El matchScore indica relevancia: 10 puntos si matchea en nombre del rol, 5 puntos si matchea en categoría. Los resultados vienen ordenados por score descendente.
// Buscar por categoría
const dataResults = library.search('data');
// Encuentra: Data Analyst, Data Engineer, Data Scientist, etc.
// También encuentra roles en categoría "Data"
Análisis de career paths
Esta es la funcionalidad más potente para planificación de carreras. Dado un rol y nivel actual, puedes obtener la vista completa del itinerario.
Qué necesitas para subir de nivel
const nextLevel = library.getNextLevel('Backend Developer', 'L5');
console.log(`Nivel actual: ${nextLevel.current.level}`);
console.log(`Siguiente nivel: ${nextLevel.next.level}`);
console.log(`Años típicos: ${nextLevel.next.yearsRange.min}-${nextLevel.next.yearsRange.max}`);
console.log(`Nuevas competencias a desarrollar: ${nextLevel.newCompetenciesCount}`);
nextLevel.newCompetencies.forEach(comp => {
console.log(` - ${comp}`);
});
// Salida:
// Nivel actual: L5 - Mid-level II
// Siguiente nivel: L6 - Senior I
// Años típicos: 7-10
// Nuevas competencias a desarrollar: 8
// - Liderazgo técnico de equipos pequeños
// - Definición de estándares de código
// - Evaluación y selección de tecnologías
// - ...
Esto responde la pregunta que todo desarrollador tiene: "¿qué necesito aprender para promocionar?"
Vista completa del career path
const career = library.getCareerPathComplete('Backend Developer', 'L5');
console.log('=== Niveles dominados ===');
career.masteredLevels.forEach(level => {
console.log(`${level.code}: ${level.coreCompetencies.length} competencias`);
});
console.log('\n=== Nivel actual ===');
console.log(`${career.currentLevel.code}: ${career.currentLevel.level}`);
console.log('\n=== Camino de crecimiento ===');
career.growthPath.forEach(level => {
console.log(`${level.code}: ${level.level}`);
});
console.log('\n=== Resumen ===');
console.log(`Competencias dominadas: ${career.summary.totalMasteredCompetencies}`);
console.log(`Competencias nivel actual: ${career.summary.currentLevelCompetencies}`);
console.log(`Por aprender: ${career.summary.remainingToLearn}`);
console.log(`Progreso: ${career.summary.progressPercentage}%`);
Esta vista es útil para:
- Empleados: Ver dónde están y qué les falta
- Managers: Planificar desarrollo de su equipo
- HR: Diseñar planes de formación basados en gaps reales
Competencias acumuladas
Las competencias son acumulativas. Un L5 debe dominar todo lo de L1-L4 más las específicas de L5:
const accumulated = library.getAccumulatedCompetencies('Backend Developer', 'L5');
accumulated.levels.forEach(level => {
console.log(`\n${level.level}:`);
level.coreCompetencies.forEach(comp => {
console.log(` ✓ ${comp}`);
});
});
Esto genera el catálogo completo de competencias que alguien en ese nivel debe demostrar.
Encontrar nivel por años de experiencia
Si solo conoces los años de experiencia de alguien, puedes estimar su nivel:
const level = library.getByExperience('Backend Developer', 6);
console.log(level.level); // 'L5 - Mid-level II'
console.log(level.yearsRange); // { min: 5, max: 7 }
Esto es una estimación basada en rangos típicos. 6 años de experiencia cae en el rango de L5 (5-7 años). Pero recuerda: años no equivalen a nivel. Un desarrollador con 6 años haciendo lo mismo puede estar en L3 por competencias reales.
Estadísticas del catálogo
Para dashboards o reportes:
const stats = library.getStatistics();
console.log(`Total roles: ${stats.totalRoles}`); // 78
console.log(`Total entradas: ${stats.totalEntries}`); // 702
console.log(`Categorías: ${stats.totalCategories}`); // 7
console.log('Por categoría:', stats.byCategory);
// { 'Software Engineering': 297, 'AI/ML': 144, 'Data': 135, ... }
Catálogo completo con metadata:
const catalog = library.getAllRolesWithMetadata();
catalog.roles.forEach(roleInfo => {
console.log(`${roleInfo.role} (${roleInfo.category})`);
console.log(` Niveles: ${roleInfo.levelCount}`);
console.log(` Competencias totales: ${roleInfo.statistics.totalCompetencies}`);
});
Soporte bilingüe
Todas las traducciones son profesionales con terminología técnica correcta. No hay mezcla de idiomas ni traducciones literales que no tienen sentido en el contexto tech.
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'
// Las competencias también están traducidas
console.log(roleEN.coreCompetencies[0]); // 'Scalable RESTful API design'
console.log(roleES.coreCompetencies[0]); // 'Diseño de APIs RESTful escalables'
El español usa español neutro sin regionalismos. "Desarrollador" en lugar de "Programador". "Competencias" en lugar de "Habilidades". Terminología que funciona igual en España, México, Argentina o Colombia.
Los 9 niveles explicados
El framework usa 9 niveles estandarizados que mapean a estructuras típicas de empresas tech:
| Nivel | Nombre | Años típicos | Descripción |
|---|---|---|---|
| L1 | Trainee | 0-1 | Recién graduado, en formación |
| L2 | Junior I | 1-2 | Ejecuta tareas definidas con supervisión |
| L3 | Junior II | 2-3 | Autonomía en tareas de complejidad baja |
| L4 | Mid-level I | 3-5 | Autonomía completa en features medianas |
| L5 | Mid-level II | 5-7 | Lidera features, empieza a mentorizar |
| L6 | Senior I | 7-10 | Liderazgo técnico, decisiones de arquitectura |
| L7 | Senior II | 10-12 | Referente técnico del equipo |
| L8 | Staff/Principal | 12-15 | Impacto cross-team, define estándares |
| L9 | VP/CTO | 15+ | Liderazgo estratégico, visión técnica |
Los años son orientativos. Un desarrollador excepcional puede llegar a L6 en 5 años. Uno que se estanca puede quedarse en L4 con 10 años de experiencia. Lo que importa son las competencias demostradas, no el calendario.
Casos de uso reales
Sistema de evaluación de candidatos
// Candidato dice tener nivel Senior (L6)
const expectedCompetencies = library.getCompetencies('Backend Developer', 'L6');
// Comparar con competencias que demuestra en entrevista
const demonstrated = evaluateInterview(candidate);
const gaps = expectedCompetencies.core.filter(
comp => !demonstrated.includes(comp)
);
if (gaps.length > 3) {
console.log('Candidato no cumple nivel L6, gaps:', gaps);
// Sugerir L5 o L4 según gaps
}
Plan de desarrollo individual
const employee = { role: 'Frontend Developer', currentLevel: 'L4' };
const nextLevel = library.getNextLevel(employee.role, employee.currentLevel);
// Generar plan de desarrollo
const developmentPlan = {
currentLevel: employee.currentLevel,
targetLevel: nextLevel.next.level,
timeframe: `${nextLevel.next.yearsRange.min - 3} - ${nextLevel.next.yearsRange.max - 3} años`,
competenciesToDevelop: nextLevel.newCompetencies,
suggestedTraining: mapCompetenciesToCourses(nextLevel.newCompetencies)
};
Comparación salarial por nivel
// Tu base de datos de salarios por nivel
const salaryBands = {
'L4': { min: 35000, max: 45000 },
'L5': { min: 45000, max: 55000 },
'L6': { min: 55000, max: 70000 }
};
// Empleado pide subida
const employee = library.getRole('FE-L5');
const band = salaryBands['L5'];
console.log(`Banda salarial para ${employee.level}: ${band.min}€ - ${band.max}€`);
Organigramas técnicos
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
Validación y calidad de datos
La librería pasó 99 tests antes de publicación:
- Integridad estructural: Todos los JSON válidos, sin campos faltantes
- Consistencia de niveles: Cada rol tiene exactamente 9 niveles L1-L9
- Validación de traducciones: 0% contaminación entre idiomas (ni palabras en inglés en archivos ES ni viceversa)
- Rangos de años coherentes: L1 < L2 < L3... sin solapamientos
- Códigos únicos: Sin duplicados en los 702 códigos de rol-nivel
Cada release ejecuta validación completa. Si añades un rol nuevo vía PR, los tests verifican que tenga estructura correcta, 9 niveles, traducciones completas, y códigos que sigan el patrón existente.
TypeScript: tipos completos
El paquete incluye definiciones TypeScript. No necesitas @types/ adicionales:
import TechRolesLibrary from '@sparring/tech-roles-library';
import type { RoleEntry, CareerPath, SearchResult } from '@sparring/tech-roles-library';
const library = new TechRolesLibrary({ language: 'es' });
// TypeScript conoce el tipo de retorno
const role: RoleEntry = library.getRole('BE-L5');
const career: CareerPath = library.getCareerPathComplete('Backend Developer', 'L5');
const results: SearchResult[] = library.search('frontend');
Los tipos están completos: RoleEntry, CareerPath, SearchResult, LibraryStatistics, opciones de configuración. El autocompletado de VS Code funciona perfectamente.
Cero dependencias
El paquete no tiene dependencias de runtime. El package.json solo lista devDependencies para testing y build. Esto significa:
- Bundle size mínimo
- Sin conflictos de versiones con otras librerías
- Sin vulnerabilidades heredadas de dependencias
- Funciona en cualquier entorno Node.js 16+
Los archivos de traducción se cargan con lazy loading. Si usas el paquete en español, no carga los archivos ingleses hasta que cambies de idioma.
Demo interactiva
Puedes explorar el catálogo completo en la demo web:
https://686f6c61.github.io/npm-tech-roles-library/demo/
La demo permite:
- Navegar roles por categoría
- Ver los 9 niveles de cada rol
- Explorar competencias de cada nivel
- Cambiar entre inglés y español
El código fuente está en GitHub: github.com/686f6c61/npm-tech-roles-library
El paquete está publicado en NPM: @sparring/tech-roles-library
Contribuciones bienvenidas para añadir roles faltantes, mejorar traducciones, o corregir competencias que no reflejen la realidad del mercado actual.