Resident Response Studio
What you'll learn
~25 min- Generate a working Node.js CLI from a single AI prompt
- Transform shorthand notes into professional resident communications with brand-appropriate tone
- Select tone profiles (concierge, firm, de-escalation) and scenario templates (noise, outage, package, delay)
- Add Fair Housing compliance phrasing guardrails
What you’re building
You get a call at 7:45 AM. A resident in 14B is upset about a water shut-off that was supposed to last two hours and is now going on six. Your maintenance lead left you a sticky note that says “14B hot water still out, valve part on backorder, maybe tmrw.” You need to send a response to the resident within the hour — something that acknowledges the problem, sets a realistic expectation, and doesn’t accidentally promise a timeline you can’t keep.
Right now you’d open Outlook, stare at the blank compose window for ten minutes, and cobble together something that’s either too casual or sounds like a legal disclaimer. What if you could type your shorthand notes into a CLI tool and get back a polished, brand-appropriate email in three seconds — with the right tone, the right compliance language, and a follow-up version already drafted?
That is what you will build in the next 20 minutes.
This module isn’t just practice — it’s a tool you can use on Monday morning. By the end, you’ll have built a working resident communication tool that demonstrates exactly what “AI-augmented property management” looks like. This is the artifact you show your regional manager, your Bozzuto leadership team, or a future employer. It proves you can combine property ops expertise with modern tooling to produce real results, fast.
By the end of this lesson you will have a Node.js CLI tool that takes rough notes about a resident issue, applies a tone profile and scenario template, checks for Fair Housing compliance red flags, and outputs a polished Markdown email ready to paste into your resident portal or Outlook. No server. No SaaS subscription. Just a command you run in your terminal.
Input text + tone profile + compliance rules = formatted output. This pattern works for customer support scripts, internal memos, vendor communications — any situation where you need consistent, professional writing from rough notes. The techniques in this lesson transfer directly to non-property contexts.
🔍Domain Primer: Property management terms you'll see in this module
New to property management software? Here are the key terms you’ll encounter:
- PMS (Property Management System) — Software that tracks leases, work orders, resident communications, and financials for an apartment community. Examples: Yardi Voyager, RealPage, Entrata, AppFolio. Think of it as the “operating system” for a property — every resident interaction, payment, and maintenance request flows through it.
- Fair Housing Act — Federal law that prohibits discrimination in housing based on race, color, religion, national origin, sex, familial status, or disability. In resident communications, this means you cannot use language that implies preference or restriction based on these protected classes. Even well-intentioned phrasing like “perfect for young professionals” or “quiet community” can create legal exposure. Your tool will flag these patterns.
- Brand voice — For luxury communities like The Concord Crystal City (a 413-unit, 18-story Bozzuto-managed property), communications must feel warm but professional. Bozzuto’s brand emphasizes hospitality-level service. That means “We understand this is frustrating” instead of “Sorry about that,” and “Our maintenance team is prioritizing your request” instead of “We’ll get to it.” The difference between a 3-star and 5-star Google review often comes down to how the first response email reads.
- De-escalation — A communication approach used when a resident is upset or threatening negative action (bad review, withholding rent, contacting corporate). De-escalation language acknowledges emotion without accepting blame, offers concrete next steps, and avoids defensive phrasing.
- SLA (Service Level Agreement) — The maximum time allowed to respond to or resolve different types of maintenance requests. Emergency requests (leaks, no heat, fire safety) typically have a 4-hour SLA. Routine requests (squeaky door, cosmetic damage) might have a 48-72 hour SLA. Your tool will reference these timelines.
You don’t need to be a property management expert to build this tool — the AI handles the code. But knowing these terms helps you understand what the tool is doing and why each feature matters.
Who this is for
- Community managers who write 10-20 resident emails per day and need consistent, professional tone across every one.
- Assistant managers and leasing consultants covering the desk who need to respond to complaints without guessing at the right language.
- Regional managers who want every property in their portfolio using compliant, brand-appropriate communications.
The Concord is a 413-unit, 18-story luxury apartment community in Crystal City, Arlington, VA — managed by Bozzuto. Amenities include a rooftop pool, fitness center, co-working lounge, and package lockers. Residents pay premium rents and expect concierge-level service. When an elevator is down or the hot water goes out, the email you send isn’t just information — it’s a brand experience. This tool is built for that reality.
The showcase
Here is what the finished CLI tool does once you run it:
- Input: You type or pipe in rough notes like
"14B hot water out since yesterday, valve part backordered, maybe tomorrow afternoon" - Tone selector: Choose from
--tone concierge(warm, hospitality-forward),--tone firm(boundary-setting for policy issues), or--tone de-escalation(empathetic, structured for upset residents) - Scenario template: Choose from
--scenario outage,--scenario noise,--scenario package,--scenario delay, or--scenario general - Follow-up variants: The tool generates three versions — send now, 24-hour follow-up, and 72-hour follow-up — so you have the full communication arc ready
- Compliance check: A warning panel flags any phrases that could create Fair Housing exposure or make unenforceable promises (e.g., “guaranteed by tomorrow,” “this only affects certain units”)
- Output: Clean Markdown formatted for copy-paste into your email portal, resident app, or Outlook
Everything runs locally on your machine. Resident names, unit numbers, and issue details never leave your computer.
The prompt
Open your terminal, navigate to a project folder, start your AI CLI tool (e.g., by typing claude), and paste this prompt:
Build a Node.js CLI tool called resident-response-studio that converts roughmaintenance/issue notes into polished, brand-appropriate resident communications.The property is The Concord Crystal City, a 413-unit luxury apartment communitymanaged by Bozzuto.
PROJECT STRUCTURE:resident-response-studio/ package.json src/ index.js (CLI entry point using Commander.js) tones.js (tone profile definitions) scenarios.js (scenario template definitions) compliance.js (Fair Housing compliance checker) formatter.js (Handlebars template renderer) templates/ email.hbs (main email template) followup-24h.hbs (24-hour follow-up template) followup-72h.hbs (72-hour follow-up template)
REQUIREMENTS:
1. CLI INTERFACE (src/index.js) - Usage: node src/index.js --tone <tone> --scenario <scenario> "<notes>" - Also accept piped input: echo "notes here" | node src/index.js --tone concierge --scenario outage - Options: --tone <concierge|firm|de-escalation> (default: concierge) --scenario <noise|outage|package|delay|general> (default: general) --unit <unit-number> (optional, inserted into greeting) --resident <name> (optional, defaults to "Valued Resident") --no-followups (skip generating follow-up variants) - Output all three message variants (send-now, 24h, 72h) to stdout as formatted Markdown separated by horizontal rules - Also write each variant to files: output/response-now.md, output/response-24h.md, output/response-72h.md
2. TONE PROFILES (src/tones.js) Export an object with three tone profiles, each containing:
a. "concierge" (default — warm, hospitality-forward) - Greeting style: "Dear [Name]," or "Good [morning/afternoon], [Name]," - Voice: first-person plural ("we", "our team") - Empathy opener: acknowledge inconvenience before explaining - Closing: offer direct contact, express appreciation for patience - Example phrases: "We understand this is frustrating", "Our team is actively working to resolve this", "Please don't hesitate to reach out" - Sign-off: "Warm regards," with "The Concord Management Team"
b. "firm" (boundary-setting — for policy enforcement) - Greeting style: "Dear [Name]," - Voice: professional, policy-referencing - Structure: state the policy, explain the specific situation, offer the resolution path - Example phrases: "Per your lease agreement", "Community guidelines require", "We're happy to discuss this further during office hours" - Sign-off: "Respectfully," with "The Concord Management Team"
c. "de-escalation" (empathetic — for upset residents) - Greeting style: "Dear [Name]," - Voice: validating, action-oriented - Structure: validate the feeling, acknowledge the specific issue, state the concrete next step with a timeline, offer an escalation path - Example phrases: "Your frustration is completely understandable", "Here is exactly what is happening and what comes next", "If this resolution does not meet your expectations, I'd like to connect you with [manager name/role]" - Sign-off: "Sincerely," with manager name and direct phone number placeholder
3. SCENARIO TEMPLATES (src/scenarios.js) Export an object with five scenario templates, each containing:
a. "noise" — Noise complaint response - Required context: time of incident, unit/area, type of noise - Structure: acknowledge report, explain steps taken (or planned), reference quiet hours policy (10pm-8am), provide next steps - Include: reminder of how to report future incidents (front desk, after-hours emergency line)
b. "outage" — Utility/service outage (water, electric, elevator, HVAC) - Required context: what is affected, estimated restoration time, cause if known - Structure: state what is affected, explain the cause, give estimated timeline, describe interim accommodations if applicable - Include: emergency contact info, alternative arrangements ("the fitness center restrooms on L2 are available")
c. "package" — Package room / locker issue - Required context: tracking number or description, what happened (missing, damaged, misdelivered, locker malfunction) - Structure: acknowledge the issue, explain investigation steps, provide timeline for resolution - Include: package room hours, Luxer One / package locker support info
d. "delay" — Maintenance delay - Required context: original work order, what is delayed, why, new estimated completion - Structure: acknowledge the original request, explain the delay transparently (parts, vendor scheduling, scope change), give new timeline, offer interim solution if possible - Include: work order reference number placeholder, maintenance office direct line
e. "general" — Catch-all for any other resident issue - Flexible structure: acknowledge, explain, resolve, follow up - Works for lease questions, amenity closures, community events, move-in/move-out coordination
4. COMPLIANCE CHECKER (src/compliance.js) - Scan the generated message for Fair Housing red flags: * Language implying preference based on familial status ("perfect for couples", "quiet for singles", "family-friendly floor") * Language implying preference based on age ("young professionals", "active seniors", "mature community") * Language referencing disability in a restrictive way * Language referencing national origin, religion, race, or sex * Promises with specific enforceability risk ("guaranteed by tomorrow", "we promise this won't happen again", "this will definitely be fixed") * Language that could be construed as retaliatory ("since you complained", "because of your review") - Output a warnings array with the flagged phrase, the reason, and a suggested replacement - Compliance check runs automatically; warnings print below the generated email in a highlighted section - If zero warnings, print "Compliance check passed -- no flags detected"
5. FOLLOW-UP VARIANTS - "send-now": The main response to the resident's issue - "24h follow-up": A check-in message sent the next day. Shorter. Asks if the issue is resolved. Provides update if there is one. Uses same tone profile. - "72h follow-up": A closing message. Confirms resolution or provides escalation path. Asks for feedback. Mentions satisfaction survey if applicable. - Each follow-up references the original issue naturally ("Following up on the [issue] we discussed on [day]...")
6. OUTPUT FORMAT - All output is Markdown, suitable for pasting into email - Include a subject line suggestion at the top of each variant - Use proper paragraph breaks, not walls of text - Bold key information: timelines, phone numbers, next steps - The Markdown should render cleanly in any email client that supports rich text or in a resident portal
DEPENDENCIES: commander, handlebars, chalk (for terminal output coloring)
SAMPLE RUN:node src/index.js --tone de-escalation --scenario outage --unit 14B \ --resident "Ms. Chen" \ "hot water out since yesterday morning, valve part on backorder from Ferguson, expected delivery tomorrow afternoon, maintenance team aware, temporary access to L2 fitness center showers offered"
Should output a professional de-escalation email acknowledging theextended outage, explaining the backorder transparently, giving thenew timeline, offering the L2 shower alternative, and providingdirect contact info for follow-up. Plus 24h and 72h follow-up drafts.That entire block is the prompt. Paste it as-is. The specificity is deliberate — every detail about tone profiles, scenario templates, compliance rules, and output format is there so the LLM gives you exactly what you need on the first try. Vague prompts produce vague tools.
What you get
After the LLM finishes (typically 60-90 seconds), you will have the project:
resident-response-studio/ package.json src/ index.js tones.js scenarios.js compliance.js formatter.js templates/ email.hbs followup-24h.hbs followup-72h.hbsSet it up and run
cd resident-response-studionpm installnode src/index.js --tone de-escalation --scenario outage --unit 14B \ --resident "Ms. Chen" \ "hot water out since yesterday morning, valve part on backorder, maybe tomorrow afternoon"You should see output like:
---## SEND NOW**Subject:** Update on Hot Water Service -- Unit 14B
Dear Ms. Chen,
Your frustration is completely understandable. Being without hot water forover 24 hours is not the level of service we hold ourselves to at The Concord,and I want to give you a transparent update on where things stand.
**What happened:** The hot water interruption in your unit is caused by avalve component that requires replacement. The part has been ordered fromour supplier and is expected to arrive **tomorrow afternoon**.
**What we're doing:** Our maintenance team has this flagged as their toppriority. Once the part arrives, installation will begin immediately --we anticipate full restoration within 2-3 hours of receiving the component.
**In the meantime:** The fitness center restrooms on Level 2 are availablefor shower access. The front desk can provide you with a temporary accesskey if needed.
If this timeline or resolution does not meet your expectations, I'd liketo connect you with our Community Manager directly at **(703) 555-0142**.
Sincerely,[Manager Name]Assistant Community ManagerThe Concord Crystal City
---## 24-HOUR FOLLOW-UP...
---## 72-HOUR FOLLOW-UP...
---## COMPLIANCE CHECKCompliance check passed -- no flags detected.If something is off
LLMs occasionally produce code with small bugs. Here are the most common issues and one-line fix prompts:
| Problem | Follow-up prompt |
|---|---|
| Commander.js not parsing arguments | The CLI arguments aren't being read. Make sure Commander is set up with .option() for each flag and .argument() for the notes text. Call .parse(process.argv) at the end. |
| Handlebars templates not rendering variables | The template outputs raw curly braces like {{residentName}} instead of actual values. Make sure you're compiling the template with Handlebars.compile() and passing the data context object when calling the compiled function. |
| Piped input not working | `When I pipe text with echo “notes” |
| Output files not created | The output/ directory and files aren't being created. Add fs.mkdirSync('output', { recursive: true }) before writing files. Use path.join for cross-platform paths. |
When Things Go Wrong
Use the Symptom → Evidence → Request pattern: describe what you see, paste the error, then ask for a fix.
How it works (the 2-minute explanation)
You do not need to understand every line of the generated code, but here is the mental model:
- Commander.js parses the command-line flags (
--tone,--scenario,--unit,--resident) and the notes argument. It gives you a clean options object to work with. - Tone profiles are plain JavaScript objects that define greeting patterns, voice rules, example phrases, and sign-off styles. The template engine selects the right profile based on your
--toneflag. - Scenario templates provide the structural skeleton for each type of communication. A noise complaint has a different flow (acknowledge > steps taken > policy reference > next steps) than a maintenance delay (acknowledge > explain delay > new timeline > interim solution).
- Handlebars is a template engine. It takes a
.hbsfile with placeholders like{{residentName}}and{{issueDescription}}, fills them in with your data, and outputs the final text. It is the same technology behind many email marketing tools. - The compliance checker runs regex patterns and phrase matching against the finished output. It does not block sending — it warns. You make the final call.
🔍Why local-first matters for resident data
Resident names, unit numbers, and issue details are sensitive information. A cloud-based tool means that data passes through someone else’s server. This CLI tool runs entirely on your machine — nothing leaves your laptop. For property management companies handling thousands of residents’ personal information, this is not just a preference; it is a data handling best practice. If your company has a data processing agreement or privacy policy, a local-first tool is the easiest path to compliance.
Customize it
The base tool handles most daily communication needs, but here are follow-up prompts to extend it for specific situations:
Add a lease renewal response template
Add a new scenario called "renewal" for lease renewal communications. It shouldhandle three sub-types: renewal offer (include proposed new rent, lease termoptions, and early-bird incentive deadline), renewal negotiation (acknowledgethe resident's counter-offer, present the property's position, offer toschedule a call), and renewal decline/non-renewal (30-day notice language,move-out procedures, security deposit timeline). Each sub-type should workwith all three tone profiles.Add batch mode for multiple residents
Add a --batch flag that accepts a CSV file path. The CSV should have columns:unit, resident_name, scenario, tone, notes. The tool reads each row andgenerates a separate response file for each resident in output/batch/. Printa summary table showing how many emails were generated, any compliancewarnings, and which units had issues. This is for sending updates to anentire floor or building during a large outage.Add a response history log
Add a --log flag that appends each generated response to a responses-log.jsonfile with timestamp, unit, scenario, tone, compliance warnings, and thefirst 100 characters of the response. This creates an audit trail. Add a"node src/index.js history" subcommand that prints the last 20 entries ina formatted table. Include a --search flag to filter history by unit numberor scenario type.Notice the pattern: you start with a working tool, then add features one prompt at a time. Each prompt builds on what already exists. You never need to plan the entire tool upfront. This is how real software development works with AI assistance — and it is how you should approach every tool in this module.
Try it yourself
- Open your CLI tool in an empty folder.
- Paste the main prompt from above.
- Run
npm installand test with the sample command. - Try all three tone profiles with the same notes — compare the output.
- Write notes for a real scenario you’ve dealt with recently and run it through the tool.
- Pick one customization from the list above and add it.
If the tool saves you ten minutes on a single email, it has already paid for the time you spent building it. If you use it five times a day, you are saving nearly an hour of writing time daily.
Key takeaways
- One prompt, one tool: a detailed, specific prompt produces a working resident communication CLI in under 2 minutes. The prompt is your specification document.
- Tone profiles solve the consistency problem — every team member sends communications that sound like they came from the same professional organization, regardless of who is on the desk that day.
- Compliance guardrails catch mistakes before they become lawsuits — Fair Housing language is tricky, and a keyword scanner catches patterns that tired eyes miss at 7 AM.
- Follow-up variants close the loop — most resident dissatisfaction comes from feeling forgotten after the first response. Having 24h and 72h follow-ups pre-drafted means you actually send them.
- Local-first protects resident data — no resident PII leaves your machine. This is not just good practice; it is the kind of data handling that auditors want to see.
A resident in unit 8C emails: 'The noise from 9C is unbearable every night. If you don't fix this I'm leaving a 1-star review.' You run the tool with --tone de-escalation --scenario noise. The compliance checker flags the phrase 'quiet community' in the generated response. Why?
What’s next
In the next lesson, you will build something more operational: a Morning Maintenance Triage Board that parses overnight work orders from CSV, scores them by urgency, and generates a printable daily action queue for your maintenance standup. Same pattern — showcase, prompt, output, customize — but with CSV data ingestion and an HTML dashboard instead of text templates.