Files
cv/profile_data.js
T

475 lines
27 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// profile_data.js — SINGLE SOURCE OF TRUTH
// ============================================================================
// Every prompt, CV, cover letter and comment in this extension derives from
// this file. Nothing else may hardcode job titles, metrics, dates or contacts.
//
// Synced from: cvs/ATS-safe résumé template.pdf (master CV).
// If the master CV changes, change THIS file — then nothing else needs editing.
// A mirror copy lives at server/profile.json for the PHP backend.
// ============================================================================
const PROFILE_DATA = {
identity: {
fullName: 'Hamza Ayed',
primaryTitle: 'Founding Technical Architect',
// Ride-hailing is the flagship, not the fence. The earlier line named only
// the two mobility platforms, and every downstream prompt read that as the
// whole scope — so full-stack backend, native Android, security and DevOps
// work (30+ shipped apps across e-commerce, delivery, healthcare, news)
// silently stopped counting toward any match score.
positioningLine:
'End-to-End Product Engineer · Flutter & Native Mobile · PHP/Laravel, Node.js & Python Backends · ' +
'Real-Time Geo Systems · Product Delivery · Technology Strategy',
location: 'Amman, Jordan',
phone: '+962 798 583 052',
email: 'hamzaayedflutter@gmail.com',
linkedin: 'linkedin.com/in/hamza-ayed',
github: 'github.com/Hamza-Ayed',
portfolio: 'intaleqapp.com/hamza.html',
productSite: 'tripz-egypt.com',
languages: 'Arabic (Native), English (Professional Working Proficiency)',
availability: 'Available immediately. Open to Remote, Hybrid and Relocation (GCC / MENA / Europe).'
},
// Titles the CV/headline generator is ALLOWED to use. Anything outside this
// list is a fabrication risk — see integrity rules in prompts.js.
allowedTitles: [
'Founding Technical Architect',
'Technical Founder',
'Principal Software Architect',
'Senior Mobile Architect',
'Senior Mobile Engineer',
'Lead Mobile Engineer',
'Senior Flutter Developer',
'Lead Flutter Engineer',
'Mobile Technical Lead',
'Founding Engineer (Mobile)',
'Senior Software Engineer (Mobile)',
'Senior Backend Engineer',
'Senior Full Stack Engineer'
],
// Titles that would overstate or misrepresent the record.
forbiddenTitles: [
'CTO',
'Senior AI Developer',
'Machine Learning Engineer',
'Data Scientist',
'DevOps Architect',
'Engineering Manager'
],
// Opens on what was built, not on a self-description. "Proven experience" and
// "Founding Engineer" were removed: the first is filler, and the second
// contradicts the standard (non-startup) title framing when this text is used
// as the fallback summary.
summary:
'Senior Mobile Architect & Full Stack Engineer who built and launched two production-grade ride-hailing platforms ' +
'(Tripz — Egypt, Intaleq — Syria) from zero to live operations. ' +
'Designed and delivered full mobility ecosystems including Rider, Driver, Admin and Customer Support ' +
'applications, along with scalable backend APIs, security layers, DevOps pipelines and fintech integrations. ' +
'Specialized in real-time systems, self-hosted geo-services, high-latency optimization and ' +
'infrastructure cost reduction.',
// ── Roles I actually apply to ─────────────────────────────────────────────
// These are PRODUCT-ENGINEERING roles: something ships to users. My security,
// server and DevOps work is real, but it is infrastructure I built in service
// of products I owned — it is not a career track I am pursuing. See
// `supportingSkills` below, which exists to stop the analyser from reading a
// skill as a target.
targetRoles: [
'Hands-on CTO / Founding CTO where architecture and product delivery are primary; team-management requirements must be assessed as gaps',
'Founding Technical Leader / Technical Co-Founder with a clear commercial mandate',
'Principal Software Architect / Technical Lead with business ownership',
'Senior / Lead / Staff Mobile Engineer',
'Flutter Developer (any seniority at or above mid-level)',
'Android Developer',
'Mobile Architect / Mobile Technical Lead',
'Founding Engineer (Mobility, Logistics, FinTech, any early-stage product)',
'Senior Backend Engineer (PHP / Laravel, Node.js, Python)',
'Full Stack Engineer',
'Maps / Geospatial / Location Platform Engineer',
'Software Engineer (general product engineering)'
],
// Genuine, provable skills that are NOT job targets. They belong in the CV as
// supporting evidence of end-to-end ownership — never as the headline, and
// never as a reason to surface or recommend a job built around them.
supportingSkills: [
'Application & API security (HMAC, anti-tampering, RASP, Fake GPS detection) — ' +
'secured the products I built; not applying for Security Engineer / AppSec / ' +
'Penetration Testing / SOC / Cybersecurity roles',
'Server administration and infrastructure (Linux, Nginx, Docker, VPS, self-hosted ' +
'CI/CD) — ran the infrastructure my own products needed; not applying for ' +
'SysAdmin / DevOps Engineer / SRE / Platform Engineer / Cloud Engineer roles',
'Data analytics certifications (IBM, Google) — background knowledge only; not ' +
'applying for Data Analyst / Data Scientist roles'
],
// Headline metrics — ordered by how well they survive a sceptical reader.
// Delivery speed and breadth lead, because they are genuinely rare. Raw user
// counts trail: a few thousand riders is a small number to anyone who knows
// this market, so it belongs in context (see achievementsAtAGlance) rather
// than as the first claim on the page.
// Each entry is a complete clause, not a label glued to a number. The earlier
// "<value> <label>" form produced ungrammatical fragments ("8 apps Built and
// launched across…") that read as broken to a human and parse poorly.
// `lead` is the scannable metric; `rest` completes the sentence.
//
// "across 2 platforms" (inherited from the master CV) is deliberately spelled
// out: models and recruiters both read it as "iOS and Android app stores"
// rather than "the Tripz and Intaleq platforms".
headlineMetrics: [
{ lead: '8 applications', rest: 'engineered and launched across 2 ride-hailing platforms (Tripz, Intaleq)' },
{ lead: 'Under 4 months', rest: 'from zero to live operations for the full Tripz ecosystem' },
// NOT "eliminated ... (~80% reduction)": a cost cannot be both removed
// entirely and reduced by a percentage. The spend was cut, not zeroed.
{ lead: '~80% lower', rest: 'third-party mapping API spend — over $10,000/month — via self-hosted infrastructure' },
{ lead: '5,750+ drivers', rest: 'onboarded across 2 markets' }
],
achievementsAtAGlance: [
'Tripz (Egypt): Scaled platform to 2,464 riders and 4,318 drivers. Built and launched 4 distinct apps ' +
'plus full backend in under 4 months with near-zero map infrastructure cost.',
'Intaleq (Syria): Acquired 2,811 riders and 1,440 drivers in the first 2 months. Engineered a custom ' +
'operational payment layer to bypass API limitations in a highly constrained market.'
],
// Grouped exactly as the master CV groups them. The ATS keyword selector may
// only choose from these values.
skills: {
'Mobile & Architecture': [
'Flutter', 'Dart', 'GetX', 'Provider', 'Clean Architecture',
'Offline-First Design', 'REST APIs', 'State Management', 'Native Android (Java)',
// Postings write "App Store Connect" and "Google Play Console" literally.
// "iOS / Android Release Management" alone matches neither.
'App Store Connect', 'Google Play Console', 'iOS / Android Release Management',
'Firebase Cloud Messaging (FCM)',
'Push Notifications', 'Background Location Tracking'
],
// Named tools, not capability phrases. An ATS matches "GraphHopper", not
// "Routing Engines" — the generic wording was costing keyword matches on
// every geo-heavy posting.
'Real-Time & Geo Systems': [
'WebSockets', 'Real-Time Dispatching', 'Live Tracking', 'GraphHopper',
'PostGIS', 'Martin (vector tile server)', 'OpenStreetMap (OSM)', 'MapLibre GL',
'Self-Hosted Map Tiles', 'Geospatial Queries', 'High-Latency Network Optimization'
],
'Backend & DevOps': [
'PHP', 'Laravel', 'Node.js', 'NestJS', 'Python', 'Django', 'Flask',
'PostgreSQL', 'MySQL', 'Redis', 'Docker', 'Linux', 'Nginx',
'Git', 'CI/CD (Gitea)', 'Infrastructure Cost Optimization', 'Self-Hosted Infrastructure'
],
'Security & FinTech': [
'Payment Gateway Integration (7+ providers)', 'HMAC Security', 'RASP',
'Fake GPS Detection', 'Anti-Tampering', 'KYC Automation'
]
},
// ── OPEN SLOT: engineering scale metrics ─────────────────────────────────
// Every number on this CV is commercial (riders, drivers, cost). None is an
// engineering number, which is the weakest point remaining in a profile that
// sells real-time systems expertise. Driver count does not demonstrate
// concurrency; concurrent connections do.
//
// Measure these on Intaleq, then paste ONE as a bullet on the Tripz or
// Intaleq role. Never estimate — an invented figure is the single easiest
// thing to get caught on in a systems interview:
// • peak concurrent WebSocket connections
// • location updates ingested per second (peak)
// • trips dispatched per day (peak)
// • p95 dispatch latency, driver ping to rider screen
//
// Template, once measured:
// 'Sustained N concurrent WebSocket connections and M location updates per
// second at peak, holding p95 dispatch latency under X ms on mobile
// networks averaging Y ms RTT.'
experience: [
{
company: 'Intaleq',
title: 'Senior Mobile Systems Architect',
location: 'MENA Region (Remote)',
start: 'Jan 2025',
end: 'Present',
// Tagged so the tailoring engine can pick the 3-4 most job-relevant
// bullets instead of always printing the same ones.
bullets: [
{ text: 'Solely architected and launched a ride-hailing platform in a high-constraint market (Syria), reaching 2,811 riders and 1,440 drivers within the first two months.', tags: ['leadership', 'ownership', 'delivery', 'mobility', 'scale'] },
{ text: 'Designed and implemented Rider, Driver, Admin and Customer Support applications.', tags: ['mobile', 'flutter', 'architecture'] },
{ text: 'Built a custom payment helper application to integrate legacy, non-API local payment gateways, enabling reliable driver balance top-ups despite infrastructure limitations.', tags: ['fintech', 'payments', 'integration'] },
// Names the actual stack. "Self-hosted routing engines" matches nothing
// in an ATS; "GraphHopper" and "PostGIS" match the postings that care.
{ text: 'Ran fully self-hosted geo infrastructure — GraphHopper routing, Martin vector tile serving and PostGIS spatial queries on OpenStreetMap data — removing third-party mapping API dependency and its recurring cost.', tags: ['geo', 'cost', 'infrastructure'] },
{ text: 'Designed an offline-first caching mechanism ensuring data integrity and uninterrupted driver–rider interactions during unstable network conditions.', tags: ['mobile', 'offline', 'reliability'] },
{ text: 'Optimized deployment cycles by 40% through a secure, self-hosted CI/CD pipeline using Gitea, ensuring data sovereignty and rapid release efficiency.', tags: ['devops', 'cicd', 'security'] }
]
},
{
company: 'Tripz',
title: 'Lead Mobile Engineer',
// "Founding" is an asset applying to a startup and a liability applying
// to an established company, where it reads as flight risk and as a
// self-awarded title that no HR department can verify. Same work, same
// facts — the generator picks the framing that fits the employer.
titleVariants: {
standard: 'Lead Mobile Engineer',
founding: 'Founding Mobile Architect'
},
location: 'Cairo, Egypt (Remote)',
start: 'Jan 2024',
end: 'Dec 2024',
bullets: [
// Solo delivery stated outright. Reviewers read the absence of team
// detail as a gap in leadership; naming it as sole ownership turns the
// same fact into the stronger signal it actually is.
{ text: 'Solely architected, built and launched a complete ride-hailing ecosystem (Rider, Driver, Admin, Customer Support apps plus backend API) in under four months, scaling to 2,464 riders and 4,318 drivers.', tags: ['delivery', 'leadership', 'ownership', 'mobility', 'scale', 'flutter'] },
{ text: 'Designed the real-time dispatch and live tracking architecture on WebSockets with Redis-backed state, sustaining continuous driver location streams over high-latency MENA mobile networks.', tags: ['realtime', 'websockets', 'geo', 'architecture', 'scale'] },
{ text: 'Cut third-party mapping API spend by approximately 80% — over $10,000/month — by self-hosting map tiles, routing logic and polyline generation on dedicated servers.', tags: ['geo', 'cost', 'infrastructure'] },
{ text: 'Replaced traditional call-center hardware by engineering a secure, mobile-first Customer Support application, enabling support agents to operate entirely remotely.', tags: ['mobile', 'product', 'cost'] },
{ text: 'Automated driver onboarding through AI-powered KYC integration, reducing manual review time and minimizing fraudulent registrations.', tags: ['ai', 'automation', 'fintech', 'security'] },
{ text: 'Implemented API-level HMAC security, anti-tampering mechanisms and Fake GPS detection to protect geo-spatial and financial data.', tags: ['security', 'geo', 'fintech'] },
{ text: 'Collaborated closely with business stakeholders and operations teams to align product and architecture decisions with on-the-ground market realities.', tags: ['leadership', 'product', 'communication'] }
]
},
{
// Previously "Global Tech Projects" — an invented company name reads as a
// placeholder to any experienced recruiter, and it was covering seven of
// the nine years on this CV. Naming the arrangement honestly is weaker in
// sound and considerably stronger in credibility.
company: 'Independent Consultant',
title: 'Lead Mobile Engineer (Flutter / Native)',
location: 'Various Clients — MENA & Remote',
start: 'Jan 2017',
end: 'Dec 2023',
bullets: [
{ text: 'Delivered 30+ production-grade mobile applications across e-commerce, delivery, healthcare and news sectors, acting as technical decision-maker for early-stage clients.', tags: ['delivery', 'leadership', 'mobile', 'scale'] },
{ text: 'Migrated legacy Android (Java) applications to Flutter, cutting maintenance complexity and delivery timelines by roughly 50%.', tags: ['flutter', 'migration', 'mobile'] },
// Ordered by how often each is actually screened for in mobile roles.
// When the tailoring model returns fewer bullets than the page allows,
// the generator tops up in this order — so the more commonly required
// evidence fills the slot first.
{ text: 'Owned App Store and Google Play release management end-to-end, from store listings and review submission through versioned production rollout.', tags: ['mobile', 'release', 'ios', 'android', 'delivery'] },
{ text: 'Built custom Flutter plugins and tailored API layers to integrate with complex legacy backend systems.', tags: ['flutter', 'integration', 'architecture'] }
]
}
],
// Published packages are the single most verifiable credential a mobile
// engineer can offer. They matter more here than usual: none of the three
// employers on this CV is a recognisable brand a recruiter can call, so a
// one-click-checkable artefact carries the credibility the employer names
// cannot.
openSource: [
{
name: 'intaleq_maps',
platform: 'Flutter SDK — pub.dev',
url: 'pub.dev/packages/intaleq_maps',
description: 'Map rendering, offline tile caching and route plotting, optimised for low-bandwidth environments.'
},
{
name: 'intaleq-maps-gl',
platform: 'JavaScript library — npm',
url: 'npmjs.com/package/intaleq-maps-gl',
description: 'Mapbox GL compatible web library for custom OSM tiles and routing integration.'
}
],
education: {
degree: 'BSc Mathematics',
institution: "Mu'tah University, Jordan",
note: 'Applied mathematical foundations to state-machine design and geo-spatial routing.'
},
certifications: [
'IBM Data Analyst Professional Certificate',
'Google Data Analytics Professional Certificate',
'IBM Data Analytics with Excel and R Specialization'
],
// ── Honest capability boundaries ──────────────────────────────────────────
// Used to stop the model inventing experience. Keep this brutally accurate:
// it is the difference between a CV that survives a technical screen and one
// that does not.
boundaries: {
strongIn: [
// Sole ownership used to sit under limitedIn, where every prompt read it
// as a deficiency and scored down roles that asked for teamwork. It is
// the opposite: shipping four apps plus a backend alone is the rarest
// thing on this CV.
'Sole end-to-end ownership: took two platforms from empty repo to live ' +
'commercial operations alone — product, mobile, backend, infra, release',
'Breadth across the whole stack: mobile, backend, database, servers, ' +
'security and deployment — no hand-off needed to ship a product',
'Flutter / Dart mobile architecture at production scale',
'Real-time systems: WebSockets, dispatching, live tracking',
'Self-hosted geo infrastructure: tiles, routing, polylines',
'Payment gateway integration and constrained-market fintech workarounds',
'Mobile-layer security: HMAC, anti-tampering, Fake GPS detection',
'PHP / Laravel / MySQL backend supporting mobile products',
'Docker, Linux, Nginx, self-hosted CI/CD'
],
// SCOPE OF THIS LIST: it exists to stop the CV/cover-letter generator from
// CLAIMING things that are not true. It is NOT a list of reasons to skip a
// job. Anything here that a posting merely mentions is a learning curve, not
// a disqualifier — see `applyPolicy` below, which governs apply/skip.
limitedIn: [
'User reconfirmed 2026-09-17: no formal engineering people management ever: no direct reports, no hiring, no performance ' +
'reviews. Leadership is technical — architecture ownership, end-to-end delivery, ' +
'stakeholder alignment. Fine for Lead / Staff / Principal roles; only pure ' +
'headcount-management titles (Engineering Manager) are a genuine stretch.',
'AI is limited to INTEGRATING third-party vision/LLM APIs (KYC automation, Gemini API). ' +
'No model training, no MLOps, no deep learning research.',
'Cloud experience is self-hosted/VPS-centric — not deep AWS/GCP/Azure managed-service experience.',
'No Kubernetes in production.',
'No native Swift/SwiftUI or Kotlin-first development — Flutter is the primary mobile path.',
'No data engineering (Spark, Hadoop, Airflow, warehouses).'
],
neverClaim: [
'TensorFlow', 'PyTorch', 'Scikit-learn', 'Spark', 'Hadoop', 'Kubernetes',
'MLOps', 'model training', 'NLP research', 'Swift', 'SwiftUI', 'Kotlin Multiplatform',
'blockchain', 'Salesforce', 'SAP'
]
},
// ── Apply / skip policy ───────────────────────────────────────────────────
// Separate from `boundaries` on purpose. `boundaries` protects CV honesty;
// this governs the apply decision. Before it existed, the analysis tab read
// the boundaries list as a rejection checklist and returned "لا تتقدّم" on
// almost everything — including plain Flutter roles.
applyPolicy: {
// A verdict of "do not apply" is only ever justified by one of these.
hardBlockers: [
'Requires a security clearance, or citizenship/residency I cannot obtain',
'Explicitly no visa sponsorship AND requires being already resident/authorised in that country',
'The core discipline is one I have never practised: pure Data Science, ML/model ' +
'training, pure QA/manual testing, embedded/firmware, game engines, ' +
'Salesforce/SAP/blockchain',
// Distinct from the line above: these ARE things I can do, but they are not
// the career I am building. A posting whose PRIMARY deliverable is
// infrastructure or security — rather than a product that ships to users —
// is a skip even at a high skills match.
'The role\'s primary deliverable is infrastructure or security rather than a ' +
'product: Security Engineer, AppSec, Penetration Tester, SOC/Cybersecurity ' +
'Analyst, SysAdmin, DevOps Engineer, SRE, Platform Engineer, Cloud/Network ' +
'Engineer, Database Administrator. These skills support my product work; ' +
'they are not the job I am looking for.',
'Native-only iOS role demanding Swift/SwiftUI as the primary daily language',
'Junior/intern/graduate level, or pay clearly below market floor',
'Unpaid, equity-only, or an obvious scam posting'
],
// These are the things the analyser kept mistaking for blockers.
notBlockers: [
'ON-SITE or hybrid anywhere in GCC/MENA/Europe — relocation is welcome, not an obstacle',
'A location not yet decided, or an office in a city I do not live in',
'Collaboration requirements may have adjacent stakeholder evidence; this does NOT establish hiring, direct reports or performance management',
'Asking for 1-3 more years than I have, or a higher title than my last one',
'Naming 2-4 tools I have not used, when the core stack is one I know',
'AWS / GCP / Azure named in a posting whose core is application engineering — ' +
'self-hosted Docker/Linux/Nginx/CI-CD transfers directly',
'A domain I have not worked in (health, e-commerce, edtech, logistics, banking)',
'React Native / Kotlin / Java-first mobile roles — Flutter and native Android transfer',
'A degree preference in CS (BSc Mathematics is accepted in practice)',
'Backend-only or full-stack roles — PHP/Laravel, Node.js and Python are all real experience',
// The mirror image of the infrastructure blocker: security and DevOps duties
// listed INSIDE a product role are a plus, not a reason to skip.
'A mobile / backend / full-stack role that also lists security, CI/CD, Docker or ' +
'server duties among its responsibilities — that combination is my strongest fit'
],
// The intended distribution of verdicts across a normal LinkedIn feed.
calibration:
'Evaluate each opportunity independently. Never force a target distribution of APPLY/SKIP. ' +
'Prioritize hands-on technical leadership, architectural ownership and business impact. ' +
'For CTO roles separate role ambition from past title: no CTO appointment or engineering direct reports are claimed. ' +
'A mandatory track record of hiring and managing engineering teams is an unmet requirement. ' +
'Unknown scope, compensation or authority requires clarification, not invented fit. ' +
'A score is a heuristic for stated requirements, never an ATS prediction or probability of getting hired.'
},
// Voice rules — applied to cover letters, LinkedIn comments and posts.
voice: {
tone: 'Technical founder and executive peer: calm, specific, evidence-first. Connect architecture to product, risk, ownership and capital allocation when relevant. Never invent people management or an investment track record.',
banned: [
'I am writing to apply', 'I leverage my expertise', 'passionate about',
'proven track record', 'dynamic environment', 'synergy', 'game-changer',
'disruptive', 'serving millions', 'in the digital age', 'Great post',
'Well said', 'Couldn\'t agree more', 'This resonates',
'في العصر الرقمي', 'مما لا شك فيه', 'ختاماً', 'يعد من أهم'
],
neverMention: [
'military history or background',
'sanctions or politically sensitive framing of the Syria market',
'exact client names under NDA'
]
}
};
// Renders the structured profile into the plain-text block that prompts consume.
function renderProfileText(p = PROFILE_DATA) {
const id = p.identity;
const lines = [];
lines.push(`${id.fullName.toUpperCase()} — ${id.primaryTitle}`);
lines.push(id.positioningLine);
lines.push('');
lines.push('SUMMARY:');
lines.push(p.summary);
lines.push('');
lines.push('TARGET ROLES: ' + p.targetRoles.join(' | '));
lines.push('');
if (p.supportingSkills && p.supportingSkills.length) {
lines.push('SUPPORTING SKILLS (real, but NOT roles I am seeking):');
p.supportingSkills.forEach(s => lines.push(`- ${s}`));
lines.push('');
}
lines.push('HEADLINE METRICS:');
p.headlineMetrics.forEach(m => lines.push(`- ${m.lead} ${m.rest}`));
lines.push('');
lines.push('AT A GLANCE:');
p.achievementsAtAGlance.forEach(a => lines.push(`- ${a}`));
lines.push('');
lines.push('TECHNICAL SKILLS:');
Object.entries(p.skills).forEach(([group, items]) => {
lines.push(`- ${group}: ${items.join(', ')}`);
});
lines.push('');
lines.push('EXPERIENCE:');
p.experience.forEach(job => {
const alt = job.titleVariants
? ` (alternate framing for startup/founding roles: ${job.titleVariants.founding})`
: '';
lines.push(`- ${job.title} — ${job.company} | ${job.start} – ${job.end} | ${job.location}${alt}`);
job.bullets.forEach(b => lines.push(` • ${b.text}`));
});
lines.push('');
lines.push('OPEN SOURCE (published, verifiable):');
(p.openSource || []).forEach(o => {
lines.push(`- ${o.name} (${o.platform}) — ${o.url}. ${o.description}`);
});
lines.push('');
lines.push('EDUCATION:');
lines.push(`- ${p.education.degree}, ${p.education.institution}. ${p.education.note}`);
p.certifications.forEach(c => lines.push(`- ${c}`));
lines.push('');
lines.push('CAPABILITY BOUNDARIES (do not overstate):');
lines.push(' STRONG IN:');
p.boundaries.strongIn.forEach(s => lines.push(` + ${s}`));
lines.push(' LIMITED / NOT EXPERIENCED IN:');
p.boundaries.limitedIn.forEach(s => lines.push(` - ${s}`));
lines.push(' NEVER CLAIM: ' + p.boundaries.neverClaim.join(', '));
lines.push('');
lines.push(`LANGUAGES: ${id.languages}`);
lines.push(`LOCATION: ${id.location} — ${id.availability}`);
lines.push(`CONTACT: ${id.email} | ${id.phone} | ${id.linkedin} | ${id.github} | ${id.portfolio}`);
return lines.join('\n');
}
// Flat list of every legitimate skill token, for ATS keyword matching.
function allSkillTokens(p = PROFILE_DATA) {
return Object.values(p.skills).flat();
}
if (typeof module !== 'undefined' && module.exports) {
module.exports = { PROFILE_DATA, renderProfileText, allSkillTokens };
}