尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗A tool to help Jersey City and Hudson County homeowners see how their property taxes have changed, how that compares with their neighbors and nearby towns, and how tax abatements work.
Status: Phase 1 – data extraction. State data pipeline, quality checks, and live billing-portal extraction for Jersey City, Hoboken and Union City.
pip install -r requirements.txt
# 1. NJ parcel map + MOD-IV attributes for Hudson County (hosted NJOGIS service)
python pipeline/fetch_njogis_parcels.py --county HUDSON --out data/raw/njogis
# 2. State MOD-IV tax lists, one zip per year (statewide, ~270 MB each). Keep the Hudson file:
# https://www.nj.gov/treasury/taxation/pdf/lpt/modiv-<YEAR>.zip -> data/raw/modiv/hudson_<YEAR>.txt
python pipeline/modiv.py data/raw/modiv/hudson_2026.txt data/interim/modiv_hudson_2026.csv
# 3. Official rates and averages -> data/raw/state/
# GTRhistory.xlsx, <YEAR>AvgResStat.pdf from https://www.nj.gov/treasury/taxation/lpt/statdata.shtml
# 4. Actual Jersey City bills for a stratified sample (city's public tax inquiry)
python pipeline/sample_jc_bills.py data/interim/modiv_hudson_2026.csv data/interim/jc_bill_sample.csv
# 5. Quality / currency report -> data/interim/quality/
python pipeline/quality_report.py
python -m pytest tests
data/raw/ is not committed (large, re-downloadable).
| Town | Portal | Client |
|---|---|---|
| Jersey City (0906) | HLS Systems Property Tax Inquiry (JSON API) | pipeline/portals/hls.py |
| Hoboken (0905) | Edmunds WIPP (GWT-RPC) — its HLS page has no bill data | pipeline/portals/wipp.py |
| Union City (0910) | Edmunds WIPP (GWT-RPC) | pipeline/portals/wipp.py |
P="python pipeline/extract_bills.py" # store: $DATABASE_URL (Supabase) if set, else data/portal/bills.sqlite
$P index --town union-city # 1. list every account (resumable)
$P fetch --town union-city # 2. fetch bills for pending accounts (resumable)
$P status # progress per town
$P export --out data/portal/export # accounts.csv, bills.csv, annual.csv
python pipeline/validate_portal.py # compare against the MOD-IV 2026 list
--interval). Stop and re-run any time.category: property_tax (regular, added, omitted), appeal_adjustment
(tax court / county board / assessor), or other (payment bookkeeping, water/sewer, SID, hotel tax).
Only property_tax should be used for "what did this property pay".--include-owners (on index/fetch), and
never for accounts the portal flags under Daniel's Law (N.J.S.A. 47:1B). --keep-raw also stores
each portal response zlib-compressed (in raw_responses locally, in the private Supabase Storage
bucket portal-raw on Postgres; print one with raw --pin <pin>), which
keeps payment history and full ledger history that the normalized bills table drops.
export --redact-owners leaves the owner columns out.past_due_amount, past_due_bills,
oldest_past_due, past_due_interest, total_due, open tax-sale liens (lien_count,
lien_open_balance), redeemed_liens (history) and the portal's own flags (portal_delinquent,
pending_tax_sale, Jersey City only), summarized as delinquency_level:
current / 1_quarter / 2_3_quarters / 4plus_quarters / lien.
A bill counts as past due when it still has a balance more than 10 days after its due date
(N.J.S.A. 54:4-67 grace period), as of the moment the account was fetched (fetched_at).
Bills before --min-year are not stored but still count. A property whose lien was bought by an
investor shows $0 owed to the city; its debt is the lien's open balance. WIPP portals (Hoboken,
Union City) report balances but not liens, and their interest field reads 0 (interest is
computed on their page), so past_due_interest is only meaningful for Jersey City.
export writes delinquent.csv (largest first) and delinquency_summary.csv.SCHEMAS in wipp.py); besides bills, owner and assessments this gives
open tax-sale liens (certificate, sale date, holder, sale amount, subsequent charges), the
"in tax sale" flag and the bankruptcy flag. Liens are stored in ..github/workflows/extract-bills.yml runs every 6 hours (and on demand from the Actions tab →
Extract tax bills → Run workflow). Two jobs run in parallel, one per portal host:
hls (Jersey City) and wipp (Union City, then Hoboken). Setup: docs/hosting.md.
DATABASE_URL secret, schema portal) directly; raw portal responses go to a private Supabase
Storage bucket. No Actions cache, release or artifact holds crawl data, so the repository can be public.max_minutes (default 320) and continues where the last run stopped,
so the full first pass (~1 day for Jersey City) completes over several runs.REFRESH_DAYS), which picks up each new quarterly bill; delinquent accounts are re-checked
weekly (RECHECK_DELINQUENT_DAYS). Bills before tax year 2019 are not kept.--include-owners --keep-raw) unless turned off for
a run; they are stored only in the database and bucket. Logs and the run summary show counts and
parcel ids only, since a public repository's logs are public.pipeline/fetch_county_records.py loads each town's records from the county tax boards' public search
(taxrecords-nj.com, which can export a whole municipality as one CSV): building floor area, year built,
the last sale with its SR-1A nonusable code, and four years of assessments, which the state MOD-IV file
lacks. Owner names and mailing addresses go to the private parcel_owners table only. Runs monthly via
.github/workflows/county-records.yml.
pipeline/fetch_permits.py loads Jersey City's permits from the city's permit portal (Tyler EnerGov,
jcnj.org/permitportal, in use since June 2023 with older permits migrated in) into permits. The portal's
public search returns at most 10,000 results per query and ignores its date filters, so recent reads the
newest permits daily and backfill searches each street address once (that covers every condo unit in a
building), keeping the permits on that address's tax lots; it is resumable and re-reads addresses after 120
days. Each permit gets a category (new construction, addition, renovation, demolition, certificate, minor,
trade sub-permit, utility). Runs daily via .github/workflows/permits.yml; the first full pass takes several
runs. The state's DCA construction permit dataset (data.nj.gov w9se-dmra) has Jersey City only through 2023,
which is why the city portal is used.
site/)Next.js app for Vercel. Two things on the home page: address search and a map of every Jersey City parcel, colored by the Q4 bill's change from a year earlier (default) or by the 5-year change. Each property has two steps: an overview (latest bill, tax over time vs similar nearby properties and the city) and an appeal step (the appeal check with the comparable sales it used, plus the property's permits and what finished work could add as an added assessment). Search understands condo units ("77 Hudson St 1205", "Unit 12", "#12"): a building shows once and lists its units. There is also a plain-language appeal guide.
Abatements (pipeline/abatements.py): the county records name each exemption's statute and its start and end
dates. A partly abated condo unit has a taxable land record (filed as class 1) plus an exempt building record
(X, class 15F); a fully abated project is a single class 15F record with an abatement statute (N.J.S.A. 40A:20
long-term, 40A:21 five-year, 55:14K / 55:16 affordable housing, 40:55C older urban renewal). An abatement that
ended shows as a land-only taxable record for an existing building, followed by the building value. Abated
properties, and those whose abatement ended within the years shown, are kept out of every comparison pool;
every condo unit is also compared with the units in its own building by full assessed value (taxable plus
exempt) per square foot, against a floor trend fitted with Theil-Sen so one over-assessed unit can't skew it.
The home page has an "Abatements only" map view and citywide totals (taxable value by class, abated value,
abatements ending soon).
Feedback: /feedback (general), /feedback?pin=… (linked from every property page, about that property) and
/feedback?q=…&topic=not_found (linked when a search finds nothing). The form pre-fills what the visitor typed in
the search box. Each message is saved as a small JSON file in the site's private Neon Object Storage bucket
(feedback/YYYY-MM/), so the database role stays read-only. Read them as CSV:
cd site && node --env-file=.env.local scripts/feedback.mjs > feedback.csv.
Try it locally without a database or secrets, on made-up data:
python scripts/demo_site_data.py # writes site/data
cd site && npm install && npm run dev # http://localhost:3000; try "102 Grove St" or "77 Hudson St 1201"
With real data instead: python pipeline/build_site.py --parcels data/raw/njogis/parcels_hudson.csv --json-out site/data
with DATABASE_URL set (reads the database, writes only local files). It reads the
public-fields-only site schema, rebuilt daily by pipeline/build_site.py
(.github/workflows/build-site.yml). Similar properties: same type, floor area within ±10% (at most
±15%), same era, nearby; see pipeline/comparables.py. Setup: docs/hosting.md.
web/)web/index.html is a single static page for Jersey City owners: search by address, tax history 2019–2026
(with what drove each year's change: the city rate vs. the property's own assessment), the 2026 first-half vs
second-half bill jump, a comparison with similar properties nearby (same type, similar assessment, within
half a mile), a 2027 appeal check (Chapter 123 ratio 66.69%, range 56.69–76.69%, nearby recorded sales) and an
appeal-preparation plan with deadlines, checklist and contacts.
python pipeline/build_web_data.py --export <hls export dir> --out web/data # ~90 s, ~58 MB of JSON
python -m http.server -d web 8000 # then open localhost:8000
The data files hold public tax-roll fields only (address, class, assessments, bills, recorded sales): no owner names, mailing addresses or delinquency data.
| Source | What it has | How current |
|---|---|---|
NJ Division of Taxation MOD-IV tax lists (modiv-YYYY.zip) | Every parcel: assessment, class, exemptions/abatement statute, last year's tax | List for year Y is certified in January of Y; its last_year_tax is tax year Y-1. Newest: 2026 list → 2025 taxes. |
| NJOGIS Parcels & MOD-IV composite (ArcGIS) | Parcel shapes/centroids joined to MOD-IV | Matches the 2025 list exactly (so taxes = 2024). Use for location only. |
NJ General Tax Rates history (GTRhistory.xlsx) | Official rate per $100 by town, 1997-2025 | 2026 not yet published. |
NJ Average Residential Statistics (YYYYAvgResStat.pdf) | Count, avg assessment, avg tax of class 2 homes by town | 2026 edition has no tax column yet. |
| Jersey City Property Tax Inquiry (HLS Systems) | Actual quarterly bills per account, incl. 2026 Q3/Q4 | Live. Queried one parcel at a time; owner names are never stored. |
Owner names are redacted at the state sources (Daniel's Law) and are never stored or displayed here. Lookups are by address or block/lot only.
liens_jsonanalyze_delinquency.py turns an export into delinquency analytics for one town: owner type
(owners.py: owner-occupied, individual investor, mom-and-pop LLC, corporate, trust/estate,
public/nonprofit) x property type (condo, single-family, 2-4 family, apartments, commercial, land)
x severity, with existing liens. Owner names only appear in its delinquent_properties.csv.rederive --town T re-parses stored raw responses with the current parsers (no network), e.g.
after a parser change; the workflow runs it automatically before fetching.//EX; refresh PERMUTATION/POLICY in wipp.py
from any request the page makes in a browser.