npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dilix/rent-control-engine

v0.1.0

Published

Resolve the maximum legal annual rent increase for any California property — local ordinance + AB-1482 statewide fallback + Costa-Hawkins exemption logic + multi-year NOI projection. All 39 CAA-chart CA jurisdictions encoded with citations (36 active + 3

Readme

@dilix/rent-control-engine

Resolve the maximum legal annual rent increase for any California property — local ordinance, AB-1482 statewide fallback, Costa-Hawkins exemption logic, multi-year NOI projection. All 39 jurisdictions on the CAA "Local Rent Control Ordinances" chart (1/2026) encoded with citations — 36 active + 3 repealed/paused.

npm version License: MIT CI Tests

Built and maintained by Dilix — the NOI defense layer for CRE.


What this answers

"Given this California property, on this date, what is the maximum legal annual rent increase the landlord may impose?"

Deterministically. With a citation. In <1ms.

import { resolveRentCap } from "@dilix/rent-control-engine";

const cap = resolveRentCap({
  city: "Oakland",
  county: "Alameda",
  state: "CA",
  yearBuilt: 1970,
  unitCount: 12,
  propertyType: "multifamily_5plus",
});

// {
//   capPct: 0.8,
//   source: "local_ordinance",
//   citation: "Oakland Code of Ordinances §8.22.010 et seq.",
//   formulaExplanation: "Oakland rent ordinance: 0.8% (published cap for 2025-08-01 → 2026-07-31); 60% of regional CPI; SF-Oakland-Hayward April 2025 reading ~1.33%",
//   effectiveStart: "2025-08-01",
//   effectiveEnd: "2026-07-31",
//   confidence: "high",
//   // ...
// }

That's a 0.8% cap on a building most underwriting models would project at 3-4% rent growth. Over a 5-year hold, that's six figures of foregone rent the model is overcounting. This package's reason for existing is to surface that gap before the deal closes.

Why this is different from "rent control data" you might license elsewhere

CRE data vendors will sell you a property record with "rent controlled: true." That's not actionable. You need the rate, the citation, and the math behind it — otherwise you can't build a defensible underwriting model on top.

Other tools:

  • Don't enumerate the formula (so you can't audit)
  • Don't surface the citation (so you can't defend the number to a customer)
  • Don't handle the variants — Beverly Hills' rent-base tier ≠ Inglewood's unit-count tier ≠ Antioch's bi-monthly published periods

This engine handles all of them. By design, in code, MIT-licensed.

Install

npm install @dilix/rent-control-engine

Requires Node 18+. Ships both ESM and CommonJS — works in Vite, Webpack, esbuild, plain Node ESM, and Lambda/Cloud-Functions runtimes that haven't migrated to ESM.

// ESM
import { resolveRentCap } from "@dilix/rent-control-engine";

// CommonJS
const { resolveRentCap } = require("@dilix/rent-control-engine");

Usage

Single-property resolution

import { resolveRentCap } from "@dilix/rent-control-engine";

const cap = resolveRentCap({
  city: "Beverly Hills",
  county: "Los Angeles",
  state: "CA",
  yearBuilt: 1960,
  unitCount: 8,
  propertyType: "multifamily_5plus",
  moveInRentBase: 2500,  // required for Beverly Hills' rent-base tier
});

Multi-year NOI projection

import { projectRentCapImpact } from "@dilix/rent-control-engine";

const sub = projectRentCapImpact(
  property,
  300_000,  // base annual GRI
  5,        // hold years
  4,        // assumed market growth %
);

console.log(sub.cumulativeDrag);  // total $ left on the table over the hold

As-of-date resolution (historical or future)

const cap = resolveRentCap(property, new Date("2026-03-15"));
// Resolves against the period covering 3/15/26

See examples/ for three working scripts:

Coverage

36 of 36 active CAA-chart California jurisdictions (per the California Apartment Association "Local Rent Control Ordinances" chart, updated 1/2026):

Alameda · Antioch · Baldwin Park · Bell Gardens · Berkeley · Beverly Hills · Commerce · Concord · Cudahy · Culver City · East Palo Alto · Gardena · Half Moon Bay · Hayward · Huntington Park · Inglewood · Larkspur · Los Angeles (City) · Los Angeles County (Unincorporated) · Los Gatos · Maywood · Mountain View · Oakland · Ojai · Oxnard · Palm Springs · Pasadena · Pomona · Richmond · Sacramento · San Francisco · San Jose · Santa Ana · Santa Monica · Thousand Oaks · West Hollywood

Plus:

  • AB-1482 California statewide rule (5% + regional CPI, max 10%)
  • Costa-Hawkins single-family/condo exemption (Civ. Code §1954.52)
  • Paused / repealed ordinances correctly fall through to AB-1482: Salinas (paused pending Nov 2026 referendum), Fairfax (repealed Nov 2024), San Anselmo (repealed Nov 2024)

Cap formula variants supported

Every CAA-chart ordinance fits one of these (TypeScript discriminated union — see ADR-1):

