Khurram Badar / Archive / Courses / Zong's 5G transformation in Pakistan

Zong's 5G transformation in Pakistan

guide · 2026-08-08 · 5882 words · Khurram Badar · for gen-z, adults, professionals · intro

/usr/bin/env python3 """Plain-language rea...

ai · pakistan

#!/usr/bin/env python3
"""Plain-language reader's guide to 5G in Pakistan, centred on the customer."""

from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.units import mm
from reportlab.lib.enums import TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (SimpleDocTemplate, Paragraph, Spacer, Table,
TableStyle, PageBreak, HRFlowable)

OUT = "/mnt/user-data/outputs/5G_in_Pakistan_What_It_Means_For_Customers.pdf"

INK = colors.HexColor("#1A1A1A")
GREY = colors.HexColor("#5A5A5A")
LIGHT = colors.HexColor("#8A8A8A")
RULE = colors.HexColor("#D5D5D0")
PAPER = colors.HexColor("#F4F2EC")
RED = colors.HexColor("#A83232")
GREEN = colors.HexColor("#2E6B4F")
BLUE = colors.HexColor("#2B5478")

def S(name, **kw):
b = dict(fontName="Helvetica", fontSize=10, leading=15, textColor=INK,
alignment=TA_JUSTIFY, spaceAfter=8)
b.update(kw)
return ParagraphStyle(name, **b)

body = S("body")
lead = S("lead", fontSize=11.4, leading=17, textColor=GREY, spaceAfter=10)
big = S("big", fontName="Helvetica-Bold", fontSize=17, leading=21,
textColor=INK, alignment=TA_LEFT, spaceBefore=2, spaceAfter=4)
sec = S("sec", fontName="Helvetica-Bold", fontSize=12.4, leading=16,
textColor=INK, alignment=TA_LEFT, spaceBefore=15, spaceAfter=5)
sub = S("sub", fontName="Helvetica-Bold", fontSize=10.4, leading=14,
textColor=BLUE, alignment=TA_LEFT, spaceBefore=11, spaceAfter=4)
who = S("who", fontName="Helvetica-Bold", fontSize=11, leading=14.5,
textColor=INK, alignment=TA_LEFT, spaceBefore=13, spaceAfter=1)
whosub = S("whosub", fontName="Helvetica-Oblique", fontSize=9.2, leading=12.5,
textColor=LIGHT, alignment=TA_LEFT, spaceAfter=6)
bull = S("bull", leftIndent=12, bulletIndent=2, spaceAfter=4)
tiny = S("tiny", fontSize=8.4, leading=11.8, textColor=LIGHT)
cell = S("cell", fontSize=8.6, leading=11.6, alignment=TA_LEFT, spaceAfter=0)
cellb = S("cellb", fontName="Helvetica-Bold", fontSize=8.6, leading=11.6,
alignment=TA_LEFT, spaceAfter=0)
cellw = S("cellw", fontName="Helvetica-Bold", fontSize=8.8, leading=11.8,
textColor=colors.white, alignment=TA_LEFT, spaceAfter=0)

story = []

def p(t, st=body):
story.append(Paragraph(t, st))

def bullets(items):
for i in items:
story.append(Paragraph(i, bull, bulletText="\u2022"))
story.append(Spacer(1, 3))

def line(c=RULE, w=0.7, before=2, after=8):
story.append(Spacer(1, before))
story.append(HRFlowable(width="100%", thickness=w, color=c))
story.append(Spacer(1, after))

def box(head, text, accent=BLUE):
rows = [[Paragraph(head, ParagraphStyle("bh", fontName="Helvetica-Bold",
fontSize=9.2, leading=12.5,
textColor=accent, spaceAfter=4))],
[Paragraph(text, ParagraphStyle("bb", fontName="Helvetica",
fontSize=9.3, leading=13.4,
textColor=INK, alignment=TA_JUSTIFY))]]
t = Table(rows, colWidths=[166 * mm])
t.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, -1), PAPER),
("LINEBEFORE", (0, 0), (0, -1), 2.6, accent),
("LEFTPADDING", (0, 0), (-1, -1), 10),
("RIGHTPADDING", (0, 0), (-1, -1), 10),
("TOPPADDING", (0, 0), (0, 0), 8),
("BOTTOMPADDING", (0, 0), (-1, 0), 0),
("TOPPADDING", (0, 1), (-1, 1), 0),
("BOTTOMPADDING", (0, -1), (-1, -1), 8),
]))
story.append(Spacer(1, 4))
story.append(t)
story.append(Spacer(1, 10))

