I build and maintain web applications, from design to production.
I’m Rain, a fourth-year computer science student at SFU. Over the past year I’ve built and maintained software for a security-key company and a property management company. I work mostly in Python, TypeScript and Rust.
Experience
- Aug 2026 – Present
MNT Realty · Vancouver, BC, Canada
I’m responsible for software and IT at a property and strata management company. I work with staff to understand what the office needs, then build and maintain the internal systems they use, connected to the company’s Microsoft 365 accounts and data.
Work- Planned and rebuilt the MNT Realty platform from scratch as one application for three sites: a public website, an owner portal for residents, and an admin console for staff.
- Designed and built MNT Control Center, an internal platform in Next.js, Node.js and PostgreSQL that replaces the separate tools the office used before.
- Set up organization sign-in and role-based access with Microsoft Entra ID, the Graph API and OAuth 2.0.
- Automated the recurring office tasks that took staff the most time: sorting incoming email, looking up owner information, and answering staff questions from company documents with an internal assistant.
Operations- Manage hosting, deployment, domains and DNS, and the release process on Vercel and GitHub Actions.
- Write tests and documentation so that someone else can take over the systems later.
TechnologiesPythonTypeScriptNext.jsReactNode.jsTailwind CSSPostgreSQLMicrosoft 365Microsoft Entra IDMicrosoft Graph APIOAuth 2.0DockerVercelGitHub ActionsRelated work - Sep – Dec 2025

