2025Senior Capstone Project
Intelligent EMR Note Generation Service
- TypeScript
- Express.js
- React
- Gemini API
- OpenAPI
- test suites, from unit to live
- 6
- reviewers required on every change
- 2
At a glance
- Microservices-based note generator with secure REST APIs for manual + automated EMR creation.
- Integrated Gemini with dynamically constructed clinical prompts, patient context, and tone control.
- React frontend with real-time preview, validation, and regeneration of AI-generated notes.
- Daily scheduling mechanism for batch note generation across all eligible patients.
- Robust error handling, structured logging, and validation pipelines for clinical accuracy.
- Full-stack docs: OpenAPI/Swagger specs, Prompt Engineering Guide, Deployment Instructions.
Senior capstone built for an industry sponsor: a Note Generation Service that turns a few high-level clinical inputs into a structured, reviewable EMR note via Google Gemini, exposed through a hardened API gateway and reused by both the UI and an automated batch job.
Purpose for developing this project
This was my senior capstone project (SE 4485: Software Engineering Project) at The University of Texas at Dallas, completed for an industry sponsor. The sponsor maintains a Behavioral Health Center (BHCC) Simulator used to model patient encounters and electronic medical record (EMR) workflows. In its original form, clinicians using the simulator had to type every clinical note from scratch: selecting a patient, choosing a note category and sub-category, and manually composing the body of the note. That manual step was slow, inconsistent across users, and a poor reflection of the kind of AI-assisted documentation that real EMR systems are starting to adopt.
Our team was asked to bridge that gap. The purpose of the project was to:
- Reduce documentation burden by generating structured clinical notes from a few high-level inputs (the patient's current state, the type of note needed, and a short summary of the patient journey) instead of forcing a clinician to write every line.
- Introduce a Note Generation Service as a middleware layer that sits between the simulator UI and an LLM (Google Gemini), so note-related logic lives in one well-defined place and can be reused by both the UI and automated jobs.
- Expose a clean RESTful API so the same note-generation capability could be triggered manually from the UI or driven on a schedule by an automated job, enabling the second objective of the project, batch / automated note creation on top of the same architecture.
- Demonstrate production-grade engineering practices: secure API key handling, an API gateway pattern, full test coverage (unit, integration, functional, performance, security), peer-reviewed pull requests, and configuration management, at a level appropriate for a real client deliverable, not a class demo.
Beyond the technical goals, the project gave me a chance to work end-to-end on a problem with real stakeholders: a sponsor with opinions about scope, a faculty advisor evaluating engineering rigor, and a small team that had to coordinate across documents, code, and reviews.
Development process
- Team & cadence. I worked on a four-person team under the SE 4485 capstone framework. We followed an iterative process with weekly sponsor syncs, a written project management plan (revised across multiple versions and tracked in
documents/), and aCHANGELOG.mdthat recorded every meaningful change with version numbers, difference highlights, and named peer reviewers. Every change required at least two reviewers before it could land: a hard rule from our configuration management plan. - Configuration management. We used GitHub as our CM tool, with kebab-case naming for all files, descriptive PR titles linked to tickets, and Husky + lint-staged enforcing ESLint and Prettier on every commit so style never became a code-review topic. Branching followed a simple model: feature branches off
dev, peer review, then merge.
Architecture decisions. Two choices defined the shape of the codebase:
- 1. API Gateway pattern. Rather than calling Gemini and the BHCC API directly from the React app, we built an Express gateway (
server/index.ts) that proxies both. This kept the Gemini API key strictly server-side, gave us a single place to add rate limiting (100 req/15 min in production), CORS rules, input validation, and request size limits, and let us version the Gemini endpoints behind RESTful resource URLs (/api/gemini/models/:modelId/content) instead of leaking Google's URL scheme into the frontend. - 2. Feature-oriented React structure. The UI is React 19 + TypeScript + Vite, with MUI for components, TanStack Query for server state, Formik + Yup for form handling, and React Router for navigation. Code is organized by
pages/,features/,components/,services/, andhooks/so that note-generation logic, patient-census logic, and shared UI live in clearly separated layers.
Building toward the two objectives:
- Objective 1: AI-assisted notes. We built dynamic, schema-driven forms that capture only the high-leverage inputs for each note type, ship them through the gateway to Gemini with a tuned prompt, and return a structured note the user can review and edit before submission to the simulator.
- Objective 2: Automated batch generation. Because the gateway exposes the same RESTful endpoints the UI uses, the batch flow reuses the exact same note-generation pipeline. We added a batch results dialog in the UI to surface per-patient outcomes, but the core logic didn't have to fork.
Testing strategy
Testing was treated as a first-class deliverable, not an afterthought. The repo has six distinct test suites wired up through Vitest:
tests/unit: component and utility-level teststests/integration: gateway + API integration, including a dedicated security suitetests/functional: user-flow tests through the rendered UItests/performance: performance budgetstests/quality: code-quality assertionstests/live: tests that hit live services for end-to-end verification
A separate npm run test:security target runs only the security validation and gateway-security integration tests, which proved useful when reviewing input validation and CORS behavior.
Deployment
The frontend deploys to Azure Static Web Apps via the GitHub Actions workflow in azure-static-web-apps-gentle-rock-0e36fee10.yml, and the gateway runs as a separate Node service. Local development uses npm run dev:full to bring up both processes together.
What I personally took away: the capstone forced me to balance three things at once (writing code a sponsor would actually use, documenting decisions for a faculty review, and coordinating with teammates whose review I couldn't bypass). The hardest, and most valuable, part wasn't the AI integration; it was the discipline of small, reviewed, well-described changes flowing through a CHANGELOG and a CM plan, the way real engineering teams actually ship.