Auto-deploy: 2026-08-05 16:58:10
This commit is contained in:
+62
-13
@@ -17,6 +17,7 @@ const PROFILE_DATA = {
|
||||
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)',
|
||||
@@ -47,9 +48,13 @@ const PROFILE_DATA = {
|
||||
'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 and Founding Engineer with proven experience building and launching two ' +
|
||||
'production-grade ride-hailing platforms (Tripz — Egypt, Intaleq — Syria) from zero to live operations. ' +
|
||||
'Senior Mobile Architect 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 backend APIs, security layers, DevOps pipelines and fintech integrations. ' +
|
||||
'Specialized in real-time systems, self-hosted geo-services, high-latency optimization and ' +
|
||||
@@ -61,12 +66,16 @@ const PROFILE_DATA = {
|
||||
'Founding Engineer (Mobility, Logistics, FinTech)'
|
||||
],
|
||||
|
||||
// Headline metrics — these are the numbers that carry the CV.
|
||||
// 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.
|
||||
headlineMetrics: [
|
||||
{ value: '5,275', label: 'Riders acquired across 2 launches' },
|
||||
{ value: '5,750+', label: 'Drivers onboarded' },
|
||||
{ value: '~80%', label: 'Map infrastructure cost cut' },
|
||||
{ value: '8 apps', label: 'Shipped across 2 platforms' }
|
||||
{ value: '8 apps', label: 'Shipped across 2 production platforms' },
|
||||
{ value: '<4 months', label: 'Zero to live operations (Tripz, full ecosystem)' },
|
||||
{ value: '$10K+/mo', label: 'Map infrastructure cost eliminated (~80% reduction)' },
|
||||
{ value: '5,750+', label: 'Drivers onboarded across 2 markets' }
|
||||
],
|
||||
|
||||
achievementsAtAGlance: [
|
||||
@@ -119,14 +128,22 @@ const PROFILE_DATA = {
|
||||
},
|
||||
{
|
||||
company: 'Tripz',
|
||||
title: 'Founding Mobile Architect',
|
||||
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: [
|
||||
{ text: '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', 'mobility', 'scale', 'flutter'] },
|
||||
{ text: 'Designed real-time dispatch and live tracking using WebSockets, optimized for high-latency MENA network environments.', tags: ['realtime', 'websockets', 'geo'] },
|
||||
{ text: 'Reduced map infrastructure expenses by approximately 80% versus third-party API pricing by self-hosting map tiles, routing logic and polyline generation on dedicated servers.', tags: ['geo', 'cost', 'infrastructure'] },
|
||||
{ text: 'Eliminated over $10,000/month in third-party mapping API spend (~80% reduction) 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'] },
|
||||
@@ -134,9 +151,13 @@ const PROFILE_DATA = {
|
||||
]
|
||||
},
|
||||
{
|
||||
company: 'Global Tech Projects',
|
||||
// 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: 'Freelance / Consultant',
|
||||
location: 'Various Clients — MENA & Remote',
|
||||
start: 'Jan 2017',
|
||||
end: 'Dec 2023',
|
||||
bullets: [
|
||||
@@ -147,6 +168,26 @@ const PROFILE_DATA = {
|
||||
}
|
||||
],
|
||||
|
||||
// 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",
|
||||
@@ -232,10 +273,18 @@ function renderProfileText(p = PROFILE_DATA) {
|
||||
lines.push('');
|
||||
lines.push('EXPERIENCE:');
|
||||
p.experience.forEach(job => {
|
||||
lines.push(`- ${job.title} — ${job.company} | ${job.start} – ${job.end} | ${job.location}`);
|
||||
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}`));
|
||||
@@ -249,7 +298,7 @@ function renderProfileText(p = PROFILE_DATA) {
|
||||
lines.push('');
|
||||
lines.push(`LANGUAGES: ${id.languages}`);
|
||||
lines.push(`LOCATION: ${id.location} — ${id.availability}`);
|
||||
lines.push(`CONTACT: ${id.email} | ${id.phone} | ${id.linkedin} | ${id.portfolio}`);
|
||||
lines.push(`CONTACT: ${id.email} | ${id.phone} | ${id.linkedin} | ${id.github} | ${id.portfolio}`);
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
@@ -106,10 +106,15 @@
|
||||
<h2>Professional Experience</h2>
|
||||
{{EXPERIENCE_BLOCK}}
|
||||
|
||||
<h2>Open Source</h2>
|
||||
{{OPENSOURCE_BLOCK}}
|
||||
|
||||
<!-- Certifications sit inside Education rather than claiming a heading of
|
||||
their own: they are data-analytics certificates on a mobile engineering
|
||||
CV, so a dedicated section would draw the eye to the least relevant
|
||||
content on the page. -->
|
||||
<h2>Education</h2>
|
||||
{{EDUCATION_BLOCK}}
|
||||
|
||||
<h2>Certifications</h2>
|
||||
{{CERTIFICATIONS_BLOCK}}
|
||||
|
||||
<h2>Additional Information</h2>
|
||||
|
||||
+44
-5
@@ -199,9 +199,23 @@ Return ONLY raw JSON (no markdown fences) with EXACTLY these keys:
|
||||
],
|
||||
"ats_keywords_matched": ["exact terms from the posting that now appear in the CV"],
|
||||
"ats_keywords_missing": ["requirements from the posting I genuinely cannot claim"],
|
||||
"estimated_ats_score": 0
|
||||
"estimated_ats_score": 0,
|
||||
"is_founding_or_startup_role": false
|
||||
}
|
||||
|
||||
"is_founding_or_startup_role": true ONLY when the hiring company is an early-stage
|
||||
startup, or the posting explicitly seeks a founding engineer / first engineer /
|
||||
0-to-1 builder / someone to own a product end-to-end. false for established
|
||||
companies, enterprises, banks, agencies and government. This controls whether my
|
||||
CV presents a past role as "Founding Mobile Architect" or "Lead Mobile Engineer" —
|
||||
identical work, framed for the reader.
|
||||
|
||||
CONSISTENCY RULE: when "is_founding_or_startup_role" is false, the words
|
||||
"Founding" and "Founder" must NOT appear anywhere in "headline" or "summary"
|
||||
either. Describe the same 0-to-1 ownership as "built and launched from zero" or
|
||||
"owned end-to-end" instead. A CV that avoids "Founding" in the job title but
|
||||
keeps it in the summary reads as careless.
|
||||
|
||||
RULES FOR "roles":
|
||||
- Include EVERY role index that exists in MY REAL DATA, in the same order.
|
||||
- For each role select the 3-4 bullets MOST relevant to this job (fewer for the
|
||||
@@ -283,9 +297,15 @@ PROMPT;
|
||||
$contactBlock =
|
||||
'<div>' . e($id['location']) . ' | ' . e($id['phone'])
|
||||
. ' | ' . e($id['email']) . '</div>'
|
||||
. '<div>' . e($id['linkedin']) . ' | ' . e($id['portfolio'])
|
||||
. '<div>' . e($id['linkedin']) . ' | ' . e($id['github'])
|
||||
. ' | ' . e($id['portfolio'])
|
||||
. ' | ' . e($id['productSite']) . '</div>';
|
||||
|
||||
// "Founding" reads as an asset at a startup and as flight risk at an
|
||||
// established company. The model classifies the employer; the facts under
|
||||
// the title are identical either way.
|
||||
$isFoundingContext = $integrityClean && !empty($ai['is_founding_or_startup_role']);
|
||||
|
||||
$skillsBlock = '';
|
||||
foreach ($profile['skills'] as $group => $items) {
|
||||
$skillsBlock .= '<p class="skill-line"><span class="label">' . e($group) . ':</span> '
|
||||
@@ -305,7 +325,17 @@ PROMPT;
|
||||
$edu = $profile['education'];
|
||||
$educationBlock = '<p>' . e($edu['degree']) . ' — ' . e($edu['institution']) . '. ' . e($edu['note']) . '</p>';
|
||||
|
||||
$certBlock = '<p>' . e(implode(' · ', $profile['certifications'])) . '</p>';
|
||||
$certBlock = '<p class="skill-line"><span class="label">Certifications:</span> '
|
||||
. e(implode(' · ', $profile['certifications'])) . '</p>';
|
||||
|
||||
// Package URLs are printed as plain text, not anchor labels — many parsers
|
||||
// read the visible text rather than the href, and a recruiter needs to be
|
||||
// able to retype these.
|
||||
$openSourceBlock = '';
|
||||
foreach (($profile['openSource'] ?? []) as $pkg) {
|
||||
$openSourceBlock .= '<p class="skill-line"><span class="label">' . e($pkg['name']) . '</span> — '
|
||||
. e($pkg['platform']) . ' · ' . e($pkg['url']) . '. ' . e($pkg['description']) . '</p>';
|
||||
}
|
||||
|
||||
$availability = $market === 'amman'
|
||||
? 'Based in Amman, Jordan. Available immediately for on-site, hybrid and remote roles.'
|
||||
@@ -329,7 +359,8 @@ PROMPT;
|
||||
|
||||
$buildHtml = function (array $d) use (
|
||||
$profile, $id, $template, $aiRoles, $headline, $summary, $coreSkills,
|
||||
$contactBlock, $skillsBlock, $educationBlock, $certBlock, $availability
|
||||
$contactBlock, $skillsBlock, $educationBlock, $certBlock, $availability,
|
||||
$openSourceBlock, $isFoundingContext
|
||||
) {
|
||||
// Headline metrics collapse to a single dense line. As four separate
|
||||
// bullets they cost four lines to say what one line says.
|
||||
@@ -351,8 +382,15 @@ PROMPT;
|
||||
|
||||
$experienceBlock = '';
|
||||
foreach ($profile['experience'] as $ri => $role) {
|
||||
$roleTitle = $role['title'];
|
||||
if (!empty($role['titleVariants'])) {
|
||||
$roleTitle = $isFoundingContext
|
||||
? ($role['titleVariants']['founding'] ?? $roleTitle)
|
||||
: ($role['titleVariants']['standard'] ?? $roleTitle);
|
||||
}
|
||||
|
||||
$experienceBlock .= '<div class="job">';
|
||||
$experienceBlock .= '<p class="job-title">' . e($role['title']) . '</p>';
|
||||
$experienceBlock .= '<p class="job-title">' . e($roleTitle) . '</p>';
|
||||
$experienceBlock .= '<p class="job-company">' . e($role['company']) . ' — ' . e($role['location']) . '</p>';
|
||||
$experienceBlock .= '<p class="job-dates">' . e($role['start']) . ' – ' . e($role['end']) . '</p>';
|
||||
|
||||
@@ -394,6 +432,7 @@ PROMPT;
|
||||
'{{DYNAMIC_SKILLS}}' => e($coreSkills),
|
||||
'{{SKILLS_BLOCK}}' => $skillsBlock,
|
||||
'{{EXPERIENCE_BLOCK}}' => $experienceBlock,
|
||||
'{{OPENSOURCE_BLOCK}}' => $openSourceBlock,
|
||||
'{{EDUCATION_BLOCK}}' => $educationBlock,
|
||||
'{{CERTIFICATIONS_BLOCK}}' => $certBlock,
|
||||
'{{LANGUAGES}}' => e($id['languages']),
|
||||
|
||||
+37
-18
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user