Drive plain résumé page from resume.json + global search (redesign phase 3)

Make the plain page (public/resume.html) a generated declared mirror so it and
the terminal share one source, and enrich that source to the superset both need.

- resume.org: merged to the superset — richer achievement-oriented bullets,
  per-item subtitle/location/tech tags, all projects (adds Terrapin Rocket,
  Robotics@UMD) and the full course list.
- org-to-json parser: optional subtitle/location fields + `- tech :: X` tagged
  bullets; `list` flag so education stays bullet-free; empty tag arrays dropped.
- scripts/build-resume-html.mjs + resume.template.html: the template owns the
  design (unchanged look); content is rendered from resume.json. Adds a global
  search box that filters every card and course pill across sections, with a
  no-results empty state. HTML-escaped; arXiv ids linkified.
- resume:build now generates both mirrors; resume:check + CI canary verify both.

Verified: yarn build + tsc clean; both canaries green; driven headless — design
preserved, 17 cards render, search isolates by keyword/tech/course, no errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nt6ycjAMdUMqGTGtbKocrs
pull/59/head
Claude 3 months ago
parent a8ec735c77
commit 2914f8dc02
No known key found for this signature in database

@ -1,12 +1,24 @@
# Drift canary for the résumé declared mirror (praxis: Mirrors and Canaries). # Drift canary for the résumé declared mirrors (praxis: Mirrors and Canaries).
# Fails if resume.json is out of sync with its canonical source resume.org. # Fails if resume.json or public/resume.html is out of sync with resume.org.
name: resume-canary name: resume-canary
on: on:
push: push:
paths: ['resume.org', 'resume.json', 'scripts/org-to-json.mjs'] paths:
- 'resume.org'
- 'resume.json'
- 'public/resume.html'
- 'resume.template.html'
- 'scripts/org-to-json.mjs'
- 'scripts/build-resume-html.mjs'
pull_request: pull_request:
paths: ['resume.org', 'resume.json', 'scripts/org-to-json.mjs'] paths:
- 'resume.org'
- 'resume.json'
- 'public/resume.html'
- 'resume.template.html'
- 'scripts/org-to-json.mjs'
- 'scripts/build-resume-html.mjs'
jobs: jobs:
check: check:
@ -18,3 +30,5 @@ jobs:
node-version: '20' node-version: '20'
- name: Verify resume.json matches resume.org - name: Verify resume.json matches resume.org
run: node scripts/org-to-json.mjs resume.org resume.json --check run: node scripts/org-to-json.mjs resume.org resume.json --check
- name: Verify public/resume.html matches resume.json
run: node scripts/build-resume-html.mjs --check

