In GitHub Projects, what do custom fields and views add on top of issue labels?
answer
- A layer over issues, not a copy
- Typed slots labels cannot express
- One-of-N and ordered beats tag soup
- Same items, several saved lenses
- Values ride the item, not the issue
basics
~20 sA GitHub Project stores extra data per item — status, priority, estimate, iteration, target date — as typed fields that labels cannot express, and renders the same items as a table, a board, or a roadmap with independent filters, grouping and sorting per view.
solid answer
~50 sA Project is a layer *over* issues and pull requests, not a copy of them. Each item gets **custom fields** you define: text, number, date, single select, and iteration. Single select is the important one — it is genuinely one-of-N and ordered, which is what a `Status` column needs and what labels can never guarantee. Iteration fields generate repeating time boxes, so sprint membership stops being a hand-made label. Alongside these sit built-in fields such as `Status`, `Assignees`, `Labels`, `Milestone`, `Repository`, and `Linked pull requests`. **Views** are saved lenses over the same item set — Table, Board, or Roadmap — each with its own filter, grouping, sorting and visible columns, so the same project serves a triage table and an execution board simultaneously. Crucially the field values live on the project item, not on the issue, so a project can span many repositories and an org-level project is the only cross-repo view GitHub gives you.
code
json · 17 lines{
"data": {
"node": {
"title": "Platform backlog",
"fields": {
"nodes": [
{ "name": "Title", "dataType": "TITLE" },
{ "name": "Status", "dataType": "SINGLE_SELECT",
"options": ["Todo", "In progress", "In review", "Done"] },
{ "name": "Estimate", "dataType": "NUMBER" },
{ "name": "Sprint", "dataType": "ITERATION" },
{ "name": "Target date", "dataType": "DATE" }
]
}
}
}
}go deeper
Know that a GitHub Project holds issues and pull requests as items with extra typed fields such as Status and Priority, and that Table, Board and Roadmap are three ways to look at the same items.
Explain the field types — text, number, date, single select, iteration — why single select suits a Status column better than labels, and that each view carries its own filter, grouping and sorting.
Demonstrate the consequence of field values living on the project item: invisible in the repository issue list, lost when an item is removed, independent across two projects, and reachable only through the GraphQL API.
Own the decision of whether a project is worth its overhead at all, and how many boards an organisation should run before the tracking cost exceeds the coordination it buys.
## What a Project actually is A GitHub Project is a spreadsheet-shaped layer that *references* issues and pull requests. Adding an issue to a project creates a **project item** pointing at it; the issue itself is unchanged. Projects can also hold **draft items** — a title and body with no repository behind them — which is how an idea gets tracked before anyone decides it deserves an issue. Because the item is the thing that carries project data, one project can hold items from many repositories, and a project can be owned by an organisation or a user rather than a repository. That is the single biggest difference from labels and milestones, which stop at the repository boundary. ## Custom fields You define fields on the project, and every item gets a value slot for each: - **Text** — free-form notes, an external ticket id. - **Number** — estimates, story points, a cost. - **Date** — a target date, a hard deadline. - **Single select** — one option from a defined list, each option with a colour and description. This is the workhorse: `Status` (Todo / In progress / In review / Done), `Priority` (P0–P3), `Size`. Being single-valued and *ordered*, it can drive board columns and grouping in a way a label set cannot, because nothing stops an issue from carrying `priority:high` and `priority:low` at once. - **Iteration** — a repeating time box with a duration and optional breaks. GitHub generates the periods, so "which sprint" becomes a field with a real date range instead of a label someone must remember to create. Built-in fields come free: `Title`, `Assignees`, `Status`, `Labels`, `Milestone`, `Repository`, `Reviewers`, `Linked pull requests`. Note that `Labels` and `Milestone` are surfaced *read-through* from the underlying issue — so a project does not replace those primitives, it composes with them. ## Views A view is a saved configuration over the item set. Three layouts: - **Table** — dense, spreadsheet-like, best for triage and bulk edits; you can group by a field to get collapsible sections. - **Board** — kanban columns, driven by any single-select or iteration field (usually `Status`). Dragging a card writes the field value. - **Roadmap** — items laid out on a timeline using date or iteration fields, which is how you see a quarter without exporting anything. Each view keeps its own filter (a query such as `is:open label:bug -status:Done`), its own grouping, sorting and column visibility. Multiple views over one project is the point: the same items appear as a triage table for the lead, a sprint board for the team, and a roadmap for a stakeholder, with no duplicated data and no synchronisation problem. ## Where the data lives, and why that matters Field values are stored on the project item. Consequences worth knowing: - The repository's issue list does **not** show project field values. Someone browsing issues sees labels and milestone, not `Priority: P1`. If a value must be visible to people who never open the project, it has to be a label as well — or the project has to be the agreed front door. - Removing an item from a project discards its field values; re-adding starts blank. - Two projects containing the same issue each keep independent values, which is exactly right when a platform team and a product team track the same work with different vocabularies. ## Automation and API Projects carry built-in workflows that set fields on events (item added, item closed, pull request merged), so a board can stay current without dragging. Programmatic access is through the **GraphQL API** — the `ProjectV2` types, with mutations such as `addProjectV2ItemById` and `updateProjectV2ItemFieldValue`. There is no REST equivalent for the current Projects experience; scripts written against the retired classic-projects REST endpoints do not carry over. ## When not to reach for it A Project is overhead. A small repository whose whole backlog fits in one issue list with three labels gains nothing. Projects earn their keep when work spans repositories, when you need a second axis (priority *and* status *and* iteration), or when the same work must be read three different ways by three different audiences.
- Someone browsing the repository's issue list cannot see the Priority you set — why?Project field values are stored on the project item, not on the issue, so the repository issue list and its filters know nothing about them. Either accept the project as the front door for that information, or mirror the few values outsiders need onto labels and keep the project authoritative for the rest.
- Why is a single-select Status field better than status: labels?A single-select field is genuinely one-of-N and its options are ordered, so board columns and grouping follow a defined sequence and an item cannot be in two states at once. Labels are an unordered set with no exclusivity, so issues drift into carrying two status labels or none, and nothing reports the inconsistency.
- How do you script against a GitHub Project?Through the GraphQL API's `ProjectV2` types — query the project and its fields to learn their ids, then call mutations such as `addProjectV2ItemById` and `updateProjectV2ItemFieldValue`. Field and option ids must be resolved first; they are not the human-readable names you see in the UI.
saying these in an interview costs you the question
- Thinks project fields are stored on the issue itself
- Believes a project is a copy of the issues
- Assumes each view needs its own project
- Expects the current Projects experience to have REST endpoints
- Says labels can enforce a single workflow state