def table(data, widths, hdr=colors.HexColor("#26313C"), extra=None):
t = Table(data, colWidths=widths, repeatRows=1, hAlign="LEFT")
cmds = [("VALIGN", (0, 0), (-1, -1), "TOP"),
("LEFTPADDING", (0, 0), (-1, -1), 7),
("RIGHTPADDING", (0, 0), (-1, -1), 7),
("TOPPADDING", (0, 0), (-1, -1), 6),
("BOTTOMPADDING", (0, 0), (-1, -1), 6),
("BACKGROUND", (0, 0), (-1, 0), hdr),
("LINEBELOW", (0, 0), (-1, -1), 0.4, RULE),
("BOX", (0, 0), (-1, -1), 0.6, RULE)]
for r in range(1, len(data)):
if r % 2 == 0:
cmds.append(("BACKGROUND", (0, r), (-1, r), PAPER))
if extra:
cmds += extra
t.setStyle(TableStyle(cmds))
story.append(t)
story.append(Spacer(1, 9))

------------------------------- COVER ------------------------------------

p("This guide is written for an ordinary reader, not for a telecom company. "
"There is a lot of noisy coverage about 5G in Pakistan right now, most of it "
"either advertising or a rewritten press release. What is missing is a "
"straight answer to the only question most people actually have: <b>will my "
"internet get better, when, and what will it cost me?</b>", lead)

p("The short version is that a small number of people in a few big cities will "
"notice a real difference in 2026. Most people will notice nothing for a "
"while, and some will notice their bill going up before their service gets "
"better. That is not cynicism - it follows directly from what has actually "
"been built, which this guide walks through.", lead)

box("How to use this",
"Sections 1 to 3 explain what happened and how the technology works, in "
"everyday language. Section 4 is the main part: nine short profiles of "
"different kinds of customer, so you can skip to whichever one sounds like "
"you. Sections 5 to 8 cover what you pay, why service breaks, what your "
"rights are, and a realistic timeline. Nothing here requires any technical "
"background.")

story.append(PageBreak())

--------------------------- 1. WHAT HAPPENED -----------------------------

p("For years the government said 5G was coming and it kept not arriving. In "
"March 2026 it finally did, in this sequence.", body)

p("On 10 March, the government auctioned radio frequencies to the mobile "
"companies. Think of these frequencies as lanes on a motorway: the more lanes "
"a company owns, the more traffic it can carry at once. Pakistan sold 480 MHz "
"worth of lanes and raised about USD 507 million. Jazz bought the most (190 "
"MHz), Ufone next (180 MHz), and Zong the least (110 MHz).", body)

p("This roughly tripled the country's supply of lanes. The regulator later told "
"Parliament that Pakistan's total available spectrum went from 274 MHz to 754 "
"MHz after the auction. That is the single most important number in this "
"whole story, and it has almost nothing to do with 5G handsets - it means "
"there is now far more room on the network for everyone, including people "
"still on 4G.", body)

p("On 19 March the licences were formally issued. Zong switched on 5G in more "
"than 16 cities the same day. Jazz switched on around 180 locations across "
"Islamabad, the provincial capitals and a few other cities. Ufone got its "
"licence but did not launch immediately.", body)

box("The detail nobody advertised",
"In July 2026 the head of the regulator told a parliamentary committee "
"that 5G had been launched in 22 cities <b>using existing mobile towers and "
"existing network infrastructure</b>, and that no new infrastructure had yet "
"been deployed for it. In other words, the launch you saw advertised was "
"largely a software and frequency change on towers that were already there. "
"That is not fraud - it is the normal first step - but it explains why so "
"many people saw the advertising and felt no difference.", RED)

p("Here is where the build actually stood in early August 2026, according to "
"regulator figures.", body)