@ -8,8 +8,8 @@
"email": "contact@wensenwu.com" "email": "contact@wensenwu.com"
}, },
"scripts": { "scripts": {
"resume:build": "node scripts/org-to-json.mjs resume.org resume.json", "resume:build": "node scripts/org-to-json.mjs resume.org resume.json && node scripts/build-resume-html.mjs",
"resume:check": "node scripts/org-to-json.mjs resume.org resume.json --check", "resume:check": "node scripts/org-to-json.mjs resume.org resume.json --check && node scripts/build-resume-html.mjs --check",
"prebuild": "yarn resume:build", "prebuild": "yarn resume:build",
"predev": "yarn resume:build", "predev": "yarn resume:build",
"dev": "next dev", "dev": "next dev",

File diff suppressed because it is too large Load Diff

@ -13,23 +13,41 @@
{ {
"id": "809dd6f7-7700-43ae-ac87-ae2ec79ab4ef", "id": "809dd6f7-7700-43ae-ac87-ae2ec79ab4ef",
"role": "Researcher", "role": "Researcher",
"company": "CAAR REU (QuICS)", "company": "CAAR REU",
"dates": "Jun 2025 – Aug 2025", "dates": "Jun 2025 – Aug 2025",
"subtitle": "Combinatorics, Algorithms, and AI for Real Problems",
"location": "QuICS · University of Maryland",
"tech": [
"Python",
"Galois",
"NumPy",
"Magma Math",
"SageMath"
],
"bullets": [ "bullets": [
"Created families of fault-tolerant CSS quantum error-correcting codes for qudits.", "Designed novel fault-tolerant CSS quantum error-correcting codes for qudits inspired by quadratic residue codes.",
"Proved transversal Clifford and T gate support using finite field and QEC theory.", "Established code families with transversal Clifford and T gate support through finite field and QEC theory proofs.",
"Built parallel Python tooling (Galois, NumPy, Magma, SageMath) to test self-orthogonality and distance." "Implemented parallel Python tooling to validate self-orthogonality and distance properties across large search spaces."
] ]
}, },
{ {
"id": "4ee96812-4a42-4fce-ab41-223dc3237ed1", "id": "4ee96812-4a42-4fce-ab41-223dc3237ed1",
"role": "Undergraduate Researcher", "role": "Undergraduate Researcher",
"company": "Bright Beams Collective (IREAP)", "company": "Bright Beams Collective",
"dates": "Sep 2023 – Dec 2024", "dates": "Sep 2023 – Dec 2024",
"subtitle": "IREAP Research Experience for Undergraduates",
"location": "Institute for Research in Electronics and Applied Physics",
"tech": [
"MAD-X",
"Elegant",
"Fusion 360",
"MATLAB",
"Ansys Workbench"
],
"bullets": [ "bullets": [
"Designed machine learning and gradient optimizers for particle accelerator beamline tuning.", "Built custom machine learning and gradient-based optimizers to derive design parameters for a planned beamline.",
"Ran MAD-X and Elegant simulations to evaluate lattice stability and beam quality.", "Ran accelerator simulations to analyze lattice stability and beam quality under varied operating configurations.",
"Produced Fusion 360 and Ansys visualizations for educational and technical presentations." "Produced animations of betatron motion for outreach presentations and technical discussions."
] ]
}, },
{ {
@ -37,10 +55,15 @@
"role": "Software Engineering Intern", "role": "Software Engineering Intern",
"company": "JODO PAY", "company": "JODO PAY",
"dates": "Jun 2022 – Jul 2022", "dates": "Jun 2022 – Jul 2022",
"subtitle": "Invoicing System Automation",
"tech": [
"JavaScript",
"TypeScript",
"Google Apps Script"
],
"bullets": [ "bullets": [
"Automated invoice generation and delivery via Google Workspace APIs.", "Automated invoice generation and dispatch for clients, reducing manual processing by 40 staff hours each week.",
"Reduced manual processing by approximately 40 staff hours each week.", "Integrated Google Workspace APIs to manage templates, customer data, and error handling workflows."
"Hardened error handling and template management with TypeScript and Apps Script."
] ]
} }
], ],
@ -49,61 +72,137 @@
"id": "28f564fa-8ac8-4720-bf5c-cf999186cf6d", "id": "28f564fa-8ac8-4720-bf5c-cf999186cf6d",
"name": "Quantum State Tomography via QML", "name": "Quantum State Tomography via QML",
"timeline": "Sep 2024 – Jul 2025", "timeline": "Sep 2024 – Jul 2025",
"subtitle": "GitHub · github.com/Mihir-Null",
"tech": [
"Python",
"Qiskit",
"Aer",
"MPI",
"Numba",
"PyTorch"
],
"bullets": [ "bullets": [
"Co-developed variational circuit tomography with custom losses and embeddings.", "Co-developed a variational circuit tomography approach, exploring loss landscapes, embedding strategies, and optimizers.",
"Launched 2,000+ experiments across multi-GPU clusters via bespoke orchestration tools.", "Executed 2,000+ experiments across multi-GPU clusters with a custom orchestrator for reproducible benchmarking.",
"Co-author on \"Quantum state reconstruction with variational quantum circuit\" (arXiv:2507.01246)." "Co-authored \"Quantum state reconstruction with variational quantum circuit\" (arXiv:2507.01246)."
] ]
}, },
{ {
"id": "25c4d9b7-ea24-4af7-8cac-f1855743abc6", "id": "25c4d9b7-ea24-4af7-8cac-f1855743abc6",
"name": "MIT iQuHack — QuEra Challenge", "name": "MIT iQuHack — QuEra Challenge",
"timeline": "Feb 2025", "timeline": "Feb 2025",
"subtitle": "Honorable Mention",
"tech": [
"Python",
"Qiskit",
"Cirq",
"Bloqade",
"PyTorch",
"TensorFlow Quantum"
],
"bullets": [ "bullets": [
"Built a compilation pipeline translating QAOA and error-correcting circuits into neutral atom instructions.", "Designed a compilation pipeline mapping diverse quantum circuits — including QAOA and Steane codes — to QuEra hardware.",
"Optimized pulse schedules using Qiskit, Cirq, Bloqade, PyTorch, and TensorFlow Quantum.", "Optimized pulse sequences for neutral atom instruction sets, contributing to the team's honorable mention finish."
"Team earned an Honorable Mention from QuEra."
] ]
}, },
{ {
"id": "e00b83aa-277b-4379-96aa-989754fefbcb", "id": "5a0897f1-4b2c-4dd4-a68e-8a324822f425",
"name": "Club Administration Automation", "name": "Quantum Machine Learning Research",
"timeline": "Nov 2024 – Feb 2025", "timeline": "Aug 2023 – Dec 2024",
"subtitle": "Undergraduate Research Portfolio",
"tech": [
"Python",
"Qiskit",
"Cirq",
"PennyLane",
"Q#"
],
"bullets": [ "bullets": [
"Automated Discord announcements, email campaigns, Instagram posts, and room reservations.", "Implemented quantum image processing with parameterized circuit kernels integrated into CNN architectures.",
"Integrated Google APIs, Discord.py, Selenium, and OAuth2 for end-to-end workflows.", "Created a hybrid transitional optimizer to mitigate barren plateaus in QAOA, presented at the FYIRE Summit 2024."
"Adopted by multiple university clubs to reduce administrative effort."
] ]
}, },
{ {
"id": "5a0897f1-4b2c-4dd4-a68e-8a324822f425", "id": "81fadb40-43da-4f62-805a-686b65bdf5f8",
"name": "Quantum ML Research Collection", "name": "Terrapin Rocket Team — Kalman Filters",
"timeline": "Aug 2023 – Dec 2024", "timeline": "Aug 2023 – Jan 2024",
"subtitle": "Guidance, Navigation, and Control",
"tech": [
"C",
"C++",
"MATLAB"
],
"bullets": [ "bullets": [
"Crafted quantum image processing pipelines with parameterized kernels inside CNNs.", "Developed six- and nine-state Kalman filters fusing multi-sensor telemetry for rocket position estimation.",
"Designed a hybrid transitional optimizer that mitigates barren plateaus in QAOA.", "Supported the team's winning entry at the 2024 Spaceport America Cup."
"Presented findings at the 2024 First Year Innovation & Research Experience Summit." ]
},
{
"id": "6fd996da-74d7-4e3c-9ac0-dc6a23d484d4",
"name": "Robotics @ UMD — Computer Vision",
"timeline": "Aug 2023 – Jan 2024",
"subtitle": "Testudog Automation",
"tech": [
"Python",
"OpenCV",
"scikit-learn"
],
"bullets": [
"Developed Haar cascade pipelines for the Testudog robotics platform deployed on a Jetson-powered Boston Dynamics Spot."
]
},
{
"id": "e00b83aa-277b-4379-96aa-989754fefbcb",
"name": "Club Administration Automation",
"timeline": "Nov 2024 – Feb 2025",
"subtitle": "Workflow Automation Suite",
"tech": [
"Python",
"Selenium",
"Discord.py",
"REST APIs",
"OAuth 2.0"
],
"bullets": [
"Automated Discord announcements, email campaigns, Instagram publishing, and room reservations for university clubs.",
"Currently deployed across multiple organizations to streamline administrative overhead."
] ]
}, },
{ {
"id": "25053703-72e2-492d-bf8b-4a5953b6160e", "id": "25053703-72e2-492d-bf8b-4a5953b6160e",
"name": "Housing Market Analysis", "name": "Housing Market Analysis",
"timeline": "Jun 2024 – Jul 2024", "timeline": "Jun 2024 – Jul 2024",
"subtitle": "Predictive Pricing Models",
"tech": [
"Python",
"Pandas",
"SciPy",
"NumPy",
"scikit-learn",
"SQL"
],
"bullets": [ "bullets": [
"Built feedforward neural networks to predict housing prices from public datasets.", "Trained feedforward neural networks for price prediction using engineered features derived from public listings and census data.",
"Applied PCA and statistical analysis to surface high-signal features.", "Applied PCA and statistical analysis to identify high-signal attributes and reduce overfitting."
"Combined web-scraped listings with census data to improve model robustness."
] ]
}, },
{ {
"id": "bdf83287-24aa-4f55-9a07-e11d6e08e319", "id": "bdf83287-24aa-4f55-9a07-e11d6e08e319",
"name": "Indie Game Development", "name": "Independent Game Development",
"timeline": "2020 – 2023", "timeline": "2020 – 2023",
"subtitle": "National Game Jam Winner",
"tech": [
"C#",
"C++",
"Unity",
"Unreal Engine",
"Blender",
"Adobe Suite"
],
"bullets": [ "bullets": [
"Shipped two action platformers with custom soft-body simulation via Unity/Unreal.", "Published two action platformers, including a custom 2D soft-body simulation available via Two Guys Studios on itch.io.",
"2nd place, 2021 Mindbox National Design Championship (Game Design).", "Placed second in the 2021 Mindbox National Design Championship; finalist in the 2020 edition.",
"National finalist, 2020 Mindbox Design Championship (Game Development).", "Built a procedural map generation toolkit leveraging noise algorithms and custom pathfinding."
"Authored a procedural map generation toolkit for arbitrary tilemaps."
] ]
} }
], ],
@ -113,6 +212,7 @@
"school": "University of Maryland — College Park", "school": "University of Maryland — College Park",
"gpa": "3.974", "gpa": "3.974",
"graduation": "May 2027", "graduation": "May 2027",
"subtitle": "Computer Science (Honors) · Physics (Honors)",
"degrees": [ "degrees": [
"B.S. Computer Science (Honors)", "B.S. Computer Science (Honors)",
"B.S. Physics (Honors)" "B.S. Physics (Honors)"
@ -124,12 +224,17 @@
], ],
"coursework": [ "coursework": [
"Graduate Quantum Computing (CMSC657)", "Graduate Quantum Computing (CMSC657)",
"Computer Science Honors Seminar",
"Differentiable Programming for Agentic AI (CMSC498Z)", "Differentiable Programming for Agentic AI (CMSC498Z)",
"Natural Language Processing (CMSC470)", "Natural Language Processing (CMSC470)",
"Data Science (CMSC320)", "Data Science (CMSC320)",
"Design & Analysis of Algorithms (CMSC451)", "Design & Analysis of Algorithms (CMSC451)",
"Object-Oriented Programming in Java (CMSC132)",
"Applied Probability & Statistics (STAT400)",
"Honors Advanced Modern Physics (PHYS400)", "Honors Advanced Modern Physics (PHYS400)",
"Quantum Mechanics II (PHYS402)" "Quantum Mechanics II (PHYS402)",
"Multivariate Calculus",
"Differential Equations"
] ]
} }
], ],
@ -140,8 +245,8 @@
"org": "Quantum Coalition", "org": "Quantum Coalition",
"dates": "Jan 2024 – Present", "dates": "Jan 2024 – Present",
"bullets": [ "bullets": [
"Co-organized the QRISE research competition with 200+ global participants.", "Co-organized the QRISE research competition with 200+ international participants.",
"Partnered with the UN and ITU to deliver the QC-FLIQ hackathon (500+ attendees)." "Partnered with the UN and ITU to deliver the QC-FLIQ hackathon for the International Year of Quantum (500+ attendees)."
] ]
}, },
{ {
@ -150,8 +255,8 @@
"org": "Undergraduate Quantum Association", "org": "Undergraduate Quantum Association",
"dates": "Jan 2025 – Present", "dates": "Jan 2025 – Present",
"bullets": [ "bullets": [
"Led programming, partnerships, and outreach after four years as an officer.", "Led organizational strategy, programming, and outreach after serving as an officer since 2020.",
"Hosted the Quantum Leap Career Nexus with 240+ attendees across IBM, Microsoft, Amazon Braket, IonQ, and more." "Produced the Quantum Leap Career Nexus with 240+ attendees and partners including IBM, Microsoft, and IonQ."
] ]
}, },
{ {
@ -160,8 +265,8 @@
"org": "ACM@UMD", "org": "ACM@UMD",
"dates": "Sep 2023 – Present", "dates": "Sep 2023 – Present",
"bullets": [ "bullets": [
"Restarted the official student chapter and launched a new web presence.", "Restarted the university chapter, launched a new website, and grew membership beyond 145 students.",
"Grew membership to 145+ students with workshops on shell scripting, AI, and quantum computing." "Led workshops focused on shell scripting, AI, quantum computing, and heuristic search techniques."
] ]
} }
], ],
@ -181,7 +286,7 @@
"title": "A Very Quick Guide to Special Relativity", "title": "A Very Quick Guide to Special Relativity",
"status": "Published — 2021", "status": "Published — 2021",
"bullets": [ "bullets": [
"Wrote and published an accessible primer covering time dilation through mass-energy equivalence.", "Authored and published an accessible primer covering time dilation through mass–energy equivalence.",
"Focused on first-principles explanations for students exploring modern physics." "Focused on first-principles explanations for students exploring modern physics."
] ]
} }

