Skip to content
Rain Zhang
Computer science · Simon Fraser University · Vancouver, BC, Canada

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.

Download Resume

Experience

  • Aug 2026 – Present

    MNT Realty

    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.
    Technologies
    PythonTypeScriptNext.jsReactNode.jsTailwind CSSPostgreSQLMicrosoft 365Microsoft Entra IDMicrosoft Graph APIOAuth 2.0DockerVercelGitHub Actions
    Related work
  • Sep – Dec 2025

    FEITIAN Technologies

    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.
    Technologies
    PythonFlaskJavaScriptHTMLRustTypeScriptReactTailwind CSSDockerGoogle CloudGitHub ActionsWebAuthn / FIDO2CTAP2.1ML-DSAliboqs
    Related 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.jsTypeScriptReact
    mntrealty.vercel.app
    What it is

    The 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 works

    Three 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 challenges

    Getting 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.

    The MNT Realty home page, with the service line and the proposal and owner-portal entry points
    Stack
    Next.jsReactTypeScriptTailwind CSSNode.jsPostgreSQLVitestVercelGitHub Actions
    Status

    The 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.

    PythonFlaskJavaScript
    webauthnlab.techRepository
    What it is

    A 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 works

    Four 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 challenges

    Teaching 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.

    The advanced tab of the WebAuthn developer platform, with an editable request and a decoded response
    Stack
    PythonFlaskJavaScriptDockerGoogle CloudGitHub Actionspython-fido2liboqsJinjapytestVitest
    Status

    Live 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.

    ReactPython
    demo.ftsafe.com
    What it is

    A 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 works

    A 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.

    The authentication demo platform sign-in screen
    Stack
    ReactJavaScriptPythonFlaskWebAuthn / FIDO2ML-DSAliboqs
    Status

    Live 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.

    RustLinux
    Repository
    What it is

    A 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 works

    An 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 challenges

    Getting 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.

    Stack
    RustLinux UHIDTrussedlittlefs2CTAP2.1fips204liboqsclap
    Status

    Works 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.

    Next.jsTypeScript
    rainzhang.meRepository
    What it is

    My 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 works

    Next.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.

    Features

    Experience 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.

    Stack
    Next.jsTypeScriptReactTailwind CSSPlaywrightVitestVercelGitHub Actions
    Status

    Live 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 is

    A 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 part

    I 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 back

    The OpenAI key is called from the browser. Today I would put it behind the backend.

    The Travel Advisor results page with hotels, restaurants and attractions
    Stack
    ReactJavaScriptTailwind CSSViteOpenAI APITripadvisor APICypressVercel
    Status

    Finished in April 2025 and still live.

Background

Sep 2023 – Apr 2027

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.

Languages
PythonTypeScriptJavaScriptRustCC++Java
Web
ReactNext.jsNode.jsFlaskTailwind CSSHTMLCSSPostgreSQL
Infrastructure and tools
DockerGoogle CloudVercelGitHub ActionsGitGitHubLinuxWebAuthn / FIDO2Microsoft 365Microsoft Entra ID

Contact

If you’re hiring, or want to talk about any of this, please write to me.