-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjob.py
More file actions
439 lines (408 loc) · 21.3 KB
/
Copy pathjob.py
File metadata and controls
439 lines (408 loc) · 21.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
# -*- coding: utf-8 -*-
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
PageBreak, KeepTogether, HRFlowable
)
from reportlab.pdfgen import canvas
# ---------- Palette ----------
NAVY = colors.HexColor("#0B3B54")
TEAL = colors.HexColor("#1A8F82")
LIGHT_BG = colors.HexColor("#EFF5F4")
TEXT = colors.HexColor("#22303A")
MUTED = colors.HexColor("#5B6B73")
WHITE = colors.white
PAGE_W, PAGE_H = A4
MARGIN = 2.0 * cm
CONTENT_W = PAGE_W - 2 * MARGIN
# ---------- Styles ----------
ss = getSampleStyleSheet()
title_style = ParagraphStyle("TitleStyle", parent=ss["Title"], fontName="Helvetica-Bold",
fontSize=26, leading=30, textColor=NAVY, spaceAfter=6, alignment=TA_LEFT)
subtitle_style = ParagraphStyle("SubtitleStyle", parent=ss["Normal"], fontName="Helvetica-Bold",
fontSize=13.5, leading=17, textColor=TEAL, spaceAfter=4)
meta_style = ParagraphStyle("MetaStyle", parent=ss["Normal"], fontName="Helvetica",
fontSize=9.5, leading=13, textColor=MUTED)
h1_banner_style = ParagraphStyle("H1Banner", parent=ss["Normal"], fontName="Helvetica-Bold",
fontSize=13, leading=16, textColor=WHITE)
h2_style = ParagraphStyle("H2Style", parent=ss["Normal"], fontName="Helvetica-Bold",
fontSize=11.5, leading=15, textColor=NAVY, spaceBefore=10, spaceAfter=4)
body_style = ParagraphStyle("BodyStyle", parent=ss["Normal"], fontName="Helvetica",
fontSize=9.7, leading=14, textColor=TEXT, spaceAfter=4)
body_italic = ParagraphStyle("BodyItalic", parent=body_style, fontName="Helvetica-Oblique",
textColor=MUTED)
bullet_style = ParagraphStyle("BulletStyle", parent=body_style, leftIndent=12, spaceAfter=3)
check_style = ParagraphStyle("CheckStyle", parent=body_style, leftIndent=12, spaceAfter=3)
table_header_style = ParagraphStyle("TableHeader", parent=ss["Normal"], fontName="Helvetica-Bold",
fontSize=9, leading=12, textColor=WHITE)
table_cell_style = ParagraphStyle("TableCell", parent=ss["Normal"], fontName="Helvetica",
fontSize=9, leading=12.5, textColor=TEXT)
table_cell_bold = ParagraphStyle("TableCellBold", parent=table_cell_style, fontName="Helvetica-Bold",
textColor=NAVY)
cover_footer_style = ParagraphStyle("CoverFooter", parent=ss["Normal"], fontName="Helvetica",
fontSize=9.5, leading=13, textColor=MUTED)
story = []
def banner(text):
t = Table([[Paragraph(text, h1_banner_style)]], colWidths=[CONTENT_W])
t.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, -1), NAVY),
("LEFTPADDING", (0, 0), (-1, -1), 10),
("RIGHTPADDING", (0, 0), (-1, -1), 10),
("TOPPADDING", (0, 0), (-1, -1), 7),
("BOTTOMPADDING", (0, 0), (-1, -1), 7),
]))
return t
def rule(color=TEAL, thickness=1.4, space_before=4, space_after=10):
return HRFlowable(width="100%", thickness=thickness, color=color,
spaceBefore=space_before, spaceAfter=space_after)
def bullet(text):
return Paragraph(u"\u2022 " + text, bullet_style)
def check(text):
return Paragraph("[ ] " + text, check_style)
def pillar_block(number, title, objective, actions, note=None):
block = [Paragraph(f"Pillar {number} \u2014 {title}", h2_style)]
block.append(Paragraph(f"<b>Objective:</b> {objective}", body_style))
for a in actions:
block.append(check(a))
if note:
block.append(Paragraph(note, body_italic))
block.append(Spacer(1, 4))
return KeepTogether(block)
def styled_table(header_row, data_rows, col_widths):
rows = [[Paragraph(h, table_header_style) for h in header_row]]
for r in data_rows:
row = [Paragraph(r[0], table_cell_bold)] + [Paragraph(c, table_cell_style) for c in r[1:]]
rows.append(row)
t = Table(rows, colWidths=col_widths, repeatRows=1)
style = [
("BACKGROUND", (0, 0), (-1, 0), TEAL),
("BOX", (0, 0), (-1, -1), 0.6, colors.HexColor("#C9D8D6")),
("INNERGRID", (0, 0), (-1, -1), 0.5, colors.HexColor("#C9D8D6")),
("VALIGN", (0, 0), (-1, -1), "TOP"),
("LEFTPADDING", (0, 0), (-1, -1), 6),
("RIGHTPADDING", (0, 0), (-1, -1), 6),
("TOPPADDING", (0, 0), (-1, -1), 5),
("BOTTOMPADDING", (0, 0), (-1, -1), 5),
]
for i in range(1, len(rows)):
if i % 2 == 0:
style.append(("BACKGROUND", (0, i), (-1, i), LIGHT_BG))
t.setStyle(TableStyle(style))
return t
# =====================================================================
# COVER PAGE
# =====================================================================
story.append(Spacer(1, 5.5 * cm))
story.append(Paragraph("UAE Tech Job Search Plan", title_style))
story.append(Paragraph("Data Analyst / AI Developer / Software Developer — Fresher Track", subtitle_style))
story.append(Spacer(1, 10))
story.append(rule(color=TEAL, thickness=2, space_before=0, space_after=14))
story.append(Paragraph("Prepared for: Fresh graduate, no professional experience, targeting the UAE private-sector tech market", meta_style))
story.append(Paragraph("Plan horizon: 90 days, self-paced", meta_style))
story.append(Paragraph("Prepared: 17 July 2026", meta_style))
story.append(Spacer(1, 6.5 * cm))
story.append(Paragraph(
"This is a general job-search and career-planning guide, not legal, immigration, or visa advice. "
"Confirm current visa and labour rules with official UAE sources or a licensed advisor.",
cover_footer_style))
story.append(PageBreak())
# =====================================================================
# STARTING POINT
# =====================================================================
story.append(banner("Your Starting Point"))
story.append(Spacer(1, 8))
story.append(Paragraph(
"You're a fresh graduate (graduated within the last two years, GPA 3.0+) with no professional "
"experience, targeting a Data Analyst, AI Developer, or Software Developer role in the UAE. "
"You are not a UAE National, so nationality-restricted schemes such as e&'s AI Graduate Programme "
"are not open to you — but the wider private-sector tech market is open to all nationalities "
"through standard employer-sponsored work visas.",
body_style))
story.append(Paragraph(
"The core challenge is the classic double catch-22: most junior job ads ask for experience you don't "
"have yet, and many employers additionally want to see \u201cUAE experience\u201d specifically. Entry-level "
"tech hiring is also tight globally right now, not just in the UAE. None of this makes the goal "
"unrealistic — it means the applicants who break in are the ones who show visible proof of skill "
"and get in front of people, rather than the ones who just apply the most.",
body_style))
story.append(Paragraph(
"This plan is built around that reality: build proof of skill first, use internships as your legitimate "
"entry ramp, and treat networking as a core activity rather than an afterthought — because UAE tech "
"hiring runs on referrals more than cold applications.",
body_style))
story.append(Spacer(1, 8))
# =====================================================================
# THE 8 PILLARS
# =====================================================================
story.append(banner("The 8-Pillar Action Plan"))
story.append(Spacer(1, 8))
story.append(pillar_block(
1, "Build Proof-of-Skill Projects",
"Replace \u201clist of skills\u201d with visible, working evidence you can build things.",
[
"Choose your primary track: Data Analyst / AI, or Software Developer (or run both in parallel if undecided)",
"Data track: complete 2 end-to-end projects on real, messy datasets (Kaggle is fine) — clean, analyse, visualise, and write up the insight",
"Data track: publish 1 interactive dashboard (Power BI or Tableau Public) with a public link",
"Dev track: build and deploy 2\u20133 full applications (not tutorial clones) with live demo links and clean GitHub repos + READMEs",
"Dev track: add automated tests and a CI pipeline to at least one project to signal engineering maturity",
],
"Aim to have your first project live within 2 weeks and a second within 6."
))
story.append(pillar_block(
2, "Get One Targeted Certification",
"One recognised, role-relevant certification outperforms several generic ones.",
[
"Data Analyst: Google Data Analytics Certificate",
"Data / AI: Microsoft Azure Data Fundamentals (DP-900), then DP-100 if time allows",
"AI Developer: an AWS or Azure ML fundamentals certification after the above",
"Software Developer: AWS Certified Cloud Practitioner plus one language- or framework-specific certification",
],
None
))
story.append(pillar_block(
3, "Build a UAE-Format, ATS-Safe CV and LinkedIn",
"Most UAE employers screen CVs through an applicant tracking system before a human sees them.",
[
"One page, single column, no infographic templates, tables, or photos that break text parsing",
"Standard section headers: Summary, Skills, Projects, Education, Certifications",
"Every project bullet states what you built, the tools used, and a measurable outcome",
"State your visa/relocation status clearly near the top of the CV",
"Match your LinkedIn headline and About section to your target role and keywords",
],
None
))
story.append(pillar_block(
4, "Target Employers Who Actually Hire Freshers",
"Stop applying to senior-only listings; focus effort where junior hiring genuinely happens.",
[
"Prioritise consumer tech/product companies, AI-hub startups, and fintechs (see employer table, next page)",
"Deprioritise senior-only listings at large telecoms, utilities, and sovereign entities unless explicitly marked entry-level",
"Shortlist 15\u201320 target companies and track them individually rather than mass-applying blindly",
],
None
))
story.append(pillar_block(
5, "Use Internships as Your Entry Ramp",
"A structured internship is the fastest legitimate way to gain the \u201cUAE experience\u201d employers ask for.",
[
"Apply to G42 and Hub71-affiliated internship / early-career tracks, both open to non-UAE Nationals",
"Consider one short freelance project for a UAE-based client (via Upwork or LinkedIn) to add a genuine regional line to your CV",
"Treat a 3\u20136 month internship as a real conversion opportunity, not a stopgap",
],
None
))
story.append(pillar_block(
6, "Work the Right Platforms and Agencies",
"Different channels surface different tiers of role — use all of them, not just one.",
[
"LinkedIn Jobs: the dominant channel for tech roles in the Gulf",
"Bayt, GulfTalent, Naukrigulf, and Indeed UAE as secondary channels",
"Register with 2\u20133 Dubai/Abu Dhabi IT recruitment agencies that place juniors into QA, support, or junior developer roles",
],
None
))
story.append(pillar_block(
7, "Network Like It's a Referral-First Market \u2014 Because It Is",
"Most UAE tech hires happen through warm introductions, not cold applications.",
[
"Attend GITEX Global and local Dubai/Abu Dhabi tech meetups when possible",
"Send 5 personalised LinkedIn connection requests per week to engineers/hiring managers at target companies (template on page 5)",
"Reach out to university alumni already working in the UAE for advice and referrals",
],
None
))
story.append(pillar_block(
8, "Plan Around the Visa Reality",
"Understand the mechanics before you commit time to a particular route.",
[
"Standard route: an employer sponsors your UAE residence visa once you have a signed offer",
"Cold sponsorship from abroad with zero experience is the hardest version of this path",
"If you can legally enter on a visit, student, or dependent visa, being physically present for interviews and networking meaningfully improves your odds",
],
"General orientation only \u2014 verify current requirements with official UAE channels (ICP/GDRFA) or a licensed immigration advisor."
))
story.append(PageBreak())
# =====================================================================
# EMPLOYER TARGET LIST
# =====================================================================
story.append(banner("Where to Focus: Target Employer Categories"))
story.append(Spacer(1, 8))
employer_rows = [
["Consumer tech & product", "Careem, Noon, Talabat, Property Finder",
"Larger junior/graduate intakes and more structured onboarding"],
["Sovereign AI & deep tech", "G42, Presight, Inception, M42",
"Run paid internship and early-career tracks open to all nationalities"],
["Startup ecosystem", "Hub71 (Abu Dhabi) and Dubai Internet City portfolio companies",
"Faster hiring, hands-on ownership, internship-to-full-time pipelines"],
["Fintech", "DIFC / ADGM licensed fintechs",
"Growing junior data and dev demand in an English-first environment"],
["Consulting & advisory", "Deloitte, PwC, EY, KPMG (technology practice)",
"Structured graduate schemes with training built in"],
["IT services & integrators", "Regional systems integrators and outsourcing firms",
"More open to freshers; a good source of your first \u201cUAE experience\u201d line"],
]
story.append(styled_table(
["Category", "Examples", "Why it's a good fit"],
employer_rows,
[4.0 * cm, 5.6 * cm, CONTENT_W - 9.6 * cm]
))
story.append(Spacer(1, 14))
# =====================================================================
# CERTIFICATIONS TABLE
# =====================================================================
story.append(banner("Certification Guide by Track"))
story.append(Spacer(1, 8))
cert_rows = [
["Data Analyst", "Google Data Analytics Certificate",
"Widely recognised, project-based, realistic to finish in a few weeks"],
["Data / AI", "Microsoft Azure Data Fundamentals (DP-900) \u2192 DP-100",
"Azure certifications increasingly appear as explicit requirements in UAE data postings"],
["AI Developer", "AWS or Azure ML fundamentals certification",
"Signals you can move a model toward production, not just train one"],
["Software Developer", "AWS Certified Cloud Practitioner + one language/framework cert",
"Cloud fundamentals are close to a universal baseline requirement now"],
]
story.append(styled_table(
["Track", "Recommended certification", "Why it matters"],
cert_rows,
[3.4 * cm, 6.0 * cm, CONTENT_W - 9.4 * cm]
))
story.append(PageBreak())
# =====================================================================
# 90 DAY TIMELINE
# =====================================================================
story.append(banner("90-Day Timeline"))
story.append(Spacer(1, 8))
timeline_rows = [
["Foundation", "Weeks 1\u20133",
"Choose track; rebuild CV/LinkedIn; start Project 1; enrol in certification",
"Draft CV live, LinkedIn updated, Project 1 underway"],
["Build & Apply", "Weeks 4\u20136",
"Finish 2 projects; complete certification; start applying to internships and junior roles",
"2 live projects, certification earned, 15+ applications sent"],
["Network & Interview", "Weeks 7\u20139",
"Attend events/meetups; run LinkedIn outreach; prepare for interviews",
"20+ new contacts, mock interviews completed"],
["Convert & Close", "Weeks 10\u201312",
"Follow up on every open application; negotiate offers; reassess if needed",
"Offer(s) in hand, or a refined plan for the next 90 days"],
]
story.append(styled_table(
["Phase", "Weeks", "Focus", "Deliverables"],
timeline_rows,
[3.4 * cm, 2.2 * cm, 6.2 * cm, CONTENT_W - 11.8 * cm]
))
story.append(Spacer(1, 16))
# =====================================================================
# NETWORKING TEMPLATES
# =====================================================================
story.append(banner("Networking Message Templates"))
story.append(Spacer(1, 8))
story.append(Paragraph("Connection request note:", h2_style))
story.append(Paragraph(
"\u201cHi [Name], I'm a recent [degree] graduate working toward a [Data Analyst / Software Developer] "
"role in the UAE. I really admire the work your team is doing at [Company] and would value any advice "
"on breaking into the market. Would you be open to a quick chat?\u201d",
body_italic))
story.append(Spacer(1, 6))
story.append(Paragraph("Follow-up after connecting:", h2_style))
story.append(Paragraph(
"\u201cThanks for connecting, [Name]. I've been building [one-line project description] to prepare for "
"data/dev roles in the UAE. If you ever hear of junior openings, or have 10 minutes for a couple of "
"questions about how your team hires, I'd really appreciate it.\u201d",
body_italic))
story.append(Spacer(1, 10))
story.append(Paragraph(
"Send around 5 of these per week to people at your shortlisted target companies. Personalise the "
"bracketed sections every time — generic copy-paste messages are easy to spot and easy to ignore.",
body_style))
story.append(PageBreak())
# =====================================================================
# CV CHECKLIST
# =====================================================================
story.append(banner("CV & LinkedIn Checklist"))
story.append(Spacer(1, 8))
for item in [
"One page, single column, no tables, graphics, or photo",
"Standard section headers: Summary, Skills, Projects, Education, Certifications",
"Every project bullet states what you built, the tools used, and a measurable outcome",
"Visa/relocation status stated clearly near the top",
"File named FirstName_LastName_CV.pdf",
"LinkedIn headline and About section match your target role and CV keywords",
]:
story.append(check(item))
story.append(Spacer(1, 14))
# =====================================================================
# MASTER TRACKER
# =====================================================================
story.append(banner("Master Action Tracker"))
story.append(Spacer(1, 8))
tracker_rows = [
["\u25a1", "Rebuild CV and LinkedIn to UAE/ATS format", "Week 1"],
["\u25a1", "Choose primary track (Data Analyst / AI Developer / Software Developer)", "Week 1"],
["\u25a1", "Start Project 1", "Weeks 1\u20132"],
["\u25a1", "Enrol in certification", "Week 2"],
["\u25a1", "Finish Project 1", "Week 3"],
["\u25a1", "Start Project 2", "Weeks 3\u20134"],
["\u25a1", "Apply to G42 / Hub71 internship tracks", "Week 4"],
["\u25a1", "Finish Project 2", "Week 6"],
["\u25a1", "Complete certification", "Weeks 5\u20136"],
["\u25a1", "Apply to 15+ junior roles across platforms", "Weeks 4\u20136"],
["\u25a1", "Start LinkedIn outreach, 5 messages/week", "Week 4 onward"],
["\u25a1", "Attend at least 1 tech event or meetup", "Weeks 7\u20139"],
["\u25a1", "Complete mock interview practice", "Weeks 8\u20139"],
["\u25a1", "Follow up on every open application", "Week 10"],
["\u25a1", "Reassess and adjust the plan", "Week 12"],
]
# Use plain checkbox glyph fallback: replace with ASCII if font can't render it
tracker_rows = [["[ ]"] + r[1:] for r in tracker_rows]
rows_for_table = [[Paragraph("Done", table_header_style), Paragraph("Action", table_header_style), Paragraph("Target", table_header_style)]]
for r in tracker_rows:
rows_for_table.append([
Paragraph(r[0], table_cell_style),
Paragraph(r[1], table_cell_style),
Paragraph(r[2], table_cell_style),
])
tracker_table = Table(rows_for_table, colWidths=[1.6 * cm, CONTENT_W - 1.6 * cm - 3.2 * cm, 3.2 * cm], repeatRows=1)
tstyle = [
("BACKGROUND", (0, 0), (-1, 0), TEAL),
("BOX", (0, 0), (-1, -1), 0.6, colors.HexColor("#C9D8D6")),
("INNERGRID", (0, 0), (-1, -1), 0.5, colors.HexColor("#C9D8D6")),
("VALIGN", (0, 0), (-1, -1), "TOP"),
("LEFTPADDING", (0, 0), (-1, -1), 6),
("RIGHTPADDING", (0, 0), (-1, -1), 6),
("TOPPADDING", (0, 0), (-1, -1), 5),
("BOTTOMPADDING", (0, 0), (-1, -1), 5),
]
for i in range(1, len(rows_for_table)):
if i % 2 == 0:
tstyle.append(("BACKGROUND", (0, i), (-1, i), LIGHT_BG))
tracker_table.setStyle(TableStyle(tstyle))
story.append(tracker_table)
# =====================================================================
# FOOTER / PAGE NUMBERS
# =====================================================================
def draw_footer(c: canvas.Canvas, doc):
c.saveState()
c.setStrokeColor(colors.HexColor("#C9D8D6"))
c.setLineWidth(0.5)
c.line(MARGIN, 1.4 * cm, PAGE_W - MARGIN, 1.4 * cm)
c.setFont("Helvetica", 8.5)
c.setFillColor(MUTED)
c.drawString(MARGIN, 1.0 * cm, "UAE Tech Job Search Plan")
c.drawRightString(PAGE_W - MARGIN, 1.0 * cm, f"Page {doc.page}")
c.restoreState()
doc = SimpleDocTemplate(
"/home/claude/plan/UAE_Tech_Job_Search_Plan.pdf",
pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=2.2 * cm, bottomMargin=2.0 * cm,
title="UAE Tech Job Search Plan",
author="Claude",
)
doc.build(story, onFirstPage=draw_footer, onLaterPages=draw_footer)
print("PDF built successfully.")