@ -9,23 +9,24 @@
# CANONICAL RESUME SOURCE — SINGLE SOURCE OF TRUTH # CANONICAL RESUME SOURCE — SINGLE SOURCE OF TRUTH
# #
# This file is the one authoritative home for every résumé fact. The terminal # This file is the one authoritative home for every résumé fact. The terminal
# (ls / sumfetch / summary) and the plain résumé page both read `resume.json`, # (ls / sumfetch / summary) and the plain résumé page (resume.html) are both
# which is a DECLARED MIRROR generated from this file by: # generated from `resume.json`, which is a DECLARED MIRROR of this file:
# #
# node scripts/org-to-json.mjs resume.org resume.json # node scripts/org-to-json.mjs resume.org resume.json (org -> json)
# node scripts/build-resume-html.mjs (json -> resume.html)
# #
# Flow is one-way: org -> json. Never hand-edit resume.json; edit THIS file and # Flow is one-way. Never hand-edit resume.json or public/resume.html; edit THIS
# regenerate. CI re-runs the parser and fails on any diff (the canary). # file and regenerate. CI re-runs the parser and fails on any diff (the canary).
# #
# SCHEMA the parser expects (RESUME_SCHEMA: 1): # SCHEMA (RESUME_SCHEMA: 1):
# * Section top-level headings name the sections below. # * Section top-level headings name the sections below.
# ** Item each item is a roam node: it carries its own :ID: and # ** Item each item is a roam node: its own :ID: + scalar fields in
# typed scalar fields in a :PROPERTIES: drawer. # a :PROPERTIES: drawer (role/company/dates/subtitle/…).
# - bullet plain list items become the item's `bullets` array. # - bullet plain list items become the item's `bullets` array.
# - tag :: value tagged bullets route into named arrays (education uses # - tech :: X tech tags for a card (experience/projects).
# `degree`, `honor`, `course`). # - degree/honor/course :: X education sub-lists.
# Add a new experience/project/etc. by copying an item heading, minting a fresh # Add an item by copying an item heading, minting a fresh :ID: (org-id-get-create
# :ID: (`org-id-get-create` in Emacs, or `uuidgen`), and filling the drawer. # or uuidgen), and filling the drawer + bullets.
# ============================================================================ # ============================================================================
* Profile * Profile
@ -48,102 +49,180 @@ hardware, game development and literature.
:PROPERTIES: :PROPERTIES:
:ID: 809dd6f7-7700-43ae-ac87-ae2ec79ab4ef :ID: 809dd6f7-7700-43ae-ac87-ae2ec79ab4ef
:ROLE: Researcher :ROLE: Researcher
:COMPANY: CAAR REU (QuICS) :COMPANY: CAAR REU
:SUBTITLE: Combinatorics, Algorithms, and AI for Real Problems
:LOCATION: QuICS · University of Maryland
:DATES: Jun 2025 – Aug 2025 :DATES: Jun 2025 – Aug 2025
:END: :END:
- Created families of fault-tolerant CSS quantum error-correcting codes for qudits. - tech :: Python
- Proved transversal Clifford and T gate support using finite field and QEC theory. - tech :: Galois
- Built parallel Python tooling (Galois, NumPy, Magma, SageMath) to test self-orthogonality and distance. - tech :: NumPy
- tech :: Magma Math
- tech :: SageMath
- Designed novel fault-tolerant CSS quantum error-correcting codes for qudits inspired by quadratic residue codes.
- Established code families with transversal Clifford and T gate support through finite field and QEC theory proofs.
- Implemented parallel Python tooling to validate self-orthogonality and distance properties across large search spaces.
** Undergraduate Researcher — Bright Beams Collective (IREAP) ** Undergraduate Researcher — Bright Beams Collective (IREAP)
:PROPERTIES: :PROPERTIES:
:ID: 4ee96812-4a42-4fce-ab41-223dc3237ed1 :ID: 4ee96812-4a42-4fce-ab41-223dc3237ed1
:ROLE: Undergraduate Researcher :ROLE: Undergraduate Researcher
:COMPANY: Bright Beams Collective (IREAP) :COMPANY: Bright Beams Collective
:SUBTITLE: IREAP Research Experience for Undergraduates
:LOCATION: Institute for Research in Electronics and Applied Physics
:DATES: Sep 2023 – Dec 2024 :DATES: Sep 2023 – Dec 2024
:END: :END:
- Designed machine learning and gradient optimizers for particle accelerator beamline tuning. - tech :: MAD-X
- Ran MAD-X and Elegant simulations to evaluate lattice stability and beam quality. - tech :: Elegant
- Produced Fusion 360 and Ansys visualizations for educational and technical presentations. - tech :: Fusion 360
- tech :: MATLAB
- tech :: Ansys Workbench
- Built custom machine learning and gradient-based optimizers to derive design parameters for a planned beamline.
- Ran accelerator simulations to analyze lattice stability and beam quality under varied operating configurations.
- Produced animations of betatron motion for outreach presentations and technical discussions.
** Software Engineering Intern — JODO PAY ** Software Engineering Intern — JODO PAY
:PROPERTIES: :PROPERTIES:
:ID: 9ca345ca-c318-4d70-aa4d-8542bc322589 :ID: 9ca345ca-c318-4d70-aa4d-8542bc322589
:ROLE: Software Engineering Intern :ROLE: Software Engineering Intern
:COMPANY: JODO PAY :COMPANY: JODO PAY
:SUBTITLE: Invoicing System Automation
:DATES: Jun 2022 – Jul 2022 :DATES: Jun 2022 – Jul 2022
:END: :END:
- Automated invoice generation and delivery via Google Workspace APIs. - tech :: JavaScript
- Reduced manual processing by approximately 40 staff hours each week. - tech :: TypeScript
- Hardened error handling and template management with TypeScript and Apps Script. - tech :: Google Apps Script
- Automated invoice generation and dispatch for clients, reducing manual processing by 40 staff hours each week.
- Integrated Google Workspace APIs to manage templates, customer data, and error handling workflows.
* Projects * Projects
** Quantum State Tomography via QML ** Quantum State Tomography via QML
:PROPERTIES: :PROPERTIES:
:ID: 28f564fa-8ac8-4720-bf5c-cf999186cf6d :ID: 28f564fa-8ac8-4720-bf5c-cf999186cf6d
:NAME: Quantum State Tomography via QML :NAME: Quantum State Tomography via QML
:SUBTITLE: GitHub · github.com/Mihir-Null
:TIMELINE: Sep 2024 – Jul 2025 :TIMELINE: Sep 2024 – Jul 2025
:END: :END:
- Co-developed variational circuit tomography with custom losses and embeddings. - tech :: Python
- Launched 2,000+ experiments across multi-GPU clusters via bespoke orchestration tools. - tech :: Qiskit
- Co-author on "Quantum state reconstruction with variational quantum circuit" (arXiv:2507.01246). - tech :: Aer
- tech :: MPI
- tech :: Numba
- tech :: PyTorch
- Co-developed a variational circuit tomography approach, exploring loss landscapes, embedding strategies, and optimizers.
- Executed 2,000+ experiments across multi-GPU clusters with a custom orchestrator for reproducible benchmarking.
- Co-authored "Quantum state reconstruction with variational quantum circuit" (arXiv:2507.01246).
** MIT iQuHack — QuEra Challenge ** MIT iQuHack — QuEra Challenge
:PROPERTIES: :PROPERTIES:
:ID: 25c4d9b7-ea24-4af7-8cac-f1855743abc6 :ID: 25c4d9b7-ea24-4af7-8cac-f1855743abc6
:NAME: MIT iQuHack — QuEra Challenge :NAME: MIT iQuHack — QuEra Challenge
:SUBTITLE: Honorable Mention
:TIMELINE: Feb 2025 :TIMELINE: Feb 2025
:END: :END:
- Built a compilation pipeline translating QAOA and error-correcting circuits into neutral atom instructions. - tech :: Python
- Optimized pulse schedules using Qiskit, Cirq, Bloqade, PyTorch, and TensorFlow Quantum. - tech :: Qiskit
- Team earned an Honorable Mention from QuEra. - tech :: Cirq
- tech :: Bloqade
- tech :: PyTorch
- tech :: TensorFlow Quantum
- Designed a compilation pipeline mapping diverse quantum circuits — including QAOA and Steane codes — to QuEra hardware.
- Optimized pulse sequences for neutral atom instruction sets, contributing to the team's honorable mention finish.
** Quantum Machine Learning Research
:PROPERTIES:
:ID: 5a0897f1-4b2c-4dd4-a68e-8a324822f425
:NAME: Quantum Machine Learning Research
:SUBTITLE: Undergraduate Research Portfolio
:TIMELINE: Aug 2023 – Dec 2024
:END:
- tech :: Python
- tech :: Qiskit
- tech :: Cirq
- tech :: PennyLane
- tech :: Q#
- Implemented quantum image processing with parameterized circuit kernels integrated into CNN architectures.
- Created a hybrid transitional optimizer to mitigate barren plateaus in QAOA, presented at the FYIRE Summit 2024.
** Terrapin Rocket Team — Kalman Filters
:PROPERTIES:
:ID: 81fadb40-43da-4f62-805a-686b65bdf5f8
:NAME: Terrapin Rocket Team — Kalman Filters
:SUBTITLE: Guidance, Navigation, and Control
:TIMELINE: Aug 2023 – Jan 2024
:END:
- tech :: C
- tech :: C++
- tech :: MATLAB
- Developed six- and nine-state Kalman filters fusing multi-sensor telemetry for rocket position estimation.
- Supported the team's winning entry at the 2024 Spaceport America Cup.
** Robotics @ UMD — Computer Vision
:PROPERTIES:
:ID: 6fd996da-74d7-4e3c-9ac0-dc6a23d484d4
:NAME: Robotics @ UMD — Computer Vision
:SUBTITLE: Testudog Automation
:TIMELINE: Aug 2023 – Jan 2024
:END:
- tech :: Python
- tech :: OpenCV
- tech :: scikit-learn
- Developed Haar cascade pipelines for the Testudog robotics platform deployed on a Jetson-powered Boston Dynamics Spot.
** Club Administration Automation ** Club Administration Automation
:PROPERTIES: :PROPERTIES:
:ID: e00b83aa-277b-4379-96aa-989754fefbcb :ID: e00b83aa-277b-4379-96aa-989754fefbcb
:NAME: Club Administration Automation :NAME: Club Administration Automation
:SUBTITLE: Workflow Automation Suite
:TIMELINE: Nov 2024 – Feb 2025 :TIMELINE: Nov 2024 – Feb 2025
:END: :END:
- Automated Discord announcements, email campaigns, Instagram posts, and room reservations. - tech :: Python
- Integrated Google APIs, Discord.py, Selenium, and OAuth2 for end-to-end workflows. - tech :: Selenium
- Adopted by multiple university clubs to reduce administrative effort. - tech :: Discord.py
- tech :: REST APIs
** Quantum ML Research Collection - tech :: OAuth 2.0
:PROPERTIES: - Automated Discord announcements, email campaigns, Instagram publishing, and room reservations for university clubs.
:ID: 5a0897f1-4b2c-4dd4-a68e-8a324822f425 - Currently deployed across multiple organizations to streamline administrative overhead.
:NAME: Quantum ML Research Collection
:TIMELINE: Aug 2023 – Dec 2024
:END:
- Crafted quantum image processing pipelines with parameterized kernels inside CNNs.
- Designed a hybrid transitional optimizer that mitigates barren plateaus in QAOA.
- Presented findings at the 2024 First Year Innovation & Research Experience Summit.
** Housing Market Analysis ** Housing Market Analysis
:PROPERTIES: :PROPERTIES:
:ID: 25053703-72e2-492d-bf8b-4a5953b6160e :ID: 25053703-72e2-492d-bf8b-4a5953b6160e
:NAME: Housing Market Analysis :NAME: Housing Market Analysis
:SUBTITLE: Predictive Pricing Models
:TIMELINE: Jun 2024 – Jul 2024 :TIMELINE: Jun 2024 – Jul 2024
:END: :END:
- Built feedforward neural networks to predict housing prices from public datasets. - tech :: Python
- Applied PCA and statistical analysis to surface high-signal features. - tech :: Pandas
- Combined web-scraped listings with census data to improve model robustness. - tech :: SciPy
- tech :: NumPy
- tech :: scikit-learn
- tech :: SQL
- Trained feedforward neural networks for price prediction using engineered features derived from public listings and census data.
- Applied PCA and statistical analysis to identify high-signal attributes and reduce overfitting.
** Indie Game Development ** Independent Game Development
:PROPERTIES: :PROPERTIES:
:ID: bdf83287-24aa-4f55-9a07-e11d6e08e319 :ID: bdf83287-24aa-4f55-9a07-e11d6e08e319
:NAME: Indie Game Development :NAME: Independent Game Development
:SUBTITLE: National Game Jam Winner
:TIMELINE: 2020 – 2023 :TIMELINE: 2020 – 2023
:END: :END:
- Shipped two action platformers with custom soft-body simulation via Unity/Unreal. - tech :: C#
- 2nd place, 2021 Mindbox National Design Championship (Game Design). - tech :: C++
- National finalist, 2020 Mindbox Design Championship (Game Development). - tech :: Unity
- Authored a procedural map generation toolkit for arbitrary tilemaps. - tech :: Unreal Engine
- tech :: Blender
- tech :: Adobe Suite
- Published two action platformers, including a custom 2D soft-body simulation available via Two Guys Studios on itch.io.
- Placed second in the 2021 Mindbox National Design Championship; finalist in the 2020 edition.
- Built a procedural map generation toolkit leveraging noise algorithms and custom pathfinding.
* Education * Education
** University of Maryland — College Park ** University of Maryland — College Park
:PROPERTIES: :PROPERTIES:
:ID: 86d31d81-d7e2-4035-9441-54badb1724a7 :ID: 86d31d81-d7e2-4035-9441-54badb1724a7
:SCHOOL: University of Maryland — College Park :SCHOOL: University of Maryland — College Park
:SUBTITLE: Computer Science (Honors) · Physics (Honors)
:GPA: 3.974 :GPA: 3.974
:GRADUATION: May 2027 :GRADUATION: May 2027
:END: :END:
@ -153,12 +232,17 @@ hardware, game development and literature.
- honor :: John D. Gannon Scholarship — Computer Science - honor :: John D. Gannon Scholarship — Computer Science
- honor :: Dean's List — Every Semester - honor :: Dean's List — Every Semester
- course :: Graduate Quantum Computing (CMSC657) - course :: Graduate Quantum Computing (CMSC657)
- course :: Computer Science Honors Seminar
- course :: Differentiable Programming for Agentic AI (CMSC498Z) - course :: Differentiable Programming for Agentic AI (CMSC498Z)
- course :: Natural Language Processing (CMSC470) - course :: Natural Language Processing (CMSC470)
- course :: Data Science (CMSC320) - course :: Data Science (CMSC320)
- course :: Design & Analysis of Algorithms (CMSC451) - course :: Design & Analysis of Algorithms (CMSC451)
- course :: Object-Oriented Programming in Java (CMSC132)
- course :: Applied Probability & Statistics (STAT400)
- course :: Honors Advanced Modern Physics (PHYS400) - course :: Honors Advanced Modern Physics (PHYS400)
- course :: Quantum Mechanics II (PHYS402) - course :: Quantum Mechanics II (PHYS402)
- course :: Multivariate Calculus
- course :: Differential Equations
* Organizations * Organizations
** Industry Chair — Quantum Coalition ** Industry Chair — Quantum Coalition
@ -168,8 +252,8 @@ hardware, game development and literature.
:ORG: Quantum Coalition :ORG: Quantum Coalition
:DATES: Jan 2024 – Present :DATES: Jan 2024 – Present
:END: :END:
- Co-organized the QRISE research competition with 200+ global participants. - Co-organized the QRISE research competition with 200+ international participants.
- Partnered with the UN and ITU to deliver the QC-FLIQ hackathon (500+ attendees). - Partnered with the UN and ITU to deliver the QC-FLIQ hackathon for the International Year of Quantum (500+ attendees).
** President — Undergraduate Quantum Association ** President — Undergraduate Quantum Association
:PROPERTIES: :PROPERTIES:
@ -178,8 +262,8 @@ hardware, game development and literature.
:ORG: Undergraduate Quantum Association :ORG: Undergraduate Quantum Association
:DATES: Jan 2025 – Present :DATES: Jan 2025 – Present
:END: :END:
- Led programming, partnerships, and outreach after four years as an officer. - Led organizational strategy, programming, and outreach after serving as an officer since 2020.
- Hosted the Quantum Leap Career Nexus with 240+ attendees across IBM, Microsoft, Amazon Braket, IonQ, and more. - Produced the Quantum Leap Career Nexus with 240+ attendees and partners including IBM, Microsoft, and IonQ.
** Co-President — ACM@UMD ** Co-President — ACM@UMD
:PROPERTIES: :PROPERTIES:
@ -188,8 +272,8 @@ hardware, game development and literature.
:ORG: ACM@UMD :ORG: ACM@UMD
:DATES: Sep 2023 – Present :DATES: Sep 2023 – Present
:END: :END:
- Restarted the official student chapter and launched a new web presence. - Restarted the university chapter, launched a new website, and grew membership beyond 145 students.
- Grew membership to 145+ students with workshops on shell scripting, AI, and quantum computing. - Led workshops focused on shell scripting, AI, quantum computing, and heuristic search techniques.
* Publications * Publications
** Quantum state reconstruction with variational quantum circuit ** Quantum state reconstruction with variational quantum circuit
@ -208,7 +292,7 @@ hardware, game development and literature.
:TITLE: A Very Quick Guide to Special Relativity :TITLE: A Very Quick Guide to Special Relativity
:STATUS: Published — 2021 :STATUS: Published — 2021
:END: :END:
- Wrote and published an accessible primer covering time dilation through mass-energy equivalence. - Authored and published an accessible primer covering time dilation through mass–energy equivalence.
- Focused on first-principles explanations for students exploring modern physics. - Focused on first-principles explanations for students exploring modern physics.
* Skills * Skills

