Plans
A plan says what we mean to build and why before anyone builds it. It covers product requirements, the engineering approach and, above all, mockups. One can cover a whole new project or a single feature. Writing it first is cheaper than finding out in review that the screen was wrong.
Where plans live
Section titled “Where plans live”Every plan is in one private project, svrbc/plans.svrbc.org,
published at plans.svrbc.org on GitLab Pages, for members
only.
- Private, because plans are unpublished material (New projects): features the church hasn’t announced, and sometimes details about members.
- One project for every plan, not a
plans/folder in each repository, because a plan can span several repositories and it outlasts any branch. The site also gives one place to see what’s planned across SVRBC. - A custom domain works with members-only Pages. A visitor who isn’t
signed in is sent to GitLab to sign in, then back to
plans.svrbc.org. GitLab’s documentation doesn’t say so, but the Pages server handles it (handleProxyingAuthininternal/auth/auth.go). The domain must be verified in the project’s Pages settings. Tried on 2026-10-24: a member signed in to GitLab lands on the page. Before the first deployment, the same sign-in ends in GitLab’s 401, since Pages doesn’t know the domain yet. - Changes arrive as merge requests from its fork, like any other project’s (Source code). The fork of a private project is private too (checked 2026-10-24).
- Merge a plan as a release: bump
versionin its merge request (svrbc-mr --ship), since a plan isn’t on the site until it’s released.
When to write one
Section titled “When to write one”Before work starts on a new project, or on a feature that changes what people see or will take more than one merge request, the developer is asked whether they want a plan first. An agent asks before it writes any code (see Agents files), and so does a reviewer who sees such work arrive without one. The answer can be no. The point is that nobody skips the plan by accident.
Bug fixes, refactors, dependency updates and infrastructure-only changes don’t need the question.
Addresses
Section titled “Addresses”Every plan is at the top level: plans.svrbc.org/<slug>. Plans aren’t
filed under a repository’s name, because one plan can span several
repositories, and the repository a feature lands in can change while it’s
planned.
- A plan for a new project takes the project’s name as its slug:
plans.svrbc.org/recipes.svrbc.org. - A plan for a feature gets a name that’s clear without its project,
in lowercase kebab case:
recipes-search,bulletin-email-signup. - A slug never changes once it’s merged, since merge requests and issues
link to it. A second plan for the same thing gets a new slug
(
recipes-search-filters), not an edit of the first. - The projects a plan touches go in its frontmatter (below). The home page lists plans by project and by status, so you can still browse by repository.
Each plan is a directory, plans/<slug>/index.md in the repository, with
its mockups in plans/<slug>/mockups/ beside it. The site serves them at
/<slug>/ and /<slug>/mockups/.
What a plan contains
Section titled “What a plan contains”One document, scaled to the work. A feature plan can be a page; a new project’s plan fills every section. Skip a section that has nothing to say, but don’t skip the mockups when anyone will see the work.
The frontmatter:
---title: Recipe searchprojects: [recipes.svrbc.org] # every project it touches, by GitLab pathscope: feature # feature, or project for a new onestatus: draft # see Lifecycleowner: cco3 # GitLab username of whoever drives itmerge-requests: [] # the merge requests that build it---The sections, in this order:
- Problem, and who it’s for. The church, its members, visitors or developers. What they can’t do today.
- Goals and non-goals. Non-goals stop the plan from growing in review.
- Mockups. See below.
- Behavior. User flows, edge cases, permissions, what happens when it fails.
- Engineering. The tier, data, hosting and infrastructure, cost, and what’s reused versus new. Link to the handbook rather than repeating it.
- Decisions, with their reasons. As this handbook does: a decision with its reason gets applied sensibly to cases nobody anticipated.
- Open questions, as a checklist, ticked as they’re answered.
- Done means. How we’ll check it works once it ships, and anything we’ll measure.
Mockups
Section titled “Mockups”Mockups are the part of a plan that matters most. A reviewer can disagree with a screen in a way they can’t with a paragraph.
- HTML, not just pictures. Build mockups with the real site’s styles (an
existing site’s, or the template’s for a new one), commit them
under
mockups/, and the plans site serves them live, so a reviewer can click through them. - Screenshots for review. CI captures each mockup as an image, so merge requests show what changed without opening anything. Not built yet; see Open questions.
- Every state, not just the happy one: empty, loading, error, long content, phone and desktop widths, and dark mode.
- Before and after for a change to an existing screen.
- Notes for what a picture can’t say: what a button does, where the data comes from.
- Rough is fine early, as long as it’s labeled a sketch.
Review and acceptance
Section titled “Review and acceptance”A plan is accepted when its merge request merges, so it’s reviewed like code, in comments on the merge request.
- A plan for an existing project is approved by that project’s owners. One that touches several projects needs the owners of each.
- A plan for a new project is approved by a maintainer of the
svrbcgroup, since the project has no owners yet.
Lifecycle
Section titled “Lifecycle”status moves through:
| Status | Means |
|---|---|
draft |
Being written; its merge request is open |
accepted |
Merged; work can start |
building |
Merge requests are building it; list them in merge-requests |
shipped |
Deployed |
abandoned |
Not going ahead; say why in the plan |
Each merge request that builds a plan links to it, and the plan lists the merge request. When the work departs from the plan, update the plan in a merge request of its own, or add a note saying what changed and why. A shipped plan is a record of why the thing is the way it is.
Open questions
Section titled “Open questions”- Signing in works on
plans.svrbc.org(2026-10-24). - The review bot can read the private project and its fork, once its token has Project: Read (Tools, 2026-10-24).
- Check that a plan whose work people will see has mockups. The build already refuses a plan without its frontmatter or with a bad slug.
- Have CI capture each mockup as images for merge requests.
- Wire plan approval into the review bot: owners of every project in
projects, or a maintainer for a new one.