Listings: one place where postings arrive, captured or typed, and are triaged before any becomes an application #25
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Postulo/postulo#25
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Observation
What exists today
base.html, lines 58–63). #10 takes them out of the header and parks them on the dashboard. This issue decides where they actually go, and it is not the dashboard.ApplicationIntakeForm— that creates the company, the posting and the application together (its docstring: "an application is almost always entered while looking at a posting"). Capture turns a URL or pasted HTML into aCaptureholding parsed data, which waits on the captures page (jobs:capture_list, linked from the dashboard as Captures awaiting review); Review opens the same intake form pre-filled and, on save, creates the application and links the capture to it (jobs/capture_views.py, lines 134–197; the wiki says it plainly: "Accepting one creates the application and links the two").JobPostingis already a full model — company, title, location, remote and employment type, URL, description, salary, posted, closing and closed dates — with create, detail, edit and delete views. But it has no list page, and no way to be created from the interface on its own:jobs:posting_createis linked from no template. A posting only ever exists behind an application or on a company page.Status.DRAFT, which is a different statement: I have decided, and I am preparing.In short, Postulo models the moment after the decision. The observation asks for the moment before it.
Shape
Listings is the stage before Applications: every posting the person has noticed, however it arrived, until they decide.
Navigation. Listings sits between Dashboard and Applications. Capture and Record leave the header (#10) and become the two actions of the Listings page: Capture (a URL or pasted page, unchanged) and Add a listing (the posting half of today's intake form: company and posting, no application). Both land in Listings.
A state on the posting.
newon arrival;shortlistedordiscardedby the person;appliedderived from the existence of an application, never set by hand;closedderived fromclosed_ator acloses_atin the past. Plusnoted_at(when it entered Listings) anddecided_at. The Listings page shows new and shortlisted by default, with filters for discarded and closed (#20's header filters apply).The decision. Apply on a listing opens the application half of the intake form — applied date, channel, CV, letter, contacts — creates the application and moves the listing out of the list; the application then follows the existing pipeline,
draftincluded, which regains its proper meaning: preparing. Discard takes an optional reason (not for me, pay, location, closed, other) and keeps the record: what a person passed on, and why, is data — Insights gains selectivity (listings seen against applications made) and "which sources produce listings I actually apply to". A discarded listing can be restored.Capture review changes its ending. A review lands in Listings as a new listing instead of creating an application. The review screen keeps its correction step — that is what makes captures safe — but its form is the posting half, with one checkbox, I have already applied, that keeps the one-step path for the most common case: recording after the fact. Captures awaiting review appear as a strip at the top of the Listings page; the captures page folds into it and
jobs:capture_listredirects there.Record an application stays, as the one-step action on the Applications page, implemented as "add a listing, then apply" so the data is identical whichever door was used.
Dashboard. Listings to decide on (with closing soon from
closes_at) replaces Captures awaiting review. A listing's closing date can raise a reminder, through #4, without any new machinery.API and extensions. The capture API's surface does not change:
POST /capturesandreview_urlkeep working, only the page a review ends on differs. #12's read API gains listings, and the "already tracked" badge in #17 and #18 covers listings as well as applications, which is the case where it is most useful.Board. Unchanged: applications by status. Listings may deserve a small board of its own (new / shortlisted) later; a list with filters comes first.
Export and import. The state fields join the posting section;
FORMAT_VERSIONbecomes 2 and the importer keeps accepting 1, derivingappliedwhere an application exists.Migration. Every existing posting has an application, so every one becomes
appliedby derivation. No row changes meaning.Documentation. Capturing postings and Tracking applications are rewritten around Listings → Applications;
docs/PLAN.mdgains the stage in the pipeline description.seed_demogets a handful of undecided and discarded listings so the page is not empty on first sight.Duplicate detection. Capturing or adding a listing whose URL — normalised: scheme and host folded, tracking parameters stripped — matches a listing or application the person already has says so ("already in your listings since 12 May") and offers to open it instead of creating a twin. The capture API answers the same way in its response, so #17 and #18 can show it in the extension before anything is sent.
The name
Listings, decided on 2026-09-05. It is the one-word form of "job listing"; it collides with nothing in the interface — the pipeline stage Offer (
Status.OFFER, event Offer received) keeps its one meaning, an employer's offer at the end of the process — and it has standard equivalents in French (annonces) and Portuguese (anúncios). Considered and set aside: Offers, the observation's original word, because of that collision; Vacancies (formal); Openings (no French equivalent); Postings (American in flavour); Jobs (reads as employment history beside the career record). In code the model staysJobPosting; URL names, views and templates saylisting.Classification
Enhancement. A workflow change, and therefore a paragraph in the release notes, but not a breaking change: the API surface is unchanged, existing data migrates by derivation, the old captures URL redirects, and no operator action is required.
Depends on / relates to
Open questions
Offers: one place where postings arrive, captured or typed, and are triaged before any becomes an applicationto Listings: one place where postings arrive, captured or typed, and are triaged before any becomes an application