@ -0,0 +1,450 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Mihir Talati – Resume</title>
<style>
:root {
--content-max-width: 960px;
--primary-text: #d9ffe2;
--secondary-text: rgba(182, 255, 210, 0.75);
--accent: #9acd32;
--card-bg: rgba(4, 30, 16, 0.82);
--card-border: rgba(98, 255, 164, 0.35);
--page-bg: radial-gradient(
circle at top,
rgba(10, 40, 22, 0.85) 0%,
rgba(1, 12, 5, 1) 55%
);
--tag-bg: rgba(82, 255, 160, 0.12);
--tag-border: rgba(146, 255, 197, 0.45);
--filter-border: rgba(146, 255, 197, 0.35);
--filter-focus: rgba(154, 205, 50, 0.45);
--glass-highlight: rgba(146, 255, 197, 0.06);
}
@keyframes scanline {
0% {
transform: translateY(-100%);
}
100% {
transform: translateY(100%);
}
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: 'IBM Plex Mono', 'Fira Code', ui-monospace, SFMono-Regular,
Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
background: #010805;
background-image: var(--page-bg);
color: var(--primary-text);
line-height: 1.65;
letter-spacing: 0.01em;
text-shadow: 0 0 6px rgba(146, 255, 197, 0.18);
position: relative;
overflow-x: hidden;
min-height: 100vh;
}
body::before {
content: '';
position: fixed;
inset: 0;
pointer-events: none;
background: linear-gradient(
rgba(255, 255, 255, 0.04) 0%,
rgba(0, 0, 0, 0) 50%,
rgba(255, 255, 255, 0.04) 100%
);
background-size: 100% 3px;
opacity: 0.25;
mix-blend-mode: overlay;
}
body::after {
content: '';
position: fixed;
left: 0;
right: 0;
top: -100%;
height: 120%;
pointer-events: none;
background: linear-gradient(
to bottom,
rgba(154, 205, 50, 0) 0%,
rgba(154, 205, 50, 0.12) 50%,
rgba(154, 205, 50, 0) 100%
);
animation: scanline 6s linear infinite;
opacity: 0.25;
}
.container {
max-width: var(--content-max-width);
margin: 0 auto;
padding: 64px 32px 96px;
}
header {
text-align: center;
margin-bottom: 56px;
}
header h1 {
margin: 0;
font-size: 2.6rem;
letter-spacing: 0.1em;
text-transform: uppercase;
color: #eafff5;
}
header p {
margin: 12px 0 0;
color: var(--secondary-text);
font-size: 1.05rem;
}
section + section {
margin-top: 56px;
}
.section-title {
font-size: 1.2rem;
font-weight: 700;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--accent);
margin-bottom: 20px;
}
.card {
position: relative;
border-radius: 20px;
padding: 32px 36px;
background: var(--card-bg);
border: 1px solid var(--card-border);
box-shadow: 0 0 0 1px rgba(154, 205, 50, 0.18),
0 24px 48px rgba(10, 60, 30, 0.45);
backdrop-filter: blur(6px) saturate(120%);
}
.card::after {
content: '';
position: absolute;
inset: 12px;
border-radius: 14px;
border: 1px solid rgba(146, 255, 197, 0.08);
pointer-events: none;
}
.card + .card {
margin-top: 28px;
}
.card-header {
display: flex;
flex-wrap: wrap;
gap: 12px 16px;
align-items: baseline;
justify-content: space-between;
margin-bottom: 20px;
position: relative;
z-index: 1;
}
.card-title {
margin: 0;
font-size: 1.2rem;
font-weight: 600;
letter-spacing: 0.04em;
color: #e5ffe9;
}
.card-subtitle {
margin: 0;
font-weight: 500;
color: var(--secondary-text);
}
.card-meta {
text-align: right;
color: var(--secondary-text);
font-size: 0.95rem;
}
.meta-line {
display: block;
}
.tag-list {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin: 0 0 20px;
padding: 0;
list-style: none;
position: relative;
z-index: 1;
}
.tag {
display: inline-flex;
align-items: center;
padding: 5px 14px;
border-radius: 999px;
border: 1px solid var(--tag-border);
background: var(--tag-bg);
color: #9df5ba;
font-size: 0.85rem;
font-weight: 600;
letter-spacing: 0.02em;
box-shadow: inset 0 0 12px rgba(146, 255, 197, 0.12);
}
ul.bullet-list {
margin: 0;
padding-left: 22px;
position: relative;
z-index: 1;
}
ul.bullet-list li {
margin-bottom: 12px;
color: var(--primary-text);
}
ul.bullet-list li:last-child {
margin-bottom: 0;
}
.education-grid {
display: grid;
gap: 32px;
}
.scholarships {
margin-top: 20px;
padding-top: 18px;
border-top: 1px solid rgba(146, 255, 197, 0.24);
}
.scholarships-title {
font-weight: 600;
margin: 0 0 10px;
color: rgba(182, 255, 210, 0.85);
letter-spacing: 0.08em;
text-transform: uppercase;
font-size: 0.75rem;
}
.courses-card {
background: linear-gradient(
160deg,
rgba(8, 40, 18, 0.9) 0%,
rgba(2, 16, 8, 0.92) 65%,
rgba(4, 24, 12, 0.96) 100%
);
border-radius: 24px;
padding: 36px;
border: 1px solid rgba(146, 255, 197, 0.4);
box-shadow: 0 30px 60px rgba(6, 40, 18, 0.5);
position: relative;
overflow: hidden;
}
.courses-card::before {
content: '';
position: absolute;
inset: -60px 20% 40%;
background: radial-gradient(
circle,
rgba(146, 255, 197, 0.28) 0%,
rgba(146, 255, 197, 0) 65%
);
opacity: 0.65;
pointer-events: none;
}
.filter-label {
display: block;
font-weight: 600;
letter-spacing: 0.18em;
text-transform: uppercase;
font-size: 0.75rem;
color: rgba(182, 255, 210, 0.78);
margin-bottom: 8px;
position: relative;
z-index: 1;
}
.filter-input {
width: 100%;
padding: 14px 18px;
border-radius: 12px;
border: 1px solid var(--filter-border);
font-size: 1rem;
background: rgba(2, 18, 9, 0.92);
color: var(--primary-text);
transition: border-color 0.2s ease, box-shadow 0.2s ease;
text-shadow: inherit;
position: relative;
z-index: 1;
}
.filter-input::placeholder {
color: rgba(182, 255, 210, 0.45);
}
.filter-input:focus {
outline: none;
border-color: var(--filter-focus);
box-shadow: 0 0 0 4px rgba(154, 205, 50, 0.18);
}
.courses-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 14px;
margin-top: 26px;
position: relative;
z-index: 1;
}
.course-pill {
background: rgba(6, 28, 14, 0.9);
border-radius: 16px;
padding: 12px 16px;
border: 1px solid rgba(146, 255, 197, 0.4);
font-weight: 500;
color: var(--primary-text);
box-shadow: inset 0 0 12px rgba(146, 255, 197, 0.08),
0 16px 32px rgba(6, 40, 18, 0.45);
transition: transform 0.15s ease, box-shadow 0.15s ease,
border-color 0.15s ease;
}
.course-pill:hover {
transform: translateY(-2px);
border-color: rgba(154, 205, 50, 0.65);
box-shadow: inset 0 0 14px rgba(146, 255, 197, 0.12),
0 18px 36px rgba(10, 60, 30, 0.55);
}
.course-pill.hidden {
display: none;
}
.empty-state {
display: none;
margin-top: 24px;
padding: 18px;
border-radius: 14px;
background: rgba(4, 20, 10, 0.75);
border: 1px dashed rgba(146, 255, 197, 0.5);
color: rgba(212, 255, 225, 0.82);
text-align: center;
font-weight: 500;
position: relative;
z-index: 1;
}
a {
color: var(--accent);
}
@media (max-width: 720px) {
header h1 {
font-size: 2.1rem;
}
.card {
padding: 26px;
}
.card-header {
flex-direction: column;
align-items: flex-start;
}
.card-meta {
text-align: left;
}
.courses-grid {
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
}
}
</style>
<style>
/* generated-page additions */
.toolbar {
margin-bottom: 40px;
}
.hidden {
display: none !important;
}
section.hidden {
display: none;
}
.card[data-search] {
scroll-margin-top: 20px;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>{{NAME}}</h1>
<p>{{HEADER_SUB}}</p>
</header>
<div class="courses-card toolbar">
<label class="filter-label" for="global-search">Search résumé</label>
<input
class="filter-input"
id="global-search"
type="search"
placeholder="Filter by keyword, tech, or course…"
autocomplete="off"
/>
</div>
{{SECTIONS}}
<div class="empty-state" id="global-empty">
No entries match that search. Try a broader keyword.
</div>
</div>
<script>
const search = document.getElementById('global-search');
const empty = document.getElementById('global-empty');
const items = Array.from(document.querySelectorAll('[data-search]'));
const sections = Array.from(
document.querySelectorAll('main section, .container section'),
);
function apply(value) {
const q = value.trim().toLowerCase();
let total = 0;
items.forEach((el) => {
const hit = el.getAttribute('data-search').includes(q);
el.classList.toggle('hidden', !hit);
if (hit) total += 1;
});
sections.forEach((sec) => {
const vis = sec.querySelectorAll('[data-search]:not(.hidden)').length;
sec.classList.toggle('hidden', vis === 0);
});
empty.style.display = total === 0 ? 'block' : 'none';
}
search.addEventListener('input', (e) => apply(e.target.value));
</script>
</body>
</html>

@ -0,0 +1,248 @@
#!/usr/bin/env node
// =============================================================================
// Module contract (praxis: Contract-First Modules · Tangle Discipline)
//
// provides — render the plain résumé page (public/resume.html) from the
// resume.json mirror + resume.template.html. One concern: json ->
// styled HTML. The template owns the design (hand-maintained); the
// content is generated so the plain page and terminal share one
// source (Single Source of Truth).
// requires — resume.json (generated from resume.org), resume.template.html.
// tests must show —
// * every section renders one card per item with its bullets/tech/meta;
// * courses render as filterable pills; each card/pill has data-search;
// * output is byte-stable so the CI canary (regen + diff) only trips on
// real drift; text is HTML-escaped; arXiv ids linkify.
//
// Flow is ONE-WAY: resume.json -> public/resume.html. Never hand-edit the
// generated page; edit resume.org (content) or resume.template.html (design).
// Usage: node scripts/build-resume-html.mjs [--check]
// =============================================================================
import { readFileSync, writeFileSync } from 'node:fs';
const SRC = 'resume.json';
const TEMPLATE = 'resume.template.html';
const OUT = 'public/resume.html';
const esc = (s = '') =>
String(s)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
// arXiv ids become links; run after escaping (ids are digits/dots, escape-safe).
const linkifyArxiv = (s) =>
s.replace(
/arXiv:(\d{4}\.\d{4,5})/gi,
(_m, id) => `<a href="https://arxiv.org/abs/${id}">arXiv:${id}</a>`,
);
const searchKey = (...parts) =>
esc(
parts.flat().filter(Boolean).join(' ').toLowerCase().replace(/\s+/g, ' '),
);
const tagList = (tech) =>
tech && tech.length
? `\n <ul class="tag-list">${tech
.map((t) => `<li class="tag">${esc(t)}</li>`)
.join('')}</ul>`
: '';
const bulletList = (bullets) =>
bullets && bullets.length
? `\n <ul class="bullet-list">${bullets
.map((x) => `<li>${linkifyArxiv(esc(x))}</li>`)
.join('')}</ul>`
: '';
const metaBlock = (lines) => {
const kept = lines.filter(Boolean);
if (!kept.length) return '';
return `\n <div class="card-meta">${kept
.map((l) => `<span class="meta-line">${esc(l)}</span>`)
.join('')}</div>`;
};
const card = ({ title, subtitle, meta = [], tech, bullets, search }) => `
<article class="card" data-search="${search}">
<div class="card-header">
<div>
<h3 class="card-title">${esc(title)}</h3>${
subtitle ? `\n <p class="card-subtitle">${esc(subtitle)}</p>` : ''
}
</div>${metaBlock(meta)}
</div>${tagList(tech)}${bulletList(bullets)}
</article>`;
const section = (id, heading, inner) =>
` <section id="${id}">\n <h2 class="section-title">${esc(
heading,
)}</h2>\n${inner}\n </section>`;
function render(data) {
const {
profile,
experience,
projects,
organizations,
publications,
education,
} = data;
const edu = education[0] || {};
const eduCard = card({
title: edu.school,
subtitle: edu.subtitle,
meta: [`Expected Graduation · ${edu.graduation}`, `GPA · ${edu.gpa}`],
bullets: null,
search: searchKey(edu.school, edu.subtitle, edu.degrees, edu.honors),
});
const eduScholar =
edu.honors && edu.honors.length
? `\n <div class="scholarships">\n <p class="scholarships-title">Scholarships &amp; Distinctions</p>\n <ul class="bullet-list">${edu.honors
.map((h) => `<li>${esc(h)}</li>`)
.join('')}</ul>\n </div>`
: '';
// inject scholarships before the closing </article> of the education card
const eduHtml = eduCard.replace(
'\n </article>',
`${eduScholar}\n </article>`,
);
const educationSection = section(
'education',
'Education',
` <div class="education-grid">${eduHtml}\n </div>`,
);
const experienceSection = section(
'work',
'Work Experience',
experience
.map((e) =>
card({
title: `${e.role} · ${e.company}`,
subtitle: e.subtitle,
meta: [e.dates, e.location],
tech: e.tech,
bullets: e.bullets,
search: searchKey(
e.role,
e.company,
e.subtitle,
e.location,
e.tech,
e.bullets,
),
}),
)
.join('\n'),
);
const projectsSection = section(
'projects',
'Projects',
projects
.map((p) =>
card({
title: p.name,
subtitle: p.subtitle,
meta: [p.timeline],
tech: p.tech,
bullets: p.bullets,
search: searchKey(p.name, p.subtitle, p.tech, p.bullets),
}),
)
.join('\n'),
);
const orgsSection = section(
'organizations',
'Organizations',
organizations
.map((o) =>
card({
title: `${o.role} · ${o.org}`,
meta: [o.dates],
bullets: o.bullets,
search: searchKey(o.role, o.org, o.bullets),
}),
)
.join('\n'),
);
const pubsSection = section(
'publications',
'Publications',
publications
.map((p) =>
card({
title: p.title,
subtitle: p.status,
bullets: p.bullets,
search: searchKey(p.title, p.status, p.bullets),
}),
)
.join('\n'),
);
const pills = (edu.coursework || [])
.map(
(c) =>
` <span class="course-pill" data-search="${searchKey(
c,
)}">${esc(c)}</span>`,
)
.join('\n');
const coursesSection = section(
'courses',
'Relevant Courses',
` <div class="courses-card">\n <div class="courses-grid" id="courses-grid">\n${pills}\n </div>\n </div>`,
);
const sections = [
educationSection,
experienceSection,
projectsSection,
orgsSection,
pubsSection,
coursesSection,
].join('\n\n');
const headerSub = `Dual Degree · ${(edu.degrees || []).join(' & ')} · GPA ${
edu.gpa
}`;
return readFileSync(TEMPLATE, 'utf8')
.replace('{{NAME}}', esc(profile.name))
.replace('{{HEADER_SUB}}', esc(headerSub))
.replace('{{SECTIONS}}', sections);
}
function main() {
const check = process.argv.includes('--check');
const html = render(JSON.parse(readFileSync(SRC, 'utf8')));
if (check) {
let current = '';
try {
current = readFileSync(OUT, 'utf8');
} catch {
/* missing counts as drift */
}
if (current !== html) {
process.stderr.write(
`DRIFT: ${OUT} is out of sync. Run: node scripts/build-resume-html.mjs\n`,
);
process.exit(1);
}
process.stdout.write(`ok: ${OUT} matches ${SRC}\n`);
return;
}
writeFileSync(OUT, html);
process.stdout.write(`wrote ${OUT} from ${SRC}\n`);
}
main();

@ -28,17 +28,35 @@ const GENERATED_NOTE =
'Regenerate: node scripts/org-to-json.mjs'; 'Regenerate: node scripts/org-to-json.mjs';
// Section registry — the fixed schema the parser understands. // Section registry — the fixed schema the parser understands.
// `fields` are optional scalar drawer props (included only when present);
// `tagged` routes `- k :: v` bullets into named arrays; `list: false` means
// the item has no free-form bullets array (education is all tagged).
const SECTIONS = { const SECTIONS = {
profile: { kind: 'profile' }, profile: { kind: 'profile' },
experience: { kind: 'items', fields: ['role', 'company', 'dates'] }, experience: {
projects: { kind: 'items', fields: ['name', 'timeline'] }, kind: 'items',
fields: ['role', 'company', 'dates', 'subtitle', 'location'],
tagged: { tech: 'tech' },
list: true,
},
projects: {
kind: 'items',
fields: ['name', 'timeline', 'subtitle'],
tagged: { tech: 'tech' },
list: true,
},
education: { education: {
kind: 'items', kind: 'items',
fields: ['school', 'gpa', 'graduation'], fields: ['school', 'gpa', 'graduation', 'subtitle'],
tagged: { degree: 'degrees', honor: 'honors', course: 'coursework' }, tagged: { degree: 'degrees', honor: 'honors', course: 'coursework' },
list: false,
},
organizations: {
kind: 'items',
fields: ['role', 'org', 'dates'],
list: true,
}, },
organizations: { kind: 'items', fields: ['role', 'org', 'dates'] }, publications: { kind: 'items', fields: ['title', 'status'], list: true },
publications: { kind: 'items', fields: ['title', 'status'] },
skills: { kind: 'skills' }, skills: { kind: 'skills' },
}; };
@ -76,7 +94,10 @@ function makeItem(cfg, props, bullets) {
plain.push(raw); plain.push(raw);
} }
} }
if (!cfg.tagged) item.bullets = plain; // Drop empty tagged arrays so optional groups (e.g. tech) don't add noise.
for (const key of Object.values(tagged))
if (item[key].length === 0) delete item[key];
if (cfg.list) item.bullets = plain;
return item; return item;
} }

@ -17,12 +17,17 @@ export type Experience = {
role: string; role: string;
company: string; company: string;
dates: string; dates: string;
subtitle?: string;
location?: string;
tech?: string[];
bullets: string[]; bullets: string[];
}; };
export type Project = { export type Project = {
id?: string; id?: string;
name: string; name: string;
timeline: string; timeline: string;
subtitle?: string;
tech?: string[];
bullets: string[]; bullets: string[];
}; };
export type Education = { export type Education = {
@ -30,6 +35,7 @@ export type Education = {
school: string; school: string;
gpa: string; gpa: string;
graduation: string; graduation: string;
subtitle?: string;
degrees: string[]; degrees: string[];
honors: string[]; honors: string[];
coursework: string[]; coursework: string[];

Loading…
Cancel
Save