ZtM Job Board, a directory built by merging one JSON file per person
⚛️ A place for developers to show recruiters they are available for hire
At a glance
- What is it?
- The ZtM Job Board is a React and TypeScript site that lists developers from the Zero To Mastery community as available for hire, and the data model is unusually simple: each person contributes one JSON file to a Submissions folder, and the build script merges them into a single dataset the site reads. It is a good example of using Git pull requests as a database.
- Who is it for?
- ZtM Job Board suits a community that wants a public hiring directory with no backend to run, because every entry is a file in the repository and every update is a pull request that anyone can review. It is the wrong choice if you need applications, messaging, moderation or an account system, because the data model is a static JSON file per person and the site is a static build with a map.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The data model is one file per person
The ZtM Job Board is a place for developers from the Zero To Mastery Community to show recruiters that they are available for hire, and the whole thing is driven by one convention: to add your name to the list, you create a file named after your GitHub username inside the Submissions folder and fill it in.
The JSON shape is small and flat:
{
"name": "[YOUR_FULL_NAME]",
"img": "[YOUR_IMG_URL]",
"email": "[YOUR_EMAIL_ADDRESS]",
"links": {
"website": "[YOUR_WEBSITE_URL]",
"linkedin": "https://www.linkedin.com/in/<YOUR_LINKEDIN_USERNAME>",
"github": "https://github.com/<YOUR_GH_USERNAME>"
},
"jobTitle": "[YOUR_TITLE]",
"location": {
"city": "[YOUR_CITY]",
"state": "[YOUR_STATE_OR_PROVINCE]",
"country": "[YOUR_COUNTRY]"
}
}The README is careful about two details that trip people up. You must remove the @ from your GitHub username in the filename, and you must not include the square brackets or angle brackets, which are only there to show which values are placeholders. If you do not want to fill in some fields, leave them blank, for example with an empty state value.
The submission rules are strict on purpose. Your pull request will only be accepted if it follows the example above, and it cannot have anything else.
That last rule is the interesting part of the design. Because the file is data and not code, a submission cannot smuggle in a script, and a reviewer can check the whole change with a glance at the diff. It also means the build can validate every entry mechanically, which is what the aggregate step does.
The example with dummy values shows the shape without placeholders, and the README includes a separate note on profile images, including the trick of appending .png to a GitHub profile URL to get an avatar page.
The build merges the folder into one dataset
The package.json shows the whole pipeline, and it is the part of this project that is actually engineering rather than data entry.
There is an aggregate-json script, node scripts/aggregate-json.mjs, and a countries-json script, node scripts/countries-json.mjs. The first is the one that matters. It reads the Submissions folder and produces the single dataset the site consumes, and it is run as part of both the development and the test flow. The start script is npm-run-all -p watch-css start-js aggregate-json, so the aggregation runs in parallel with the CSS watcher and the Vite dev server, which means a new submission appears without a manual step.
The test script is npm-run-all aggregate-json && vitest. The aggregation is a prerequisite of the tests, which is the right order: if the merge step breaks, the tests fail rather than the site quietly serving an empty list.
The build is a two step process. build-css runs sass over the src directory, and build-js runs vite build. The postbuild step then moves the favicons into place, removes the leftover directory, and runs purgecss over the generated CSS with the built HTML and JavaScript as content, which strips the unused rules from the stylesheet after the fact rather than relying on the source CSS being minimal.
The deployment is gh-pages -d build, so the site is published to GitHub Pages from the build directory. The homepage field is set to a dot, which is what tells Vite to use relative paths, and that is exactly what you need for a GitHub Pages site served from a subdirectory rather than a domain root.
The site itself is at zero-to-mastery.github.io/ZtM-Job-Board/ and the repository has a build workflow badge against the master branch.
Why a pull request is the write path
The decision to use Git as the database is more interesting than it first looks, because it changes who can write to the site and what happens when they do.
In a normal application, a profile form means a server, a database, an account system, a moderation queue and probably an email confirmation. Here, adding a profile means one file and one pull request, and the review is a human reading a diff of a JSON object. The community around Zero To Mastery already works this way, since the README points at the Contributing To Open Source video in the course curriculum and at the Make a Pull Request guide, so the workflow is not a new burden on contributors, it is the workflow the community already teaches.
The trade is real and worth stating. There is no way to edit your entry without a pull request, so a typo in your email address stays until you notice it. There is no ordering or ranking, so a recruiter sees the list as it is. And every entry is public in the repository history, which for a job board is mostly a feature and for an email address is a mild consideration.
The alternative framing is worth keeping in mind, because this is a design other projects copy. Anything that is naturally append-only, human-curated and low volume does not need a database. A directory of conference talks, a list of translation contributions, a catalogue of hardware with a community file each. In each case the git model is a good fit and the pull request is a feature rather than a workaround, because the review trail and the credit to the contributor are both built in.
The strictness of the format is what makes it work. If a submission could contain anything at all, the build would need to defend against it, and the review would need to read it as code. Constraining the file to a known shape turns a pull request into a data check.
The index.html at the repository root and the src/ directory hold the site, and the scripts/ directory holds the aggregation and the country data generation, so the boundary between data and presentation is a directory boundary as much as anything else.
A map, a search box and a counter, with no backend
The dependency list describes the interface, and it is a short list that says the site is a browse and filter experience rather than an application.
Leaflet and react-leaflet provide the map, which is the reason a location field with city, state and country exists in the schema at all. react-search-input provides the search box over the directory. react-countup is for an animated statistic, probably the number of people on the board. webfontloader loads the icon fonts, and tachyons supplies the utility CSS, which is why there is a separate Sass build alongside the utility classes.
There is no backend in the dependency list, no database client and no API client. Everything the site renders came from the merged JSON, and the only network requests are for the map tiles and the fonts and the profile images people put in their own files.
That design has a consequence worth thinking about, because the img field accepts any URL. The README says profile pictures and images are allowed, and the recommended route is the GitHub avatar trick, appending.png to a GitHub profile URL to get an avatars.githubusercontent.com page you can copy the address of. The JSON example in the README uses exactly that pattern for the image field. Nothing stops someone pointing img at something else, which is a small open redirect and tracking surface in a page that is read by recruiters, and it is a consequence of a schema that trusts its contributors by design.
The build tooling around it is a modern React setup. Vite with the React plugin, React 19.2.3 with react-dom, and vitest for the tests. The lint-staged configuration runs prettier over source files on pre-commit through husky, and there is a.whitesource file, a.prettierrc.json, an.npmrc and a.nvmrc, which is a fairly complete modern JavaScript project skeleton.
The icons are credited in the Resources section as coming from Material Design Icons and Octicons, and the project is MIT licensed.
Editorial conclusion
ZtM Job Board suits a community that wants a public hiring directory with no backend to run, because every entry is a file in the repository and every update is a pull request that anyone can review. It is the wrong choice if you need applications, messaging, moderation or an account system, because the data model is a static JSON file per person and the site is a static build with a map. Before adding yourself, read the submission rules, since the pull request is accepted only if the file follows the example exactly and contains nothing else.
Frequently asked questions
How do I add myself to the ZtM Job Board?
Fork the repository, create a file named after your GitHub username with the @ removed inside the Submissions folder, fill in the JSON fields following the example exactly, and open a pull request. Profile images and images are allowed, and any field you want to skip can be left blank.
How does the ZtM Job Board get its data?
From the Submissions folder. The build script node scripts/aggregate-json.mjs merges the individual JSON files into one dataset, and it runs as part of the start command and as a prerequisite of the test command, so a broken merge fails the tests rather than shipping an empty board.
How do I run the ZtM Job Board locally?
Clone the repository, change into the directory, run npm ci and then npm start. The start script runs the CSS watcher, the Vite dev server and the JSON aggregation in parallel.
Why are pull requests to the ZtM Job Board so strict?
The README says a pull request will only be accepted if it follows the example exactly and cannot have anything else. The reason is that the file is data rather than code, so a strict format is what makes a submission safe to merge and reviewable at a glance.
What technology is the ZtM Job Board built with?
React 19 and TypeScript with Vite, Leaflet for the map, react-search-input for the search box, tachyons for utility CSS and a Sass build, with vitest for tests. The site is deployed to GitHub Pages with the gh-pages script and no backend of its own.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/zero-to-mastery-ztm-job-board)Was this useful?