table([[Paragraph("Operator", cellw), Paragraph("5G sites live", cellw),
Paragraph("Share", cellw), Paragraph("Owned by", cellw)],
[Paragraph("Jazz", cellb), Paragraph("689", cell), Paragraph("60.7%", cell),
Paragraph("VEON (Amsterdam, listed in New York)", cell)],
[Paragraph("Zong", cellb), Paragraph("338", cell), Paragraph("29.8%", cell),
Paragraph("China Mobile (Chinese state-owned)", cell)],
[Paragraph("Ufone", cellb), Paragraph("109", cell), Paragraph("9.6%", cell),
Paragraph("PTCL group (Etisalat and Pakistani state)", cell)],
[Paragraph("Total", cellb), Paragraph("1,136", cellb),
Paragraph("23 cities", cellb), Paragraph("As at 4 August 2026", cell)]],
[26 * mm, 26 * mm, 24 * mm, 90 * mm])

p("To put 1,136 in perspective: Pakistan has roughly 58,000 mobile towers. So "
"about two out of every hundred sites in the country currently carry 5G. And "
"they are heavily bunched - Karachi, Lahore, Islamabad and Faisalabad account "
"for around 72 percent of them.", body)

p("The last thing worth knowing is that the market itself is being reshuffled "
"at the same time. PTCL bought Telenor Pakistan and is merging it with Ufone. "
"That turns four big mobile companies into three. As of June 2026 Jazz had "
"about 36 percent of subscribers and Zong about 27 percent, with Telenor and "
"Ufone together making up roughly another 36 percent - which means the merged "
"company will be level with Jazz and Zong will drop to third place.", body)

story.append(PageBreak())

--------------------------- 2. HOW IT WORKS ------------------------------

p("You can follow the rest of this guide with four ideas. No engineering "
"knowledge needed.", body)

p("Spectrum is the lanes", sub)
p("Radio spectrum is the invisible airspace your phone uses. Companies rent "
"slices of it from the government. Low frequencies travel far and go through "
"walls but carry less data - good for villages and for indoor coverage. High "
"frequencies carry huge amounts of data but only over short distances - good "
"for crowded city centres. This matters more than you would think: <b>Zong "
"bought only high and middle frequencies. Jazz also bought low frequency at "
"700 MHz.</b> That single difference means Jazz can eventually reach small "
"towns and rural areas with 5G in a way Zong currently cannot.", body)

p("The tower is the on-ramp; the fibre behind it is the motorway", sub)
p("This is the part almost every article skips, and it explains most of the "
"disappointment people feel. A mobile tower does not create internet. It "
"relays it from a cable buried in the ground. If that cable is thin, it does "
"not matter how fast the tower can talk to your phone - the traffic jams "
"behind it.", body)
p("In Pakistan, only about 17.9 percent of mobile towers are connected by "
"fibre. The rest use older, slower links. This is why you can stand under a "
"tower with full signal bars, see a fast speed reading, and still find that "
"nothing loads properly at nine in the evening. The bars measure the last "
"hundred metres. The congestion is a kilometre behind you.", body)

box("The single best explanation for bad internet in Pakistan",
"Not the towers. Not 5G. Not your phone. It is that four out of five towers "
"in the country are not connected to fibre, and the fibre that does exist "
"is expensive to lay because import duties on fibre cable have run around "
"60 to 67 percent and because getting permission to dig is a fight with "
"property owners and local authorities.", RED)

p("Fixed wireless access: home internet without a cable", sub)
p("Because laying fibre to every house is slow and expensive, the companies "
"want to sell you home internet delivered over the mobile network instead. "
"You get a small router that sits in your window and picks up the 5G signal, "
"and it feeds Wi-Fi to your house. This is called fixed wireless access, or "
"FWA, and Zong in particular has been pushing it.", body)
p("In most countries FWA is the second-best option, worse than fibre. In "
"Pakistan it is often <i>better</i> than the fixed alternative, because "
"Pakistan's fixed broadband is genuinely slow. Independent measurement over "
"the first quarter of 2026 found the fastest fixed broadband network in the "
"country delivered about 21.4 Mbps on download. A good 5G connection beats "
"that comfortably. That is the real opportunity here, and it is the most "
"underreported part of the whole 5G story.", body)

p("But every home router eats capacity that phones would otherwise use", sub)
p("Here is the catch. FWA and your mobile phone draw from the same tower. A "
"household streaming video all evening consumes far more than a person "
"scrolling on a phone. So the number of homes a company can sign up is capped "
"by how many towers it has, not by how many people want the service.", body)
p("This is why you should treat announcements about home internet with some "
"caution. If a company sells unlimited home plans aggressively on a small "
"number of towers, the service will degrade for everyone on that tower - "
"including its mobile customers. Sensible operators sell capped plans. Watch "
"which approach yours takes.", body)