| Variant | Example | |---|---| | fixed_pct | San Jose 5%, Hayward 5%, Ojai 4% | | cpi_formula (with floor/ceiling/lower-of/higher-of variants) | Oakland (lower of 60% CPI or 3%), Mountain View (CPI bounded 2-5%), Pasadena (75% of CPI) | | flat_plus_cpi | AB-1482, Sacramento, Larkspur (5% + CPI capped at 7%) | | published_periods | SF, Antioch (bi-monthly resets), LA, Inglewood | | unit_count_tiered | Inglewood (≤4 units vs 5+) | | rent_base_tiered | Beverly Hills ($600 cutoff) | | binding_arbitration | Gardena (5% threshold) | | not_in_effect | Salinas, Fairfax, San Anselmo |

FAQ

Why not just license CoreLogic or ATTOM for this? They don't have it. Property data vendors carry "rent controlled: true/false" booleans without rates, formulas, or citations. We checked.

Why open source? Verifiable code IS the moat. Customers underwriting deals on top of regulatory math need to be able to audit it. See ADR-5.

Where do the CPI numbers come from? Today: back-calculated from the CAA chart's published cap percentages for internal consistency. Tomorrow: BLS authoritative readings refreshed quarterly. We document the source on every reading via the source field. See ADR-3.

Why is Oakland's cap so much lower than San Francisco's? Both ordinances tie their cap to the SF-Oakland-Hayward regional CPI, but the application math differs (Oakland's CAA-published rate this period is 0.8%; SF's is 1.6%). The engine encodes both exactly per CAA — see src/ordinances.ts for the literal computation per jurisdiction.

Will this work for New York / New Jersey / Oregon? Not yet. v0.1 is California-only. Out-of-state addresses return source: "no_local_rule_no_ab1482" with a warning. NY rent stabilization is on the roadmap (see ADR-4). NY in particular requires DHCR registration data that isn't trivial to ship.

An ordinance changed last week. How fast can I get the update? Open a data correction issue with an authoritative source link. Most data corrections ship within 48 hours.

Limitations and known gaps

We document these so you can decide what's safe to underwrite on top of.

  • Year-only date matching for builtBefore cutoffs. A 1979 SF property built before 6/13/79 should be SF-covered, but our resolver flags 1979 as exempt because year ≥ 1979. Affects ~5% of borderline-year buildings. (ADR-2)
  • Santa Monica $-cap not modeled. Santa Monica caps the absolute monthly increase ($60-$76 per period) in addition to the % cap. Only the % is computed. High-end rents may be more constrained by the dollar cap.
  • Unincorporated LA County sub-tiers. General tier resolved; small-property-landlord (+1%) and luxury-unit (+2%) sub-tiers require property metadata not yet exposed in the input.
  • Projections beyond the published period fall through to market growth. projectRentCapImpact resolves a cap for each future year. When the future date lies past the ordinance's published cap window (typical published-periods ordinances like Oakland), the cap returns null and the projection grows the cap-rent at the market assumption. The cumulative drag is therefore the floor, not a worst-case — re-published caps are likely to compress growth further. For conservative underwriting, call resolveRentCap with the current period and apply that cap flat across the hold.
  • California only.

See CHANGELOG.md for the full feature/limitation tracker.

Performance

37 tests · 11ms total
resolveRentCap median latency: <1ms
projectRentCapImpact (5-year hold): <2ms

No network calls, no DB reads, no ML inference. The whole engine fits in memory and resolves synchronously.

Architecture decisions

Significant design choices are documented in docs/architecture-decisions.md. The seven ADRs cover:

  1. Discriminated union vs. class hierarchy for CapFormula
  2. Year-only date matching trade-off
  3. Back-calculated CPI vs. BLS pulls
  4. CA-only at v0.1
  5. Open source the engine, monetize the data
  6. No DB; ordinances live in code
  7. Confidence as enum, not numeric score

Contributing

Data corrections are the most valuable contribution; see CONTRIBUTING.md. Every accepted correction ships with the next release and the contributor is credited in CHANGELOG.md.

Source attribution

All ordinances are encoded from the California Apartment Association "Local Rent Control Ordinances" chart, updated 1/2026 (© CAA). The chart is the operative reference document for rent control in California. Refresh against the next CAA update each quarter.

Disclaimer

Not legal advice. The data, citations, and computations produced by this software are informational only. Verify rent control eligibility, applicable formulas, and resolved cap percentages with the relevant municipal rent board and a licensed California land-use attorney before relying on any output for investment, leasing, or compliance decisions.

License

MIT — see LICENSE.


Why Dilix built this

I'm a CRE professional who got tired of underwriting models that assume 3-4% rent growth on properties that legally can't grow rents above 1%. The gap compounds. The exit-value haircut on a 5-year hold can swing six figures.

So this engine exists. It's the math nobody else publishes, written deterministically, audit-ready by default. If you find an ordinance that's wrong or a citation that's broken, open an issue — keeping it accurate is the whole point.

Erica Walters, founder, Dilix · dilix.ai