Downloadable kit
Public Data Site Kit
Kit files are in English.
Turn a public dataset into a static site that refreshes itself daily and shows the source and date under every number.
Python 3.9+. Tested on Linux and macOS. For anyone with a public dataset and a question about their own town or region.
- Fetch CSV files or JSON APIs every day, with conditional requests and a raw snapshot of each response.
- Write down what you distrust as rules, from ranges to outliers against the median, and get a log line for every dropped row.
- Build a static site with a page per place, the source and date under every number, and a licence check before anything ships.
Local Python kit | ZIP, guide and reports in English | Offline demo
$49One-time payment
I'm a subscriber: check my accessYearly: every kit included. Monthly: one new kit per billing cycle.
Delivered downloads are non-refundable. Return policy
View full-size sample ↗Access, downloads and refund policy
Yearly: every available kit and bundle, unlimited downloads.
Monthly: one new standalone kit per billing cycle, no bundles. Re-downloads are free and do not use a new claim.
Monthly subscriptions started before February 28, 2026 keep all-access, including bundles and unlimited downloads.
Monthly access currently allows three downloads per kit. Need another? Contact joozio@hey.com.
Download access while subscribed. Keep the files you download.
Digital downloads are non-refundable once delivered. We resend broken links, replace corrupt files and review products significantly different from their description case by case. Contact joozio@hey.com with your order details. Return policy
How it works
I built six small websites from Polish public data with my AI agent: housing prices developers must publish by law, smog from state stations, regional statistics, public tenders, a site that crosses four of them, and a weather site that reads sensors inside parcel lockers. All six run the same pipeline. Fetch the data every day, clean it, build one static page per place, and rebuild only when something moved. Most of the work was distrust. A thermometer in a metal box in the sun reads 30°C while the street is at 12, so each city's number is a median, and a sensor far hotter than its neighbours loses its reading. This kit is that pipeline, made generic. You write one JSON config per site: where the data lives, how its columns map, and what you distrust about it. The kit fetches CSV files or JSON APIs, logs every row it drops with the reason, and builds a ranking, a page per place, a search page, a sitemap and structured data, with the source and date under every number. It refuses to build until you fill in a licence check for each source. Standard library Python, no account. The demo builds a sample site from public domain U.S. data, offline.
Built from the pipeline behind six public data sites the author runs. 147 tests, passing on Linux under Python 3.9, 3.11, 3.12, 3.13 and 3.14 and on macOS on Apple silicon under Python 3.9 and 3.14 as of October 30, 2026.
Latest update: 2026-10-30
v1.0.0 (2026-10-30). First release.
Best for
- +Anyone with a public dataset and a question about their own town, region or country
- +Developers and data journalists who want a site that refreshes itself every day without a database or a framework
- +People building with a coding agent who want the pipeline settled, so the agent spends its time on the data
Not for
- -Picking the dataset or the question. Chapter 1 has the test I use and chapter 8 the prompt I give an agent; the noticing is yours
- -Charts and maps. Pages are plain HTML and CSS; data.json is there if you want your own front end on top
- -Data about people. The licence gate refuses any source whose entry says it holds personal data
- -Deploying. The kit stops at public/; chapter 6 shows rsync, GitHub Pages, Cloudflare Pages and Netlify
What you get
Package includes
- •START-HERE.html: run the demo, how it works, the distrust rules, your own site, what is in the box, the limits
- •bin/pds.py: init, check, fetch, normalize, build, refresh and --self-test
- •pds/: the pipeline, standard library Python
- •guide/01 to 08: picking a dataset, the licence check, writing down what you distrust, crossing a second dataset, the daily refresh, deploy, the config reference and agent prompts
- •templates/: site.json, licence.json, a cron line, a launchd plist, an nginx server block and a distrust worksheet
- •examples/sample-site: two U.S. federal public domain files, 217 county rows and 9 state rows, with a filled-in licence form
- •examples/demo.sh: seven offline steps on a temporary copy: a first build, a day where nothing changed, a changed file, and the guards
- •tests/: 147 tests, python3 -m unittest discover -s tests
- •SETUP.md, MANIFEST.txt, CHANGELOG.md, LICENSE.txt
FAQ
Do I need Claude Code or another agent?
No. Everything runs as python3 bin/pds.py from a terminal. Chapter 8 has the prompts I give a coding agent, the starter prompt from the post and one pointed at this kit, and they work with any agent.
What do I have to install?
Nothing. Python 3.9 or newer, standard library only. Unzip into a new folder and run python3 bin/pds.py --self-test. The 147 tests pass on Linux under Python 3.9, 3.11, 3.12, 3.13 and 3.14 and on macOS on Apple silicon under Python 3.9 and 3.14. SETUP.md has notes for macOS and Windows; no Windows run has been recorded for this release, and examples/demo.sh needs a POSIX shell.
Does anything leave my machine?
Only the requests your own site.json names, to the URLs you put there. No account, no telemetry, no database. The self-test, the demo and the tests run offline.
Which sources can it read?
CSV over HTTP, a JSON API with page-number or next-link pagination, or a local file. Several sources can map to the same place ids, so one page shows two datasets, each with its own source line. There is no HTML scraper: chapter 1 says to look for an API or a file first.
What happens on the morning a source breaks?
A failed fetch stops the run with exit code 3 and the live site stays as it was. If far fewer rows survive than last time, the run refuses to publish, exits 1, and keeps what came back in work/refused/ so you can look. Every run, changed or not, writes one line to state/runs.jsonl, so a day with no line means the scheduler never ran.
Can the site be in another language?
Yes. Every interface string and the number format can be replaced in site.json; chapter 7 has a Polish example. The kit files and the sample are in English.