I build and maintain web systems, from design through to production.
I’m Rain, a third-year computer science student at SFU. In the past year I’ve built and run production systems for a security-key company and a property management firm, mostly in Python, TypeScript and Rust.
Experience
- Aug 2026 – Present
MNT Realty · Vancouver, BC, Canada
The only engineer at a property and strata management company. I build and run the internal systems the office works from, and connect them to the company’s Microsoft 365 accounts and data.
Work- Designed and built MNT Control Center, an internal platform that brings the company’s scattered tools into one place.
- Set up organisation sign-in and role-based access with Microsoft Entra ID, the Graph API and OAuth 2.0.
- Built the internal web applications behind it in Next.js, Node.js and PostgreSQL.
- Automated recurring office work: sorting incoming email, looking up owner information, and answering staff questions from company documents through an internal assistant.
Operations- Look after hosting, deployment, domains and DNS, and the release workflow on Vercel and GitHub Actions.
- Test, maintain and document everything myself, so the systems can be handed over one day.
TechnologiesPythonTypeScriptNext.jsReactNode.jsTailwind CSSPostgreSQLMicrosoft 365Microsoft Entra IDMicrosoft Graph APIOAuth 2.0DockerVercelGitHub ActionsRelated work - Sep – Dec 2025
FEITIAN Technologies · International Department · Beijing, China
Built three systems for FEITIAN’s post-quantum FIDO2 work and ran them end to end: a public WebAuthn developer platform, a software security key in Rust, and a customer demo site.
Work- Designed and built the company’s first WebAuthn/FIDO2 developer platform, replacing scattered third-party tools with one place to register, sign in, inspect and debug credentials.
- Wrote a CTAP2 authenticator in Rust that Linux presents as a virtual USB security key, so browsers and libfido2 could test ML-DSA credentials before hardware existed.
- Built a self-service demo site so customers could try passwordless sign-in and security keys without going through support.
Delivery- Deployed with Docker on Linux servers and Google Cloud Run; GitHub Actions for tests, builds and a daily FIDO metadata refresh.
- Worked with FEITIAN’s hardware and security engineers so the tools matched real devices and the data they needed.
- Kept maintaining all three after the internship ended.
TechnologiesPythonFlaskJavaScriptHTMLRustTypeScriptReactTailwind CSSDockerGoogle CloudGitHub ActionsWebAuthn / FIDO2CTAP2.1ML-DSAliboqsRelated work
Selected Work
- Aug 2026 – Present
One Next.js application serving three surfaces for a property management company: the public website, an owner portal for residents, and a staff admin console.
Next.jsTypeScriptReactmntrealty.vercel.appWhat it isThe platform MNT Realty runs on: a public website for prospective clients, an owner portal where residents of the stratas MNT manages read notices, book amenities and download documents, and an admin console where staff run all of it. Replacing a single 553 KB HTML document that switched between all four audiences with CSS and served everything from one PHP endpoint.
How it worksThree surfaces, three subdomains, one build. A proxy routes on the host — admin.* to the console, owners.* to the portal — and turns those paths into a not-found page on the public host, so each keeps its own chrome and its own host-only session cookie. Public pages are prerendered; the console and the portal render per request. Every read and write goes through one named data-store contract, one operation per write and one read model per screen, so what staff enter reaches residents at once and the store behind it can be swapped for the drafted PostgreSQL schema without touching a screen.
Technical challengesGetting the access model right in one place rather than in every guard: navigation, page guards and the file route all read the same table, and a section outside a viewer’s role is not-found rather than forbidden, so the portal never tells a tenant what an owner can see. Making a strata a real boundary, so nothing about one is reachable while another is open. And keeping MNT’s own business facts — company details, the strata-document fee schedule, the amenity slot template — as versioned data an administrator edits under Settings, rather than literals in the source, with every saved version restorable.
StackNext.jsReactTypeScriptTailwind CSSNode.jsPostgreSQLVitestVercelGitHub ActionsStatusThe public website, the owner portal and the admin console are all built and deployed; cloud data and backend workflows are next. The source belongs to MNT Realty and is not public.
- Sep 2025 – Present
A public tool for testing FIDO2/WebAuthn flows, including post-quantum ML-DSA credentials.
What it isA Flask web app for developers building on FIDO2. Register and sign in with real or virtual authenticators, edit the raw WebAuthn request as JSON, decode what comes back, and look up any authenticator in the FIDO Alliance metadata service. Built at FEITIAN during my internship and still maintained.
How it worksFour tabs: simple sign-in, an advanced mode with an editable request, a codec for attestation objects and CBOR/CTAP structures, and a metadata explorer with root-certificate checks. The server is a modified copy of Yubico’s python-fido2 with ML-DSA-44, -65 and -87 added through liboqs. Each visitor gets an isolated session store, on local disk or Google Cloud Storage, cleaned up after 14 days of inactivity.
Technical challengesTeaching the library algorithms it did not know: new COSE identifiers, key handling and attestation checks, without breaking the classical paths. Keeping Cloud Run cold starts short with liboqs in the image, which led to lazy warm-up and a one-worker gunicorn build. Keeping the metadata current without a person in the loop: a daily GitHub Action re-verifies and commits the snapshot.
StackPythonFlaskJavaScriptDockerGoogle CloudGitHub Actionspython-fido2liboqsJinjapytestVitestStatusLive at webauthnlab.tech and maintained under FeitianTech. About 120 server test files, plus frontend and post-quantum tests, run in CI.
- Nov – Dec 2025
A customer-facing site for trying FEITIAN’s passwordless and post-quantum sign-in.
ReactPythondemo.ftsafe.comWhat it isA demo for FEITIAN’s customers and sales team. Where the developer platform is built for engineers, this one is for people evaluating the products: register a security key, sign in, and see a post-quantum credential work, without reading a specification.
How it worksA React front end over the same authentication service and ML-DSA support as the developer platform, with a guided interface in place of raw requests and responses.
StackReactJavaScriptPythonFlaskWebAuthn / FIDO2ML-DSAliboqsStatusLive at demo.ftsafe.com. The source belongs to FEITIAN and is not public.
- Oct – Nov 2025
A CTAP2 security key in software. Linux presents it as a USB device, so browsers can test post-quantum credentials without hardware.
RustLinuxRepositoryWhat it isA Rust workspace that behaves like a FIDO2 security key without the key. It exists so FEITIAN’s engineers and partners could develop against ML-DSA credentials before the hardware was ready. It started as my own repository and is now maintained under FeitianTech.
How it worksAn authenticator core implements CTAP2.1 on the Trussed framework with littlefs2 storage: credential management, PIN/UV protocols 1 and 2, and reset. A runner registers a virtual USB HID device through Linux uhid and speaks CTAPHID, so Chrome, Firefox and libfido2 see an ordinary key. It advertises ES256 and ML-DSA-44, -65 and -87, and ships a small command-line tool (attach, detach, status, reset, pin) that can run as a daemon.
Technical challengesGetting the HID transport and the CTAP state machine right enough that real browsers accept it. Fitting post-quantum keys into CTAP and COSE structures made for classical ones. The first version called liboqs over a C FFI; it later moved to the pure-Rust fips204 crate, with secret keys zeroised on drop.
StackRustLinux UHIDTrussedlittlefs2CTAP2.1fips204liboqsclapStatusWorks on Linux and is used alongside the developer platform. CI runs rustfmt, clippy and the test suite.
Other Work
- Feb 2025 – Present
A statically generated portfolio in English and Japanese, built on one small design system shared with my resume and cover letter.
What it isMy portfolio, at rainzhang.me. One scrolling page in two languages, on its own design system: one typeface, ivory paper, one accent, no borders or shadows. The resume and cover letter use the same system, so everything a recruiter sees from me comes from one hand.
How it worksNext.js App Router prerenders both languages at build time from one typed content model, so /en and /ja stay structurally identical and only the prose differs. Tailwind reads the design system’s tokens rather than raw values, Albert Sans is self-hosted through next/font, and middleware sends a first-time visitor in Japan to the Japanese route unless they have chosen otherwise.
FeaturesExperience and project rows expand in place, a language switch whose pill slides between English and Japanese, a first-screen entrance in pure CSS, a contact form that posts to Formspree behind a honeypot and a request timeout, and a copy-to-clipboard email. Everything renders without JavaScript and every duration honours prefers-reduced-motion.
StackNext.jsTypeScriptReactTailwind CSSPlaywrightVitestVercelGitHub ActionsStatusLive at rainzhang.me. Unit tests in Vitest and an end-to-end suite in Playwright across Chromium, Firefox, Safari and mobile run in CI.
- Jan – Apr 2025
A course project with three classmates: a trip planner that picks a destination from your passport and visas, then fills in hotels, restaurants and an itinerary.
What it isA CMPT 276 group project. You answer a short questionnaire or pick a place, choose dates, and get hotels, restaurants, attractions and a day-by-day plan, with a chat assistant for follow-up questions.
My partI built the React and Tailwind front end, the passport and visa questionnaire that asks OpenAI for a destination, the date steps and their validation, and the chat widget. A teammate wrote the Express service that fronts the Tripadvisor API.
Looking backThe OpenAI key is called from the browser. Today I would put it behind the backend.
StackReactJavaScriptTailwind CSSViteOpenAI APITripadvisor APICypressVercelStatusFinished in April 2025 and still live.
Background
Simon Fraser University
BSc, Computer Science · Vancouver, BC, Canada · Graduating April 2027
CGPA 3.44 / 4.33. Dean’s Honour Roll in Fall 2024 and Summer 2025.
Contact
If you’re hiring, or want to talk about any of this, please write to me.
- linkedin.com/in/rainzhang05
- GitHub
- github.com/rainzhang05