We design and build systems that have to work offline, pass an accessibility
audit, and speak more than one language — including
right‑to‑left.
WEBWorx builds the parts most teams treat as someone else's problem: the disconnected
path, the screen-reader path, the Arabic path, the audit trail. Two decades of that work
has been delivered inside Government of Canada programmes; the
current products carry it further — a casualty-care
application that runs with no network at all, and a school system operating in three
languages.
Both are ours from data model to deployment — architecture, interface, accessibility,
translation, test suite, CI and hosting. They are the clearest statement of what
WEBWorx does.
An offline-first progressive web application for casualty care and
transport documentation. Field responders capture patient identity, injuries marked on
an anatomical body chart, vitals and treatments, then sign off and hand over to a
hospital as an HL7 FHIR R4 bundle — with no connectivity required at
any point.
Works at zero signal. Records live on the device in IndexedDB; the service worker keeps the whole application available offline after first load.
Encrypted at rest. AES-256-GCM through WebCrypto, with the key derived from a passphrase and held only in memory — an exported backup is unreadable without it.
Seven languages, three right-to-left. English, French, Arabic, Spanish, Farsi, Swahili and Urdu, with translation that works offline.
Optional convergence. Devices sharing a self-hosted server merge through a conflict-aware operation log — never last-write-wins, and switched off by default.
Deploys two ways. One container image serves either an organisation server with PostgreSQL and automatic TLS, or a field kit on Raspberry Pi class hardware with no internet at all.
Test files
223
Browser E2E
~40
CI workflows
9
Languages
7
React 18
TypeScript
Vite
Dexie / IndexedDB
Workbox
Fastify 5
PostgreSQL
HL7 FHIR R4
WebCrypto
Playwright
axe-core
Docker
Prototype status: not a medical device and not for clinical use.
A complete school information system for an Ontario JK–8 school of
roughly 600 students: enrolment, attendance, gradebook, assessment, timetabling,
discipline, health office, fees and statutory filings — plus a separate parent portal
on the public internet. Interface in English, French and Arabic with
full right-to-left support.
Roles decide what exists. A bursar is never offered a class register; a teacher sees one class. Access is shaped by role, not hidden by the interface.
Money needs two people. A fee entered by one person is approved by another — separation of duties enforced in the data model, not in a policy document.
The parent portal is a separate build. The internet-facing surface ships its own bundle carrying no court order, no medical note, and no other family's child.
Ten jobs run unattended, and something watches them. Backups with a restore check, audit-chain verification, retention purges, statutory filings and instalment runs — with a health board that reports what did not send.
Arabic that survives printing. Report cards are generated as PDFs with Arabic properly shaped and bidirectional text resolved, not flattened to an image.
Modules
20
Test modules
112
Scheduled jobs
10
Languages
3
Django 5.2
DRF
PostgreSQL
React 18
TypeScript
Vite
WeasyPrint
RFC 6238 TOTP
mypy
ruff
Gunicorn
Ontario is the reference edition; other jurisdictions are added as edition profiles.
02 — Capabilities
What WEBWorx designs and builds
Depth is stated honestly. Specialist means work most practitioners do not take
on; applied means shipped and working, without claiming mastery.
Our strongest area. Offline is not a cache bolted on late — it is the baseline the application is designed against, with connectivity treated as the optional extra.
Durable local storage — IndexedDB through Dexie, with tests running against fake-indexeddb so the offline path is covered in CI rather than assumed.
Application shell — Workbox via vite-plugin-pwa, installable to a home screen; elsewhere a hand-rolled service worker and web manifest with no tooling at all.
Multi-device convergence — a conflict-aware operation-log merge, explicitly not last-write-wins, default-off and gated behind a PIN-protected admin panel.
Deployment realism — one image, two profiles: a VPS with PostgreSQL and automatic TLS, or a field kit on Raspberry Pi class hardware with SQLite and LAN TLS.
Fifteen years of accessibility work across Government of Canada programmes — Common Look and Feel and WCAG 2.0 from 2011, GCWeb 17 and WCAG 2.1 AA today — and, less commonly, decisions that show how individual assistive technologies actually behave rather than knowledge of the success criteria alone.
Screen readers in the test plan since 2012 — at Natural Resources Canada, test cases were run through a screen reader to confirm a visually impaired user could finish the task, rather than checking the markup validated. Migrating departments off legacy Common Look and Feel onto WCAG was a repeated brief.
Assistive-technology-specific judgement — native <details> disclosure chosen over a scripted tree because it is keyboard and screen-reader correct with zero libraries, and an ARIA role deliberately not added because it would change NVDA's mode.
Four AT stacks verified — NVDA and JAWS on Windows, VoiceOver on macOS and iOS, TalkBack on Android.
Automated where automation is honest — axe-core assertions inside the browser end-to-end suite, with manual verification for everything it cannot see.
Programme-level remediation — led accessibility and usability remediation for a public portal serving thousands of users, aligned to Canada.ca and WCAG.
English, French, Arabic, Spanish, Farsi, Swahili and Urdu — three right-to-left. Bilingual English and French delivery under the Official Languages Act is routine; the multilingual RTL work goes well past it.
Right-to-left throughout, not merely mirrored — full RTL interfaces, and generated PDFs where Arabic is shaped and bidirectional text is resolved by the text engine.
Translation that survives disconnection — an in-house context-based i18n layer chosen over a library specifically so it works offline, with English fallback.
Localised media — narrated walkthroughs produced in three languages with captions delivered as separate .vtt tracks, so Arabic shaping can be switched off if it renders wrongly.
Multilingual static delivery — a six-language site with hreflang alternates in the sitemap and per-language canonical pages.
Around 500 TypeScript and TSX files across the product line, organised so the boundaries mean something. React 18 with Vite in three separate products — and no state-management library, no UI kit and no router package, because context and composition are sufficient here.
Deliberate layering — domain model and standards mapping live in a framework-free package, reusable unchanged by a future native client or the server.
Ports and adapters — a provincial health-record gateway written as an implementation of a port interface, not as calls scattered through the interface layer.
Bundle separation as a security boundary — a public portal built as a distinct bundle so the internet-facing surface ships less code and less data.
Type checking as a gate — tsc --noEmit across the root and every workspace before a build is allowed to proceed.
Django 5.2 and Django REST Framework carrying a genuinely complex domain, with fifteen years of database design behind it — logical and physical models, ERDs, Oracle and SQL Server, migration and reconciliation.
Domain decomposition — twenty applications, 185 migrations, PostgreSQL in production and SQLite for local development, each concern owning its own tables and rules.
Rules in the model, not the screen — separation of duties, role-scoped visibility and retention schedules enforced where they cannot be bypassed.
Unattended work that reports itself — scheduled jobs with a health board that surfaces what failed to run, and a restore check that proves the backup.
Legacy migration — SSIS packages moving legacy datasets into Dataverse with source-to-target mapping, transformation, validation and reconciliation.
The commercial core of the practice, and where the web skills above get applied under real constraint — a platform that renders your HTML for you, restricts what JavaScript may do, and still has to meet federal accessibility and official-languages obligations.
Public-facing portals — multi-step bilingual intake with conditional logic, file upload, CAPTCHA and full screen-reader support, on Liquid web templates over Dataverse.
A productised scaffold — a console script that extracts a form's schema straight from the maker environment, plus a generic controller and template, taking a Power Apps form to a compliant portal against a written checklist.
Integration beyond the defaults — Dataverse Web API and OData, FetchXML, custom APIs, Power Automate flows, and OpenAPI contracts authored for downstream consumers.
Custom interface controls — Power Apps Component Framework grid and field controls in TypeScript and React where the platform has no answer.
Not a security practice by title, but the security code shows the habits of people who have thought about failure modes: standards-conformant primitives, documented parameter choices, and a written argument for anything that could be got subtly wrong.
At-rest encryption — WebCrypto AES-256-GCM with PBKDF2-SHA-256 at the OWASP-recommended iteration floor; the derived key is non-extractable and memory-only.
Second factor written to the RFC — TOTP proved against the specifications' own published test vectors, with constant-time comparison, refusal of a replayed counter and a deliberately narrow drift window.
Tamper-evident audit — a hash-chained audit log with a verification command and a retention and destruction schedule.
Supply chain — CodeQL, secret scanning and a generated CycloneDX SBOM in CI, and a dependency count kept deliberately small.
Complete business applications in a single HTML file, running from the file system, with no build, no server and no dependencies. A real engineering constraint, chosen because the users are counter staff who should not have to install or maintain anything.
Defensive parsing — point-of-sale exports consumed as-is, with title blocks, repeated page headers, subtotal rows and pagination lines detected and discarded.
Print as a first-class output — A4 layouts reproducing the source system's own report, headers repeating per page, and the document title set so "Save as PDF" suggests a sensible file name.
Domain encoding — shop search tags decoded into product sizes, malformed tags audited, and corrections suggested back to the counter.
Local persistence and safe merge — retention across sessions, and multi-year imports merged by reference so re-importing overlapping exports cannot duplicate.
Testing is not decorative. The largest product carries 223 test files plus around forty browser end-to-end specifications, and exposes one command that runs the identical sequence CI runs — type check, every workspace's tests, the build, then the browser suite.
Layered suites — Vitest for unit and integration, Testing Library for components, Playwright for browser flows, in-memory PostgreSQL for service tests.
Nine GitHub Actions workflows on a single product — CI, end-to-end, CodeQL, secret scan, image publish, Pages deploy and automated code review.
Environment-aware deployment — staging and production shipping different server configuration, one cache-disabled and no-index, the other cached with security headers.
Builds with no install step — a hand-written static site generator using Node built-ins only, paired with smoke tests that run against the deployed URL.
03 — Approach
Six convictions, visible in the code
These recur across unrelated domains — emergency medicine, school administration,
federal service delivery, retail operations, household finance. Recurrence across
domains is what separates a conviction from a coincidence.
01
Offline is the architecture, not a feature
Every product assumes the network is missing and designs from there. Connectivity is
the optional enhancement, and the disconnected path is the one that gets the
tests.
In practice
A casualty-care application fully usable at zero connectivity, with sync default-off and admin-gated
A field-kit profile targeting Raspberry Pi class hardware with no internet at all
Business tools that run by double-clicking an HTML file over file://
A finance application with no server, no analytics and no network calls of any kind
02
Accessibility and language are substrate
Not a remediation pass at the end. Seven interface languages, three right-to-left, and
the hard parts handled rather than avoided.
Decisions are made per screen reader, not per specification.
In practice
Arabic shaped and bidi-resolved inside generated PDFs, not flattened to an image
A documented refusal to put role="button" on <summary> — it forces NVDA into focus mode
Verification across NVDA, JAWS, VoiceOver and TalkBack
axe-core assertions running inside the browser suite, not as a manual audit
03
A dependency is a security decision
Time-based one-time passwords written out rather than installed — because both RFCs
publish official test vectors, so the implementation can be proved against the
standard instead of trusted because it is popular.
The argument is committed beside the code.
In practice
A four-line requirements.txt, each line carrying a written justification
A static site generator using only Node built-ins, so the build needs no npm install
Single-file browser applications with zero dependencies, several thousand lines each
CodeQL, secret scanning and a CycloneDX SBOM wired in alongside the tests
04
Least privilege is designed in, then measured
A government portal was re-architected from client-side reads and a direct record POST
to server-rendered queries and a back-end flow. Required database table permissions
went from three tables with Create and Read to zero — recorded as a
before-and-after table rather than left implicit.
In practice
Client lookups replaced by server-side queries; record creation moved behind an automation flow
CAPTCHA verification moved server-side, removing another permission entirely
Custom validation retired in favour of the framework's native validator
05
Rules belong in the model
Anything that matters is enforced where it cannot be bypassed — not hidden by an
interface that a different route can reach around.
Roles determine what is offered, not merely what is permitted.
In practice
Separation of duties on money: entered by one person, approved by another
Access rights that differ between two children in the same family because a court order says so
A public portal built as a separate bundle so restricted data is never shipped to it
Hash-chained audit with a verification command and a retention schedule
06
The documentation argues, and admits things
Architecture documents ship as Markdown and PDF together with file inventories,
sequence diagrams, decision tables and a named section for known constraints and their
workarounds. Comments record where a default was wrong — one
type-checker note states that the defaults were inspecting about 3% of the tree, and
that enabling the stricter flag took it from 0 to 141 real errors.
In practice
Roadmaps stating, per feature, the specific check that closes it
A generated test catalogue committed from the suite's own output
Lint exclusions scoped to one file and one rule, with the reason written out
RFP-grade functional specifications, test artifacts and operational deliverables
04 — More work
Across sectors, from portals to shop floors
Federal service delivery, commercial sites, operations tooling and product discovery.
Filter by technology to see where each capability shows up.
Government of Canada · Health Canada
Public repos
SafePort — public service portals
Bilingual public-facing portals for the Travelling Public Programme: a General
Inspection report and a Ship Sanitation Inspection request, both multi-step forms with
conditional logic, file upload, CAPTCHA and comprehensive screen-reader support — on
Power Pages and Dataverse under WET4 / GCWeb and WCAG 2.1 AA.
Roughly 21,000 lines of hand-written client library sit behind these: validation, an
accessible date picker, a bilingual time selector, a universal announcer, a native
file bridge and session-timeout handling.
A public, read-only browse interface over five years of Health Canada cruise ship
inspection results — a two-tier tree of cruise lines, vessels and inspection history
with search, filtering and lazy loading.
The accessibility architecture is why this is here: native <details>
disclosure chosen over a scripted tree for zero-library correctness, and an ARIA role
deliberately omitted because it would flip NVDA into the wrong mode.
The SafePort work generalised into a reusable kit: a console script that extracts a
form's schema directly from the maker environment, a generic form controller, a Liquid
template and a written checklist that takes a Power Apps form to a WET4-compliant
portal.
Turning one delivery into a repeatable asset — bilingual message overrides,
cross-field rules, conditional visibility and pattern validation expressed as
configuration rather than code.
A bilingual Bootstrap 5 rebuild of a live commercial site, compiled from partials by a
hand-written static site generator that uses only Node built-ins —
the build requires no npm install at all.
The pipeline is the interesting part: push to main auto-deploys to staging, production
is a manual dispatch, and the workflow swaps in environment-specific server
configuration — cache-disabled and no-index for staging, cached with security headers
for production.
Four complete business tools, each running by double-clicking an HTML file:
sales reporting with print-perfect A4 output, inventory
dissection that decodes and audits search tags, invoice history
with PDF-fidelity rendering and stock reconciliation, and a loyalty
programme with a campaigns engine.
No server, no install, no dependencies, no monthly fee — and the data never leaves the
browser it is loaded in. Constraint-driven engineering for users who should not have to
maintain anything.
Four spreadsheet calculators from a published household finance guide, rebuilt as one
installable progressive web app with stable hash routes so each chapter's QR code opens
its own tool directly.
Private by construction — no server, no analytics, no network calls of any kind. Every
entry stays in the browser's own storage, with per-tool resets and a global clear.
The AidPost product site in six languages — English, French, Arabic, Spanish, Swahili
and Urdu — as plain HTML and CSS with no build step, no framework and no dependencies,
on Cloudflare Pages.
Each language is a fully translated page rather than a string swap, with
hreflang alternates in the sitemap and right-to-left handled properly.
A discovery engagement rather than a codebase: a system map of Ontario's non-emergency
patient transfer market, a bottom-up opportunity model with every assumption written
down and auditable, a source register with per-source confidence ratings, and an
operating business case.
The analyst half of the job. It also contains a read-only assessment that
overturns the study's own earlier assumption — the record of a conclusion
being corrected by evidence.
Only technologies in production use or evidenced in the delivery record.
Nothing aspirational.
Languages
TypeScript
JavaScript (ES2020+)
Python 3.12
C# / .NET
SQL
PL/SQL
Liquid
HTML5
CSS3
PowerShell
VB.NET
XML / XSLT
Front end
React 18
Vite
Dexie
IndexedDB
Workbox
Service Workers
Web App Manifest
WebCrypto
Bootstrap 5
WET-BOEW / GCWeb
CDTS
SVG
Print CSS
onnxruntime-web
Back end & data
Django 5.2
Django REST Framework
Fastify 5
Node.js
PostgreSQL
SQLite
Dataverse
SQL Server
Oracle
Gunicorn
SSIS
Entity Framework
Testing & quality
Vitest
Playwright
Testing Library
fake-indexeddb
pg-mem
jsdom
axe-core
ESLint
mypy
ruff
user-event
Platform & delivery
GitHub Actions
Docker
Cloudflare Pages
GitHub Pages
Render
Azure DevOps
CodeQL
CycloneDX SBOM
Let's Encrypt
Wrangler
Apache config
Standards & interop
HL7 FHIR R4
WCAG 2.1 AA
WET4 / GCWeb
OpenAPI / Swagger
OData
FetchXML
RFC 6238 / 4226
AAMVA
WebVTT
hreflang
Official Languages Act
Microsoft Power Platform
Power Pages
Power Apps (model-driven)
Power Automate
Dataverse
Dynamics 365 CE
PCF controls
Business Process Flows
Plugins (C#)
SSRS
Security
AES-256-GCM
PBKDF2-SHA-256
TOTP / MFA
Hash-chained audit logs
Content Security Policy
reCAPTCHA
Secret scanning
Least-privilege design
AI-assisted delivery
Claude Code
Agent skills
MCP servers
Automated review in CI
Committed agent instructions
06 — The practice
Who you work with
WEBWorx is a senior-only practice. Engagements are led and delivered by the principal —
there is no hand-off from the person you met to a team you did not.
AF
Akram Farhat
Principal Senior Consultant
Twenty years of enterprise software engineering and systems analysis, eight of them
specialising in Power Apps, Power Pages, Power Automate, Dataverse and Dynamics 365 CE.
Delivery lead on public-facing Government of Canada service portals under GCWeb /
WET-BOEW and WCAG, with database design and data-modelling depth behind it — and the
architect and developer of AidPost and ESMS.
Based Ottawa, Ontario
Clearance Reliability status, valid to January 2030
Education BSc (Hons) Computer Engineering Technology, University of Teesside
Languages English and Arabic; working knowledge of French
Delivery record
Health CanadaSystem Analyst, Level 32025 – 2026
SafePort, GI Report, SSI Request and Cruise Ship Scores portals. Power Pages and Dataverse under GCWeb 17 / WET4; led accessibility remediation for a portal serving thousands of users; modernised client-side code to TypeScript.
GCcase — Government of Canada case management on Dynamics 365 CE. Dataverse data models, PCF grid and field controls in TypeScript and React, SSIS migration of legacy datasets, PowerShell release automation in Azure DevOps.
BC Ministry of Attorney GeneralSenior Developer / Analyst2022 – 2023
FAMS (maintenance enforcement) and CARMA (case review and adjudication). Dynamics 365 CE and Power Apps solutions with .NET, FetchXML and JavaScript; OpenAPI contracts for integration endpoints.
EC Connex intake and case management on Dynamics 365. Business process flows, SSRS reporting, SharePoint integration patterns, and performance testing of web form intake at scale.
National Research Council (IRAP)System Analyst2017 – 2019
IRAP Innovation Portal, SONAR and Concierge. Modernisation of a client-facing portal for thousands of users aligned to the Canada.ca theme and WCAG 2.0, on ASP.NET with WCF services.
Natural Resources CanadaSystem Analyst2012 – 2016
EnerGuide Rating System. Oracle 11g PL/SQL, Erwin logical and physical data models, data conversion from legacy stores, multi-tier ASP.NET delivery under WCAG 2.0 and WET v4.
City of OttawaSenior Programmer / Developer2003 – 2004
GROVER — ambulance call reporting for the Emergency Medical Services branch, 650 paramedic users. Oracle back end, 60+ VB.NET class objects, a data-warehouse reporting subsystem, and the full design documentation set.
The first entry and the newest one are the same problem. In 2003 the
work was capturing patient treatment and response data for 650 paramedics. In 2026 it is
AidPost — casualty care and transport documentation for field responders, offline,
encrypted, in seven languages. Twenty-three years apart, on the technology that finally
makes it portable. Also omitted for brevity: Employment and Social Development Canada,
Transport Canada, the Immigration and Refugee Board, and Fisheries and Oceans.
How this page was written. The capabilities and approach above were
compiled by reading the code — twenty-six repositories with their commit history, build
configuration, test suites and architecture documents — rather than from a résumé. Nine
of those repositories are private and appear here by capability and technology only: no
client identifiers, no source excerpts, no screenshots.
Available for design & development engagements
Let's talk about the hard part
Offline-first architecture, accessibility that survives an audit, bilingual or
right-to-left delivery, or Power Platform work that has to meet federal standards.
Tell us what has to be true, and we will tell you how we would build it.