The day the post type went live, job.army had a perfect empty room, a jobs archive with zero jobs. A job board’s value is its volume and freshness, hundreds of current listings, updated as they open and close, and no human types that daily. This post is the empty-board problem stated honestly, and the fetch skeleton that became the plugin’s heartbeat.
The arithmetic makes the case brutally. Federal hiring posts hundreds of new positions daily and closes hundreds more. Hand-entering one job, title, agency, location, salary, description, dates, takes minutes, so a human keeping even a hundred jobs current is a full-time clerk, and the board would still always be behind. The only honest architecture is automated ingestion, a fetcher that pulls listings from a source, transforms them, and creates or updates the job posts, running on a schedule and on demand:
function jab_fetch_jobs() {
$response = wp_remote_get(jab_source_url(), array(
'timeout' => 30,
'headers' => jab_source_headers(),
));
if (is_wp_error($response)) {
jab_log('Fetch failed: ' . $response->get_error_message());
return 0;
}
$data = json_decode(wp_remote_retrieve_body($response), true);
$count = 0;
foreach (jab_extract_items($data) as $item) {
if (jab_import_job($item)) { $count++; }
}
return $count;
}
The shape matters more than the details yet, fetch, decode, extract, import, with every stage named as its own function, because each stage will grow, sources will multiply, extraction will handle different formats, and import will dedupe and map fields, all of which the coming posts cover. Two disciplines are already load-bearing. wp_remote_get with an explicit timeout and error handling, because remote sources fail routinely and a fetcher that dies silently leaves the board quietly stale, so failures log where the debug workflow can see them. And the import returns a count, surfaced in the admin as fetched N jobs, because automation you cannot observe is automation you cannot trust.
The design also decided early what automation would not do, publish blindly. Fetched jobs arrive as drafts for review in the beginning, the same human-gate philosophy as the forex rates, automation proposes, a person approves, at least until the pipeline proved itself. The gate loosened later as trust accumulated, but starting gated meant the board’s early public face was never at the mercy of an unproven parser.
A few things people ask me about this
Why does my wp_remote_get fetch fail with no error on screen? Remote failures return WP_Error objects, and unread errors are silent. Check is_wp_error, log the message, and surface fetch counts in the admin so a zero jumps out.
Should imported content publish immediately? Not until the pipeline is proven. Import as drafts, review a few batches, then automate the publish once the field mapping has shown itself trustworthy.
Next
A pipeline needs a source, and the choice of source decided this project’s fate. Why USAJOBS, the official federal API, was the rare perfect answer is the next post.