FEITIAN Technologies · International Department · Beijing, China
I planned, built and ran three systems for FEITIAN’s post-quantum FIDO2 work: a public WebAuthn developer platform, a software security key in Rust, and a customer demo site.
Work- Built the company’s first WebAuthn/FIDO2 developer platform, because the team’s third-party tools could not show post-quantum credentials. Developers can register, sign in, inspect and debug credentials in one place.
- 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 the hardware was ready.
- Built a self-service demo site where customers can try passwordless sign-in and security keys without contacting support.
- Worked with FEITIAN’s hardware and security engineers so the tools matched the real devices and the data they returned.
Operations- Deployed with Docker on Linux servers and Google Cloud Run, with GitHub Actions running tests, builds and a daily update of the FIDO metadata.
- Still maintain all three systems after the internship ended in December 2025.
TechnologiesPythonFlaskJavaScriptHTMLRustTypeScriptReactTailwind CSSDockerGoogle CloudGitHub ActionsWebAuthn / FIDO2CTAP2.1ML-DSAliboqsRelated work
Selected Work
- Aug 2026 – Present
One Next.js application serving three sites for a property management company: a public website, an owner portal for residents, and an admin console for staff.
Next.jsTypeScriptReactmntrealty.vercel.appWhat it isMNT Realty’s website and online services. Prospective clients see the public website. Residents of the stratas MNT manages sign in to the owner portal to read notices, book amenities and download documents. Staff manage all of it from the admin console.
How it worksThe three sites come from one build, each on its own subdomain. A proxy sends each subdomain to its own pages (admin to the console, owners to the portal), and the public site returns a not-found page for those paths. Each site has its own layout and its own host-only session cookie. Public pages are prerendered, and the console and the portal are rendered on each request. All reads and writes go through one data store interface, so changes staff make show up for residents right away, and the store can later be switched to the drafted PostgreSQL schema without changing any screens.
Technical challengesAccess rules are defined once, in a table that the navigation, the page guards and the file route all read. A section outside a user’s role returns not-found rather than forbidden, so the portal does not reveal what other roles can see. Each strata is kept separate: while one is open, nothing from another can be reached. MNT’s own business details, such as company information, the fee schedule for strata documents and the template for amenity booking slots, are versioned data that an administrator edits under Settings, not values in the code. Any saved version can be restored.
StackNext.jsReactTypeScriptTailwind CSSNode.jsPostgreSQLVitestVercelGitHub ActionsStatusAll three sites are built and deployed. The next steps are cloud data storage and backend workflows. The source code belongs to MNT Realty and is not public.
- Oct 2025 – Present
A CTAP2 security key that runs in software. Linux presents it as a USB device, so browsers can test post-quantum credentials without real hardware.
RustLinuxRepositoryWhat it isA Rust workspace that works like a FIDO2 security key, but in software. FEITIAN’s engineers and partners needed to build and test software that uses ML-DSA credentials before the hardware was ready. It started in my own repository and has since moved to FEITIAN’s GitHub organization, where I still maintain it.
How it worksThe authenticator core implements CTAP2.1 (credential management, PIN/UV protocols 1 and 2, and reset) on the Trussed framework with littlefs2 storage. A runner creates a virtual USB HID device through Linux uhid and uses the CTAPHID protocol, so Chrome, Firefox and libfido2 treat it as an ordinary security key. It supports ES256 and ML-DSA-44, -65 and -87, and comes with a small command-line tool (attach, detach, status, reset, pin) that can run in the background.
Technical challengesBrowsers only accept devices that follow the protocol closely, so the HID transport and the CTAP state machine had to be exact before Chrome or Firefox would use the key. CTAP and COSE structures were designed for classical keys, and post-quantum keys do not fit them easily. The first version called liboqs through a C FFI; it later moved to the pure-Rust fips204 crate, with secret keys zeroized when they are dropped.
StackRustLinux UHIDTrussedlittlefs2CTAP2.1fips204liboqsclapStatusWorks on Linux and is used alongside the developer platform. It is still in active development, and CI runs rustfmt, clippy and the test suite.
- Sep 2025 – Present
A public tool for testing FIDO2/WebAuthn flows, including post-quantum ML-DSA credentials.
What it isA Flask web application for developers who work with FIDO2. The third-party tools the team used could not show post-quantum credentials, so I built one that could. Developers can register and sign in with real or virtual authenticators, edit the raw WebAuthn request as JSON, decode the response, and look up any authenticator in the FIDO Alliance metadata service. I started it during my internship at FEITIAN and still maintain it.
How it worksIt has 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 that checks root certificates. The server uses a modified copy of Yubico’s python-fido2 library, with ML-DSA-44, -65 and -87 added through liboqs. Each visitor gets a separate session store, on local disk or in Google Cloud Storage, and a store that goes unused for 14 days is deleted.
Technical challengespython-fido2 had no post-quantum support, so I added the COSE identifiers, key handling and attestation checks for ML-DSA while keeping the classical algorithms working. Including liboqs in the container image made Cloud Run slow to start, so I added a lazy warm-up and set gunicorn to run a single worker. The FIDO metadata goes out of date, so a daily GitHub Action re-verifies the snapshot and commits it automatically.
StackPythonFlaskJavaScriptDockerGoogle CloudGitHub Actionspython-fido2liboqsJinjapytestVitestStatusLive at webauthnlab.tech and maintained in FEITIAN’s GitHub organization. CI runs about 120 server test files, plus front-end and post-quantum tests.
- Nov – Dec 2025
A demo site where FEITIAN’s customers can try passwordless and post-quantum sign-in.
ReactPythondemo.ftsafe.comWhat it isA demo for FEITIAN’s customers and sales team. The developer platform is for engineers; this site is for people evaluating FEITIAN’s products. Visitors can register a security key, sign in, and see a post-quantum credential work without reading a specification.
How it worksA React front end on top of the same authentication service and ML-DSA support as the developer platform. Instead of raw requests and responses, it guides visitors through each step.
StackReactJavaScriptPythonFlaskWebAuthn / FIDO2ML-DSAliboqsStatusLive at demo.ftsafe.com. The source code belongs to FEITIAN and is not public.
Other Work
- Feb 2025 – Present
A statically generated portfolio site in English and Japanese. It shares a small design system with my resume and cover letter.
What it isMy portfolio at rainzhang.me: a home page and a resume page, both in English and Japanese. It uses its own small design system: one typeface, one accent colour, no borders or shadows, and a light and a dark theme. My resume and cover letter use the same design, so the three look like one set.
How it worksThe Next.js App Router prerenders both languages at build time from one typed content model, so the English and Japanese home pages have the same structure and only the text differs. Tailwind reads the design system’s tokens instead of raw values, and Albert Sans is self-hosted through next/font. Middleware shows a first-time visitor from Japan the Japanese version, and after that the site remembers the language each reader last used.
FeaturesExperience and project rows expand in place. The site also has a language switch, a theme switch (System, Light and Dark), a short entrance animation in plain CSS, a contact form that sends through Formspree with a honeypot field and a request timeout, and a button that copies my email address. The pages still load and their links still work without JavaScript, and every animation follows the reader’s reduced-motion setting.
StackNext.jsTypeScriptReactTailwind CSSPlaywrightVitestVercelGitHub ActionsStatusLive at rainzhang.me. CI runs Vitest unit tests and Playwright end-to-end tests in Chromium, Firefox and WebKit, plus an emulated iPhone.
- Jan – Apr 2025
A course project with three classmates: a trip planner that suggests a destination based on a traveller’s passport and visas, then fills in hotels, restaurants and an itinerary.
What it isA group project for CMPT 276. Users answer a short questionnaire or choose a place, pick their dates, and get hotels, restaurants, attractions and a day-by-day plan. A chat assistant answers 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 connects to the Tripadvisor API.
Looking backThe app calls the OpenAI API directly from the browser. If I built it again, I would move that call to the backend.
StackReactJavaScriptTailwind CSSViteOpenAI APITripadvisor APICypressVercelStatusFinished in April 2025 and still live.
Background
Simon Fraser University
BSc, Computer Science · Vancouver, BC, Canada · Expected to graduate in December 2027
CGPA 3.44 / 4.33. Dean’s Honour Roll in Fall 2024 and Summer 2025.
Contact
If you’re hiring or would like to talk about my work, I’d be glad to hear from you.
- linkedin.com/in/rainzhang05
- GitHub
- github.com/rainzhang05