story.append(PageBreak())

--------------------------- 3. THE PLAYERS -------------------------------

p("It is worth knowing who you are actually buying from, because ownership "
"shapes behaviour.", body)

p("Zong", sub)
p("Legally CMPak. Wholly owned by China Mobile, the Chinese state-controlled "
"operator, and its first venture outside China. It entered Pakistan in 2007 "
"with about 2 percent of the market and now has roughly 27 percent and around "
"54 million customers. Its network equipment comes largely from Huawei and "
"ZTE. It was first to trial 5G in Pakistan back in 2019 and first to launch "
"commercially in 2026. It publishes very little financial information about "
"its Pakistan business, so most claims about how it is doing cannot be "
"independently checked.", body)

p("Jazz", sub)
p("Legally PMCL. It used to be called Mobilink, which is why people still say "
"that, but Mobilink has not been the owner since the 2017 rebrand - the owner "
"is VEON, a company headquartered in Amsterdam and listed in New York and "
"Amsterdam. The local group now calls itself JazzWorld. It is the largest "
"operator, with over 75 million mobile customers, and it also owns JazzCash, "
"which is a very large payments business in its own right. Because VEON is "
"publicly listed, Jazz's numbers are reported every three months and can be "
"checked.", body)

p("Ufone and Telenor, becoming one company", sub)
p("Both now sit under PTCL, the old national telephone company. They are being "
"merged. This combination is going to matter a great deal, because PTCL owns "
"the country's main fibre network and already sells home broadband to over "
"900,000 households. It also bought the largest share of the high-frequency "
"spectrum best suited to home wireless internet. It is currently last in 5G "
"towers and holds the strongest long-term position - a contradiction worth "
"keeping in mind when you read rankings.", body)

box("A word about the sovereignty question",
"Both Zong and Jazz sell business cloud services and both advertise that "
"your data stays inside Pakistan. That claim is about <i>where the servers "
"sit</i>. It is not a claim about <i>who owns the company holding your "
"data</i>. Zong is Chinese state-owned; Jazz is owned by an Amsterdam and "
"New York listed group. For an ordinary consumer this is irrelevant. For a "
"hospital, a bank, a school system or a government department, it is a "
"separate question that deserves a separate answer, and it is one that "
"marketing material tends to blur.", GREEN)

story.append(PageBreak())

--------------------------- 4. THE CUSTOMERS -----------------------------

p("This is the heart of it. Find the description closest to you.", body)

--- 1

--- 2

--- 3

--- 4

story.append(PageBreak())

--- 5

--- 6

--- 7

--- 8

--- 9

story.append(PageBreak())

--------------------------- 5. WHAT YOU PAY ------------------------------

p("A lot of anger at mobile companies is really anger at the tax structure, so "
"it is worth being precise about where your money goes. Here is what happens "
"to a Rs 100 prepaid recharge.", body)

table([[Paragraph("Step", cellw), Paragraph("Amount", cellw),
Paragraph("What it is", cellw)],
[Paragraph("You pay", cellb), Paragraph("Rs 100.00", cell),
Paragraph("The recharge you buy", cell)],
[Paragraph("Less advance income tax at 15%", cell),
Paragraph("- Rs 13.04", cell),
Paragraph("Deducted immediately, before the credit reaches your SIM. "
"Collected for the FBR, not kept by the operator.", cell)],
[Paragraph("Less sales tax at 19.5%", cell), Paragraph("- Rs 14.19", cell),
Paragraph("Charged on what remains as you use it, on calls, SMS and "
"data", cell)],
[Paragraph("You can actually use", cellb), Paragraph("Rs 72.77", cellb),
Paragraph("An effective tax burden of roughly 34.5 percent", cellb)]],
[56 * mm, 26 * mm, 84 * mm])

p("So when a package feels smaller than the price on the poster, that is "
"usually the tax structure rather than the operator cheating you. It is also "
"why affordability, not coverage, is now the main barrier to people getting "
"online in Pakistan: around 40 percent of people who <i>have</i> mobile "
"broadband coverage do not actively use mobile internet, and smartphone "
"ownership sits at roughly half the population.", body)

