Skip to content

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.

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 (handleProxyingAuth in internal/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 version in its merge request (svrbc-mr --ship), since a plan isn’t on the site until it’s released.

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.

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/.

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 search
projects: [recipes.svrbc.org] # every project it touches, by GitLab path
scope: feature # feature, or project for a new one
status: draft # see Lifecycle
owner: cco3 # GitLab username of whoever drives it
merge-requests: [] # the merge requests that build it
---

The sections, in this order:

  1. Problem, and who it’s for. The church, its members, visitors or developers. What they can’t do today.
  2. Goals and non-goals. Non-goals stop the plan from growing in review.
  3. Mockups. See below.
  4. Behavior. User flows, edge cases, permissions, what happens when it fails.
  5. Engineering. The tier, data, hosting and infrastructure, cost, and what’s reused versus new. Link to the handbook rather than repeating it.
  6. Decisions, with their reasons. As this handbook does: a decision with its reason gets applied sensibly to cases nobody anticipated.
  7. Open questions, as a checklist, ticked as they’re answered.
  8. Done means. How we’ll check it works once it ships, and anything we’ll measure.

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.

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 svrbc group, since the project has no owners yet.

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.

  • 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.