How to Use GitHub Projects Effectively
Most engineering teams still plan work in one tool and ship it in another. Issues live in Jira or Trello, pull requests live in GitHub, and every status change requires a human to copy context across tabs. GitHub Projects removes much of that friction by keeping planning, issue tracking, and delivery close to the code.
Current GitHub Projects is the planning layer on top of issues and pull requests: custom fields, saved views, built-in automations, roadmaps, charts, and API access. It replaces Projects (classic), not the same product with a new coat of paint.
For teams that already live in GitHub, the value is straightforward:
- Less context switching between a tracker and the code host
- Fewer stale status updates because issue and pull request state can drive project state
- One place to plan cross-repository work without losing repository-level detail
- A workflow that works for a two-person open source project, an inner source program, or a larger engineering org
Not Projects (classic)
This guide covers the current GitHub Projects experience. If you're starting fresh, use the new Projects workflow, not classic boards.
Open Source Maintainer Lens
For the rest of this guide, imagine a maintainer coordinating work across several related repositories: core code, supporting libraries, documentation, examples, release tooling, or other adjacent repos. The same patterns also work well for inner source programs on GitHub Enterprise, internal platform teams, and product engineering groups.
Getting Started¶
Create the Project¶
The first decision is scope: create the project under your own account or under an organization.
| Scope | Best For | Tradeoff |
|---|---|---|
| User project | Personal planning, solo open source maintenance, lightweight cross-repo work | Easier to start, less reusable for teams |
| Organization project | Team backlogs, sprint planning, roadmap tracking, shared engineering workflows | Requires org-level permissions, but scales much better |
A practical rule:
- If the project is for you, create it at the user level.
- If the project is for a team, create it at the organization level.
To create one in the GitHub UI:
- Go to your profile or organization.
- Open Projects.
- Click New project.
- Start from a blank project unless you already have a template you trust.
- Name it after the workflow, not just the team.
Good names:
Infrastructure Automation MaintenanceMulti-Repo Sprint BoardShared Maintainer WorkflowOpen Source Release Coordination
Weak names:
Project 1Team BoardStuff
Link Repositories¶
Projects become more useful the moment they are linked to the repositories that generate the work. Linking repositories makes it easier to add issues and pull requests, power automations, and keep the project close to the code.
In the UI:
- Open the project.
- Open the project menu.
- Go to the project settings.
- Link the repositories that should feed this project.
For an engineering team, link every repository that regularly contributes work to the same delivery stream. For open source or inner source maintainers, this often means linking the primary repository, supporting libraries or SDKs, documentation, examples, and release tooling that move together.
Assign Access by Team¶
If you're using an organization project, don't stop at creating the project. Set up access so the right teams can actually manage it.
In the UI:
- Open the project.
- Go to Settings.
- Open Manage access.
- Add the relevant GitHub teams.
- Assign the role each team should have.
For a maintainer-heavy organization, team-based access is usually cleaner than assigning people one by one. It scales better, it survives personnel changes, and it matches the way repository ownership often already works.
A practical pattern is to grant project access to repository-aligned maintainer teams such as:
org/blue-maintainersorg/green-maintainersorg/orange-maintainersorg/purple-maintainers
If those teams are responsible for triage, planning, and workflow maintenance, giving them project admin access can make sense. If they only need to update and view items, use a less privileged role that matches how you want the project governed.
Add Items the Right Way¶
Modern Projects supports two useful item types from day one:
- Draft issues: lightweight planning items that live only in the project
- Issues and pull requests: real repository-backed work items
Use draft issues when:
- you're brainstorming backlog items
- the work isn't ready for a repository yet
- you're doing sprint planning and want to capture loose tasks quickly
Use real issues when:
- the work should have repository history
- you want assignees, labels, milestones, or notifications
- the item is ready for execution
Structured issue forms make repository-backed items easier to triage. See How to Write Effective GitHub Issue Templates.
A healthy pattern looks like this:
- Capture early ideas as draft issues during planning.
- Refine them until they are actionable.
- Convert the ones that matter into real issues in the appropriate repository.
That distinction matters. A project full of real issues too early creates noise. A project full of draft issues forever creates shadow work. Start light, then promote work into the repository when it's ready.
Master Custom Fields¶
GitHub Projects gets powerful when you stop treating it like a simple board and start treating it like a data model. Your custom fields are the schema that your views and automation depend on.
For most teams, the minimum useful schema looks like this:
| Field | Type | Suggested Values | Why It Exists |
|---|---|---|---|
Status | Single select | Backlog, In Progress, In Review, Completed | Workflow state |
Priority | Single select | P0, P1, P2 | Urgency and sequencing |
Size | Single select or number | X-Small, Small, Medium, Large, X-Large or 1, 2, 3, 5, 8 | Capacity planning |
Iteration | Iteration | 1- or 2-week cycles | Sprint or delivery cadence |
Start date | Date | Actual date values | Roadmap placement |
Target date | Date | Actual date values | Roadmap placement |
External ID | Text | JIRA-123, support case, internal ticket ID | Cross-system traceability |
Status¶
This is the field most teams get wrong first. They add too many states and recreate a workflow engine inside a project.
Start with four values:
| Value | Meaning |
|---|---|
Backlog | Captured, but not yet actively being worked |
In Progress | Someone is actively executing the work |
In Review | Code or design review is the current bottleneck |
Completed | The work is complete and closed |
That's enough for most software teams.
If your team really needs it, add Blocked later. Don't start with ten status values just because another tool had them.
For maintainers working across repositories with an active pull request review cycle, a richer status model can be worth it. A practical example looks like this:
| Value | Meaning |
|---|---|
Backlog | Captured, but not yet planned |
Planned | Prioritized and ready for an upcoming iteration |
In Progress | Active implementation work is underway |
Ready for Review | The work is ready for someone to review |
In Review | Review is actively happening |
Changes Requested | Review feedback must be addressed |
Changes Approved | The changes are approved and waiting to merge |
Changes Merged | The pull request merged, but follow-up work may remain |
Completed | The work is fully finished from a project perspective |
This kind of status field fits multi-repository maintenance especially well. It helps you separate "code exists", "review is happening", "the PR merged", and "the overall work is truly done". Those states are often not the same when you are coordinating release notes, docs, compatibility updates, or follow-on cleanup.
Use Richer Status Values Deliberately
If you adopt a larger status set like this, keep the names tied to real decisions and real handoffs. Every status should answer a practical question: what is waiting, who needs to act next, and what changed since the last view of the board?
Priority¶
Priority is not the same thing as status. A P0 item can still be Backlog.
Use a simple scale:
| Value | Meaning |
|---|---|
P0 | Production issue, customer blocker, or work that must be handled now |
P1 | Important near-term work |
P2 | Useful, but not urgent |
If you add P3, teams often stop treating priority as a real decision. Keep the scale small.
If numeric-style priority labels feel too formal or too product-management-heavy, a plain-language scale can work better:
| Value | Meaning |
|---|---|
Urgent | Needs attention immediately, often due to a production problem, broken release, or maintainer blocker |
High | Important work that should be pulled forward soon |
Medium | Valuable work, but not the next fire to put out |
Low | Worth doing, but safe to defer |
This model is especially effective for teams balancing work across several repositories because it reads naturally at a glance. When you are juggling a bug, a release task, a documentation fix, and an enhancement request across multiple repositories, Urgent / High / Medium / Low is often easier to scan and easier to explain to contributors than P0 / P1 / P2.
The label style matters less than the shared definition behind it. The field is only useful if it helps the team decide what gets worked next.
Size or Estimate¶
Pick one estimating model and stick to it.
For teams that want quick planning:
| Value | Meaning |
|---|---|
X-Small | Tiny change, usually low risk and often same day |
Small | Small change with limited coordination |
Medium | Moderate effort with some review or testing overhead |
Large | Meaningful work that likely spans multiple sessions or reviewers |
X-Large | Large, risky, or cross-repository work that probably should be split |
For teams already using agile estimation, use a number field or a single-select field with story points such as 1, 2, 3, 5, and 8.
For maintainer teams and internal platform groups, this X-Small through X-Large model is often more useful than story points. It is fast to apply, easy for occasional contributors to understand, and good enough for planning a mix of bug fixes, release tasks, documentation updates, and cross-repository changes.
Treat X-Large as a Signal
If an item is consistently landing in X-Large, that's often a sign that it should be split into smaller issues, tracked as an initiative, or handled as a roadmap item rather than a normal backlog task.
The main rule is consistency. A field no one trusts becomes a decorative column.
Iteration¶
The iteration field is where GitHub Projects starts to feel like a real sprint workspace instead of a generic kanban tool.
What Is an Iteration
In GitHub Projects, an iteration is effectively a sprint for teams using timeboxed planning. GitHub uses the broader term because it also fits teams that plan in weekly or biweekly cycles without formally calling them sprints.
A good setup:
- Create an Iteration field.
- Choose your sprint cadence, usually one or two weeks.
- Add scheduled breaks for holidays or company shutdowns if your team needs them.
- Use iteration as the default planning bucket, not milestone labels. For release-scoped grouping in a single repository, GitHub Milestones as Release Payloads is often the better fit.
Iterations work especially well because GitHub Projects can use them in table, board, and roadmap views. That makes one field do work across planning, standups, and reporting.
External Tracking IDs¶
Sometimes GitHub Projects is the operational hub, but not the only system that matters. You may still need to reference a Jira issue, a support case, an internal engineering tracker, or another enterprise record.
A simple text field handles this well.
Examples:
| Field Name | Example Value | Use Case |
|---|---|---|
External ID | JIRA-2481 | Link work back to an internal delivery tracker |
Support Case | SR 3-12345678901 | Track a vendor or customer support escalation |
Internal Issue(s) | ENG-4421 | Preserve internal issue references alongside public work |
This is one of those fields that looks minor but becomes very useful during release prep, escalations, and status reporting. It gives maintainers a lightweight way to preserve traceability without forcing the GitHub issue title or body to carry every external identifier.
GitHub-First Does Not Have to Mean GitHub-Only
If your team still depends on Jira, a support system, or another internal tracker, a text field for external references is often the cleanest bridge. It keeps GitHub Projects usable without pretending the rest of your delivery environment doesn't exist.
Design the Views That Matter¶
A good project has more than one view. Different conversations need different slices of the same data. In practice, that usually means a mix of:
- Shared team views for backlog grooming, planning, and review
- Personal working views for "what do I need to move today?"
- Repository- or area-specific views when one project spans many related codebases
Planning View¶
The planning view should feel like a backlog spreadsheet, not a kanban lane view.
Set it up like this:
- Create a new view named Planning.
- Set the layout to Table.
- Show these columns:
Title,Repository,Status,Priority,Size,Iteration,Assignees - Group by Iteration.
- Sort by Priority, then by Size.
- Filter out completed work if you want a cleaner backlog.
This view is where sprint planning, backlog grooming, and cross-repository prioritization should happen. For maintainers coordinating several repositories, it's often the best place to line up bug fixes, release prep, documentation updates, and compatibility work in one place.
If you use numeric estimates, turn on Field sum for the estimate column. Seeing the point total per iteration is one of the easiest ways to avoid overcommitting the sprint.
Maintainer View¶
One of the most useful views in a multi-repository project is a personal working view, usually something like My items.
Set it up like this:
- Create a new view named My items.
- Set the layout to Table.
- Filter to:
assignee:@me - Show columns that help you act quickly, such as:
Title,Status,Linked pull requests,Repository,Sub-issues,Priority - Group by Status.
- Hide empty groups if you want a tighter operational view.
This kind of view is excellent for maintainers because it answers a different question than the planning board. It isn't "what is the whole project doing?" It's "what is on me right now?"
In a view like this, the status groups are doing real work. You can scan:
- what is still in
Backlog - what is actively
In Progress - what is
Ready for Review - what is already
In Review - what has already been
Completed - which items already have linked pull requests
That last point matters more than it sounds. Seeing the Linked pull requests column beside the item title makes it much easier to connect planning state to actual code movement. At a glance, you can tell which assigned items already have active PRs tied to them.
Daily Standup View¶
The daily standup view should answer one question quickly: what is moving right now?
Set it up like this:
- Create a new view named Daily Standup.
- Set the layout to Board.
- Group by Status.
- Filter to the current iteration.
- Optionally hide
Completedif you want a tighter daily focus. - Keep cards lightweight: title, assignee, repository, and priority are usually enough.
With a richer maintainer workflow, this usually means columns like:
BacklogIn ProgressReady for ReviewIn ReviewCompleted
If your team wants standups to stay short, don't use this view to debate priority or redesign the sprint. That belongs in the planning view.
If you're a solo maintainer, this still works. The view becomes a quick operational snapshot of what is actively being coded, what is waiting for review, and what can ship next.
Repository or Area Views¶
When one project covers many repositories, it's often worth creating focused views for a product area or repository family.
Examples:
Platform APIsShared ToolingDeveloper DocsRelease Engineering
Set these up with repository filters, then choose the layout that matches the work. A table view is great for triage and dependency tracking. A board view is better when you want to focus on status movement within one area.
A repository-scoped view can look like this:
- Create a view named Platform APIs.
- Filter it to the repositories that belong in that slice of work.
- Group by Status.
- Keep the active statuses visible:
Backlog,In Progress,Ready for Review,In Review,Completed - Include columns like Linked pull requests and Sub-issues if those relationships matter for that area.
This kind of view is especially useful when one initiative spans several related repositories. It lets you focus on one ecosystem at a time without losing the benefits of having everything in one project.
That repository-scoped view keeps the project from feeling overwhelming. Instead of one giant backlog for everything, you can jump into the slice that matches the work you're handling at that moment.
Executive View¶
Executives and project leads usually don't want a kanban board. They want a time-based view of major initiatives. In open source and inner source, this is often closer to a portfolio roadmap: upcoming releases, milestone work, deprecations, or cross-repository compatibility efforts.
Set it up like this:
- Create Start date and Target date fields if you haven't already.
- Create a new view named Executive.
- Set the layout to Roadmap.
- Configure the roadmap to use Start date and Target date.
- Filter the view to only high-level work, such as:
label:epicor a custom field likeTrack = Initiative - Zoom out to Quarter or Year.
- Slice by repository, team, or priority if that helps leadership discussions.
Roadmap views in GitHub Projects can use date fields or iteration fields to position work on the timeline. For cross-repository initiatives, date fields are usually clearer because they allow longer-running items that don't fit neatly inside one sprint.
A useful practice here is to track epics as real issues in a planning or meta repository, then link the implementation issues from the working repositories underneath them through normal issue references and project filters. For example, one roadmap item might represent a coordinated release across an application repository, its supporting library, and the related documentation.
Automation¶
GitHub Projects includes built-in workflows that can update item status, auto-add items from repositories, and archive completed work. This is where Projects becomes especially useful for multi-repository maintenance, because repository events can drive project state instead of relying on maintainers to update cards by hand.
You can manage these workflows from the project menu under Workflows.
Auto-Add New Issues from Specific Repositories¶
This is the first automation most teams should enable.
Setup:
- Open your project.
- Open the project menu.
- Click Workflows.
- Create a workflow to auto-add items.
- Select the repository that should feed this workflow.
- Add a filter so you don't pull in everything blindly.
If your project spans many repositories, it's often cleaner to create one add-to-project workflow per repository instead of one giant catch-all rule. That gives you a durable pattern like this:
Add to Project: BlueAdd to Project: GreenAdd to Project: OrangeAdd to Project: PurpleAdd to Project: Yellow
That approach works well for maintainers because each repository can have slightly different intake rules without turning the project into a giant filter puzzle.
Good starter filters:
If you want both issues and pull requests to enter the project automatically, a filter like this is practical:
Then scope the workflow to the selected repository and item types you actually want to track.
For many maintainer-led workflows, a filter like is:issue is:open is often enough. For product teams, be more selective so the project doesn't become a mirror of every repository issue list.
Automate Status Changes¶
This is where a richer maintainer workflow really pays off. Instead of stopping at a simple start-and-finish model, you can let pull request review activity and item lifecycle events update statuses automatically.
A strong baseline looks like this:
| Workflow | Suggested Status Result |
|---|---|
| Item added to project | Backlog |
| Pull request review requesting changes | Changes Requested |
| Pull request approved | Changes Approved |
| Pull request merged | Changes Merged or Completed |
| Item closed | Completed |
| Item reopened | Backlog |
This gives you a project that stays aligned with what is actually happening in GitHub.
Set Backlog When an Item Is Added¶
This is a great default for a cross-repository project.
Setup:
- Open Workflows.
- Select Item Added to Project.
- Configure it for the item types you care about, usually issues and pull requests.
- Set
Status = Backlog.
This works especially well when you have many repository-specific add-to-project workflows, because new work lands in one predictable state before you triage it.
Move Status on Review Activity¶
If your project tracks pull requests directly, built-in review workflows are surprisingly useful.
Setup:
- Open Workflows.
- Enable Code Changes Requested and set
Status = Changes Requested. - Enable Code Review Approved and set
Status = Changes Approved. - Optionally enable Pull Request Merged and set
Status = Changes MergedorCompleted.
For teams using review-driven workflows, this is one of the highest-value automations in Projects. It keeps the project synced to review reality instead of leaving maintainers to remember whether a PR is waiting on feedback, waiting on merge, or truly done. Pair it with a solid pull request template so review context stays consistent.
Move Work to a Terminal State When an Issue Closes or a Pull Request Merges¶
This part is easier. GitHub Projects ships with default workflows for it.
Setup:
- Open the project.
- Open Workflows.
- Review the default workflow for item closed and ensure it sets
Status = Completedor your equivalent terminal state. - Review the default workflow for pull request merged and ensure it also sets
Status = Changes Merged,Completed, or the terminal state that best matches your workflow. - Save and enable both workflows if they aren't already on.
For most teams, these should stay enabled. They are the easiest way to keep the project honest without asking engineers to drag cards manually after every merge.
Reopened Means Backlog Again¶
Reopened work is one of the easiest things to miss if you don't automate it.
Setup:
- Open Workflows.
- Enable Item Reopened.
- Set
Status = BacklogorPlanned, depending on how your team re-triages reopened work.
This helps because a reopened bug or pull request should usually re-enter the project as active triage, not stay stranded in a completed state.
Auto-Archive Closed Work¶
Once the project has accurate terminal states, auto-archive keeps old work from piling up forever.
Setup:
- Open Workflows.
- Select Auto-archive Items.
- Add a filter for the completed items you want to archive on a schedule.
A practical example looks like this:
Using updated: is helpful because it lets GitHub re-run the workflow on a schedule and archive items after they have stayed closed for a while, instead of immediately disappearing from the project.
Tips for Power Users¶
Use GitHub Actions and GraphQL When Built-In Automation Stops Short¶
Built-in workflows are great until you need to update one project item based on an event that happens on another item. A common example is moving an issue to In Progress when a pull request linked to that issue is opened.
That's a good use case for GitHub Actions plus the GraphQL API.
name: project-status-sync
on:
pull_request:
types: [opened, reopened]
jobs:
update-project:
runs-on: ubuntu-latest
steps:
- name: Move project item to In Progress
env:
GH_TOKEN: ${{ secrets.PROJECT_TOKEN }}
PROJECT_ID: ${{ secrets.PROJECT_ID }}
ITEM_ID: ${{ secrets.PROJECT_ITEM_ID }}
STATUS_FIELD_ID: ${{ secrets.STATUS_FIELD_ID }}
IN_PROGRESS_OPTION_ID: ${{ secrets.IN_PROGRESS_OPTION_ID }}
run: |
gh api graphql -f query='
mutation($project:ID!, $item:ID!, $field:ID!, $option:String!) {
updateProjectV2ItemFieldValue(input: {
projectId: $project
itemId: $item
fieldId: $field
value: { singleSelectOptionId: $option }
}) {
projectV2Item {
id
}
}
}' \
-F project="$PROJECT_ID" \
-F item="$ITEM_ID" \
-F field="$STATUS_FIELD_ID" \
-F option="$IN_PROGRESS_OPTION_ID"
In a real workflow, you would usually look up ITEM_ID dynamically from the linked issue or pull request rather than storing it as a fixed secret. The bigger point is that GitHub Projects has a real API surface, so you're not boxed into the built-in workflow menu.
Learn the Keyboard and Bulk-Edit Habits¶
You don't need a long list of shortcuts to get faster. You need a few habits:
- Press
?anywhere on GitHub to open the keyboard shortcut reference. - Treat the table view like a spreadsheet: edit fields inline instead of opening every item.
- Use multi-select and bulk-edit for iteration changes, priority changes, and cleanup at the start or end of a sprint.
Teams that do this consistently spend much less time "maintaining the project" and more time using it to make decisions.
GitHub CLI Reference¶
The GitHub UI should be the default path for most teams getting started. The gh CLI becomes more useful later, when you want to script setup, inspect field IDs, or seed items quickly from the terminal.
The minimum token scope is project.
Use these commands as a reference:
| Task | Command |
|---|---|
| Create a project | gh project create --owner my-org --title "Multi-Repo Sprint Board" |
| Link a repository | gh project link 7 --owner my-org --repo my-org/blue-service |
| Create a draft item | gh project item-create 7 --owner my-org --title "Plan vNext compatibility testing for blue-service" |
| Add an existing issue or pull request | gh project item-add 7 --owner my-org --url https://github.com/my-org/blue-service/issues/123 |
| List project fields | gh project field-list 7 --owner my-org |
| Open the project in your browser | gh project view 7 --owner my-org --web |
This is especially useful when you need to confirm the exact project schema before writing automation against it.
GitHub Projects works best when it is treated as a planning layer for the work already happening in GitHub, not as a separate bureaucracy. A small set of fields, a few purpose-built views, and a handful of automations is usually enough to replace a lot of external tooling.
If your team already lives in GitHub, build one project this week: define Status, Priority, Size, and Iteration, create the planning and standup views, and turn on the default automations. Start by linking the repositories that actually ship together and let the project become the shared operational layer above them. Once that foundation is working, add the roadmap and the advanced automation only where they solve a real problem.
References¶
- How to Write Effective GitHub Issue Templates
- GitHub Milestones as Release Payloads
- How to Write an Effective GitHub Pull Request Template