p("That said, operators are not blameless on price. Package prices have risen "
"noticeably, and the industry has been openly lobbying for tax relief while "
"simultaneously raising tariffs. Both things are true at once: the tax burden "
"is genuinely punitive, and prices have gone up faster than service quality.", body)

--------------------------- 6. WHY IT BREAKS -----------------------------

p("If your internet is bad, one of these five is almost certainly the reason, "
"and only one of them is about 5G.", body)

bullets([
"<b>Fibre behind the tower.</b> Only about 17.9 percent of towers are "
"fibre-connected. This is the biggest single cause and the slowest to fix.",
"<b>Electricity.</b> The regulator told Parliament that load shedding of up "
"to ten hours daily in some areas significantly degrades telecom service. "
"Towers run on backup power that was never designed for outages that long, "
"and diesel is expensive.",
"<b>No new towers yet for 5G.</b> The launch used existing infrastructure. "
"Real densification - more sites, closer together - is the 2026 to 2027 "
"job, not something already done.",
"<b>Device gap.</b> Under 5 percent of handsets in use support 5G, so even "
"where the network is live, most people cannot reach it.",
"<b>Congestion at peak hours.</b> Everyone is online between roughly 8pm "
"and midnight. The new spectrum genuinely helps here, and this is where "
"improvement should appear first.",
])

story.append(PageBreak())

--------------------------- 7. YOUR RIGHTS -------------------------------

p("Pakistan has a functioning complaints system that most people do not use. "
"The regulator publishes monthly complaint data by operator, and the "
"resolution rates are genuinely high.", body)

p("In January 2026 the regulator received 6,054 consumer complaints and about "
"95 percent were resolved. Jazz drew the most (2,292), Zong second (1,093, of "
"which 97.5 percent were resolved). By March the monthly total had fallen to "
"4,842, with Jazz again highest at 1,892 and Zong at 804. Jazz topping the "
"list every month partly reflects that it has the most customers - complaint "
"counts should be read against subscriber numbers, not on their own.", body)

p("The more revealing measure is a service quality survey the regulator ran "
"covering late 2025. Jazz came out best, and was the only operator to meet "
"the overall problem resolution benchmark. Zong performed poorly on speed of "
"response, resolving only about 19 percent of problems within 24 hours. Most "
"operators fell short on problem resolution overall.", body)

box("A finding that deserves more attention than it got",
"The same regulator survey found that emergency helpline numbers were "
"either unavailable or wrongly routed across networks in Quetta, Peshawar, "
"Multan, Faisalabad and Gilgit-Baltistan. In one case, child protection "
"calls originating in Gilgit-Baltistan were being routed to Muzaffarabad. "
"If you live in these areas, it is worth testing that emergency numbers "
"connect correctly from your own handset rather than assuming they do.", RED)

p("Operators have also been penalised on consumer protection grounds. In 2026 "
"the regulator fined the four operators a combined total of around Rs 740 "
"million over SIMs issued and activated against people's national identity "
"card numbers without their knowledge or presence - Zong drew the largest "
"single share at about Rs 155.6 million, with Jazz, Telenor and Ufone at "
"about Rs 116.7 million each.", body)

p("What this means for you in practice", sub)
bullets([
"Complain to your operator first and keep the reference number. Operators "
"resolve most complaints, and the regulator's process expects you to have "
"tried this first.",
"If unresolved, escalate to the PTA. The published resolution rates suggest "
"escalation works more often than people assume.",
"Check periodically which SIMs are registered against your CNIC. Given the "
"scale of the fines above, this is not a theoretical risk.",
"Test emergency numbers from your own phone if you live in the cities named "
"above.",
"If you are being billed for a speed tier you never receive at peak hours, "
"that is a service quality complaint, not just bad luck.",
])

story.append(PageBreak())

--------------------------- 8. TIMELINE ----------------------------------

table([[Paragraph("When", cellw), Paragraph("What is likely", cellw),
Paragraph("Who feels it", cellw)],
[Paragraph("Rest of 2026", cellb),
Paragraph("Extra spectrum absorbed into 4G, easing evening congestion. "
"5G site counts climb - Zong targeting 1,000+ for the year, "
"Jazz signalling around 2,500 by December. Coverage stays "
"concentrated in big cities.", cell),
Paragraph("4G smartphone users in cities. This is the year's real, "
"quiet improvement.", cell)],
[Paragraph("2027", cellb),
Paragraph("Spectrum payments fall due for the operators. iPhone support "
"expected to arrive. Home wireless internet becomes a serious "
"product if fibre backhaul improves. Merged Ufone-Telenor "
"starts competing properly.", cell),
Paragraph("iPhone owners, households wanting home internet, and anyone "
"hoping prices fall - which they may not, given the payments "
"due.", cell)],
[Paragraph("2028 and beyond", cellb),
Paragraph("Meaningful 5G outside the largest cities, but only if fibre "
"duties and right-of-way reforms actually take effect and "
"power supply to towers stabilises.", cell),
Paragraph("Smaller cities and towns. Villages remain a 4G story for "
"the foreseeable future.", cell)]],
[30 * mm, 78 * mm, 58 * mm])

p("The two things that would change this timeline for the better are not "
"telecom decisions at all. They are the proposed cut in import duties on "
"fibre cable, which has been under consideration at a reduction from around "
"60 percent to roughly 5 percent, and the removal of right-of-way charges for "
"laying cable. If those land properly, everything above accelerates. If they "
"stall, everything above slips.", body)

--------------------------- 9. READING CLAIMS ----------------------------

table([[Paragraph("When you see this", cellw),
Paragraph("What it usually means", cellw)],
[Paragraph("\"Speeds up to 1.4 Gbps\"", cell),
Paragraph("A test result under ideal conditions with no other users. "
"Real-world figures near a tower have been reported around "
"300 Mbps, and most people will see far less.", cell)],
[Paragraph("\"Live in 16 cities\" or \"22 cities\"", cell),
Paragraph("At least one site is switched on in each. It does not mean "
"the city is covered. Check the coverage map for your own "
"neighbourhood.", cell)],
[Paragraph("\"Transforming everything for Pakistan\"", cell),
Paragraph("About 2 percent of the country's towers currently carry 5G "
"and under 5 percent of handsets can use it.", cell)],
[Paragraph("\"Data stays in Pakistan\"", cell),
Paragraph("True as a statement about server location. Says nothing "
"about who owns the company holding the data.", cell)],
[Paragraph("\"1,000 sites this year\"", cell),
Paragraph("Often counts upgraded existing sites as well as new ones. "
"Worth asking which.", cell)],
[Paragraph("A podcast or video featuring company executives", cell),
Paragraph("Frequently sponsored content. Useful for understanding what "
"a company wants to do; not a source for whether it has done "
"it. Regulator data is.", cell)]],
[56 * mm, 110 * mm])

line(RULE, 0.7, 6, 8)

p("Where these figures come from", sec)
p("Deployment counts, complaint statistics, service quality findings, spectrum "
"totals and penalty figures come from the Pakistan Telecommunication "
"Authority and from testimony to the National Assembly Standing Committee on "
"Information Technology and Telecommunication. Company figures come from "
"operator disclosures and, in Jazz's case, VEON's quarterly reporting. Fixed "
"broadband speed measurement is from Opensignal's Pakistan report covering "
"the first quarter of 2026. Tax calculations follow published breakdowns of "
"prepaid recharge deductions. Additional reporting from Dawn, the Express "
"Tribune, Business Recorder, TechJuice, PhoneWorld, ProPakistani, Developing "
"Telecoms and TelecomTV.", tiny)
p("Figures reflect the position as at 8 August 2026 and will move. Where this "
"guide gives a judgement rather than a fact - for example about what is "
"likely to happen in 2027 - it is written as a judgement and you should treat "
"it as one.", tiny)

------------------------------ RENDER ------------------------------------

doc = SimpleDocTemplate(OUT, pagesize=A4,
leftMargin=20 * mm, rightMargin=20 * mm,
topMargin=20 * mm, bottomMargin=19 * mm,
title="5G in Pakistan: what it actually means for the "
"people paying for it",
author="Plain-language guide, August 2026")
doc.build(story, onFirstPage=deco, onLaterPages=deco)
print("written:", OUT)

← HOD course development with framework alignmentWeb Dev Published Mobile Developer →
Two years of working thought, indexed.
Ask me to present it in your conference room — WhatsApp +971 55 623 9111
Book Session →