Roadmap
Phases, not dates. A phase is done when the whole of it works offline on a real phone at a real crag — not when the code merges.
Items move out of this page and into shipped documentation when they land. Items that are wanted but not committed live on the wishlist; an item is promoted from wishlist to roadmap only when someone has decided it is actually next.
Several phases below are gated on decisions nobody has made yet. Those are collected on decisions we owe rather than guessed at here.
:::tip This page is the shape. The backlog is the order.
A phase says what belongs together and why one has to come before another. It does not say what anybody is picking up next — for that, read the backlog, which flattens everything below into one loosely ordered list with the core work at the top.
Status lives here, in these tables. Order lives there. Neither page duplicates the other's job. :::
:::note Status key
Shipped In progress Not started :::
The shape of the plan
Crag Topo is three products stacked on each other, and the stacking order is the whole argument for this ordering:
- A guidebook that works in airplane mode, on routes where being wrong is dangerous. Phases 1–5. Useful on its own.
- A guidebook the community writes. Phases 6–8. This is what makes coverage possible without a publishing deal — and it is the keystone: it generates the photos, lines and geometry that everything after it consumes.
- A guidebook that knows where you are standing. Phases 10–11. AR, 3D, beta. Impossible without the volume of contributed imagery that phase 6 produces.
Read that as a constraint, not a preference. AR route lines are the most exciting thing on this page and they are tenth, because pointing a camera at a wall is worthless until enough walls have lines drawn on them — and enough walls only get lines drawn on them if strangers can do the drawing and get paid for it.
Phase 0 — Foundations
Getting the machine working before building anything on it.
| Item | Status | Notes |
|---|---|---|
| Monorepo, workspaces, shared types | Shipped | ADR-0001 |
| Cloudflare Worker + D1, migrations, seed data | Shipped | ADR-0002 |
| Expo app shell, native tabs, Liquid Glass surfaces | Shipped | ADR-0003 |
| On-device SQLite + delta sync protocol | Shipped | ADR-0004 |
| Docs site, decision log, wiki | Shipped | ADR-0005 |
| Preview deployment on every PR | Shipped | ADR-0006 |
| Container / design-component split | Shipped | ADR-0008 |
| Accounts and identity | Not started | Deferred by ADR-0007 — now blocking |
:::danger The identity deferral has become the critical path
ADR-0007 parked accounts on the reasoning that a guidebook does not need them. That was right for a guidebook. It is not right for a guidebook that credits its authors and pays them.
Phases 5, 6, 7, 8, 9 and 12 all require a durable identity that survives a lost phone, and phase 8 requires one strong enough to attach money to. Nothing below phase 5 is blocked; almost everything above it is. Superseding ADR-0007 is the single highest-leverage decision on this page — see decisions we owe. :::
Phase 1 — A usable guidebook
The minimum thing a climber would actually take to a crag instead of Rockfax.
| Item | Status | Notes |
|---|---|---|
| Browse crags, sectors, routes from local data | In progress | List screens exist; detail is thin |
| Image storage and delivery (R2 + transforms) | Not started | Needs an ADR — bucket, CDN, sizes |
| Topo photo viewer: pinch, pan, route lines | Not started | TopoOverlay renders lines already |
| Tap a line to select the route; tap a route to highlight its line | Not started | The core interaction |
| Route detail: description, gear, first ascent, history | Not started | |
| "Download this crag" with progress and size | Not started | Images are the bulk of it; phase 4 automates it |
| Approach: parking pin, walk-in time, offline map tiles | Not started | Offline tiles need an ADR; phase 2 makes it structured |
| Access restrictions surfaced prominently and dated | Not started | Safety-critical; see principles |
| Filter routes by grade band, type, stars | Not started | gradeBand already stored |
| Approximate grade conversion, shown beside the published grade | Not started | ADR-0010 |
| Route characteristic tags, as symbols and pills | Not started | See below — vocabulary needs a decision |
| Filter and search by tag | Not started | Falls out of the vocabulary for free |
| Offline search across everything downloaded | Not started | SQLite FTS5 — instant, with no network path at all |
| Real crag data for at least two crags | Not started | Licensing question, not a technical one |
Route tags: what a guidebook says in a symbol
A guidebook conveys half of what it knows through icons in the margin. The app should do the same, better, because a tag is filterable and a printed icon is not — "sport, 6a to 6c, dries fast, shade in the afternoon, not polished" is the query people actually want to run and cannot.
Roughly what wants tagging, in five groups:
| Group | Examples |
|---|---|
| Safety | Loose rock, bold, poor gear, unprotected start, bad landing, tidal, polished |
| Shape | Slab, vertical, overhang, roof, arête, crack, chimney, corner, groove |
| Movement | Crimpy, juggy, slopers, pockets, technical, powerful, sustained, off-width |
| Conditions | Seeps, dries fast, morning sun, afternoon shade, midgy, exposed to wind |
| Logistics | Abseil approach, sea cliff, walk-off, lower-off, stakes needed, kid-friendly |
Four rules that matter more than the list itself:
- A controlled vocabulary, never free text. Free tags fragment into "runout", "run-out" and "bold" within a week, and a fragmented tag cannot be filtered, counted, translated, or voted on. This is the decision that has to be right first; everything else is editorial.
- Safety tags do not look like flavour tags. "Loose rock" and "crimpy" must be visually distinct and safety must sort first. They are different kinds of claim (principle 3) and rendering them identically flattens the difference.
- Never a symbol on its own for anything safety-related. A glyph for "loose rock" is not self-evident to anyone, and it is invisible to a screen reader. The icon is shorthand for a label, never a replacement for one.
- A cap on the card. Twelve pills on a route row is noise. The card shows the top few by a fixed priority with safety first; the detail screen shows everything.
Tags are also the cheapest thing in the app to build consensus on later — "is it polished?" is
exactly what a lot of people voting can answer and one editor cannot. That is phase 7, but the
vocabulary has to exist first, and it is worth collecting opinions from the first tick, on the same
argument as suggestedGrade in principle 7.
Done means: you can take an iPhone in airplane mode to Stanage and find, read, and identify a route without ever seeing a spinner.
Phase 2 — Multi-pitch, alpine, and the ways in and out
This phase is early because it is the case where being wrong hurts someone.
On a single-pitch crag, a wrong description costs you a bit of pride and a wrong walk-in costs twenty minutes. On a twelve-pitch route it is different in kind: more days go wrong on the descent than on the climb, an abseil line that is out by one station puts you somewhere with no anchor, and a descent that assumes two 60 m ropes when you brought one is a night out. Alpine routes also change — a fixed rope goes, a bergschrund opens, a pitch that was solid is now loose — which means the record has to carry not just what is true but when somebody last checked.
Principle 3 has been amended to say this outright: approach and descent are safety information, not logistics.
What the data model has to grow
The current shape assumes a route is one line, on one photo, with one grade. That is true for grit and sport crags and false for everything this phase is about.
| Today | What multi-pitch and alpine need |
|---|---|
| A route has one grade | A route has a set of grades — overall alpine (PD/AD/D/TD/ED), rock, ice (WI), mixed (M), aid (A) — none of them converted into the others |
| A route is a single unit | A route has pitches: number, grade, length, belay description, the gear for that pitch |
| A route line is drawn on one photo | A 300 m route does not fit a photo. It needs a schematic topo — the drawn line diagram with pitch bubbles — alongside the photo of the wall |
| Descent is prose, if it exists | Descent is its own record, shared between routes: type, rope length required, number of abseils, whether stations are in-situ, and how old that information is |
| Approach is a pin and a number | Approach is a record too: terrain, scrambling grade, glacier or not, seasonal notes, the hut |
| Facts are timeless | Alpine facts decay. A condition report needs a date, and a stale one has to read as stale rather than as truth |
What it has to feel like
- Pitch-by-pitch mode. One pitch per screen, big enough to read at a hanging belay in gloves, showing the grade and the gear for the pitch you are about to lead. Advance with a target you can hit without looking.
- The descent is one tap away from anywhere on the route. Not buried at the bottom of a description you have to scroll through in the dark.
- A low-power view. An alpine day outlives a phone battery. A dimmed, text-only, nothing-streaming mode is a safety feature, not a nicety.
- Retreat, stated. Where you can bail from, what it takes, and where the anchors are. Almost no guidebook does this systematically, and it is exactly the information you want at the worst moment of the day.
- Logging that matches reality. Led everything, swung leads, seconded, or retreated from pitch six. "I did it" means different things and the record should say which.
| Item | Status | Notes |
|---|---|---|
| Pitches as first-class records | Not started | Schema change — needs an ADR and a data-model update |
| Multiple grades per route, none converted into each other | Not started | ADR-0010; alpine, rock, ice, mixed and aid at once |
| UK trad grades always carry a technical grade | Not started | Validation plus a rule for imported data that lacks one |
| Descent as its own record, with rope length and station type | Not started | Safety-critical. Shared between routes |
| Structured approach: terrain, scrambling grade, hut, season | Not started | Supersedes today's approach_minutes |
| Schematic pitch topos alongside photo topos | Not started | A second rendering mode, not a second image |
| Retreat and bail-out information | Not started | |
| Dated route condition reports that visibly age | Not started | The mechanism the community fills in during phase 7 |
| Objective hazards and the season a route is in condition | Not started | |
| Pitch-by-pitch mode and the low-power view | Not started | |
| Multi-pitch logging: led, swung, seconded, retreated | Not started | Lands with phase 5 |
Done means: you can do a twelve-pitch route in the Dolomites on a phone in airplane mode, find the abseil line in the dark, and know before you left the hut whether the rope you packed gets you down.
Phase 3 — Navigation that matches where you are
Today the app has three tabs — Crags, Logbook, Profile — which was right for a browsing shell and is wrong for the product described on this page. This phase settles the information architecture before there are twenty screens fighting over five slots.
The proposal, and the reasoning:
| Tab | SF Symbol | What it is |
|---|---|---|
| Nearby | location.circle | Crags around you, closest first. Becomes this crag when GPS says you have arrived. |
| Map | map | The same data spatially: clustered pins, filters, offline tiles, parking, approach. |
| Plan | flag | Ticklist, wishlist, trips, conditions. "What am I doing on Saturday." |
| Logbook | book | What you have climbed. History, filters, totals. |
| Feed | person.2 | Friends' ascents, crag updates, conditions reports. |
Three deliberate calls in that table:
- There is no "Crag" tab. A crag is a push destination from Nearby or Map, never a tab — a tab is a place you can always go, and "the crag" is only meaningful once you have picked one. Instead, Nearby becomes the crag when you are standing at it, which is principle 1 taken literally.
- Profile stops being a tab. It becomes the avatar in the large-title navigation bar, which is where iOS has put account for years now. That frees the fifth slot for something people open daily.
- Five, not six. iOS collapses anything past five into a "More" list, which is where features go to be forgotten. If a sixth earns a place, something else has to lose one.
| Item | Status | Notes |
|---|---|---|
| Settle the five-tab structure | Not started | Needs a decision — decisions we owe |
| Nearby: distance-sorted crags, "you are at" state | Not started | Needs a background-location permission policy |
| Map tab: clustered pins, grade and type filters | Not started | Offline tiles are the blocker, not the map |
| Plan tab: ticklist, trips, "wishlist routes at this crag" | Not started | The query is cheap; the schema already supports it |
| Profile moves to the navigation bar | Not started |
Done means: every screen in the app is two taps from wherever you are standing, and no tab exists that you would not open on a normal Saturday.
Phase 4 — Storage you never think about
The download model today is manual: you choose a crag, you get a crag. That does not survive contact with a real trip, where you look at nine crags on the drive and want all nine on the walk in.
Three tiers, and the whole point is that the middle one is automatic:
| Tier | What happens | Evicted? |
|---|---|---|
| Pinned | You said keep it. Full imagery, permanently. | Never, without you saying so |
| Cached | You looked at it, so it downloaded itself in the background. | Yes — least-recently-used, when space is needed |
| Metadata | Every crag in your region: names, grades, access, parking. Kilobytes. | Never — too small and too safety-relevant to drop |
Rules that make the automatic tier trustworthy rather than annoying:
- A budget, not a surprise. One slider in Settings: use up to N GB. The app never exceeds it and never asks again.
- Wi-Fi and charging by default, with an explicit "download now over cellular" for the person in a layby at 7am.
- Never evict what you are about to need. A crag attached to a trip in the next fortnight is exempt from LRU, as is anything downloaded in the last 24 hours.
- Never evict safety text. Access status, restrictions, approach and descent stay for every crag you have ever opened. They are text, they cost nothing, and getting them wrong gets someone lost or worse.
- Say what it costs before it costs it. Per-crag size shown before download, and a storage screen that breaks down where the gigabytes went, per crag, with a swipe to free.
| Item | Status | Notes |
|---|---|---|
| Three-tier storage model in the local schema | Not started | user_crags gains a tier and a last-viewed stamp |
| Auto-download on view, in the background | Not started | The iOS background task budget is the real constraint |
| LRU eviction with the exemptions above | Not started | Needs an ADR — it is cross-cutting to sync |
| Storage settings: budget slider, per-crag breakdown | Not started | |
| Pre-emptive download from a planned trip | Not started | "Heading to the Peak Saturday — grab four crags, 340 MB?" |
Done means: nobody who used the app on the sofa on Thursday discovers on Saturday that the crag did not come with them.
Phase 5 — Logging
Recording what you climbed, with the people you climbed it with.
| Item | Status | Notes |
|---|---|---|
| Log an ascent: style, date, attempts, notes | Not started | Schema and sync already support it |
| Offline logging with the outbox, replayed on sync | Not started | Outbox table exists |
| Tag partners — Crag Topo users and free-text names | Not started | partnerUserIds / partnerNames |
| Mutual ticks: a tagged partner sees it on their logbook | Not started | Needs a consent model — ADR |
| Multi-pitch ticks: led, swung leads, seconded, retreated | Not started | Depends on phase 2 |
| Logbook screen: history, filters, totals | Not started | |
| Suggest a grade and star rating with your tick | Not started | Fields already collected |
| Wishlist: add, prioritise, note | Not started | Schema exists |
| Conflict resolution UI for the two-device case | Not started | Server currently wins silently |
Done means: a weekend's climbing can be logged from the car with no signal, and it is correct on both climbers' phones by Monday.
Phase 6 — Add a crag, from the crag
The keystone. Everything after this phase is downstream of it, because everything after this phase consumes contributed content.
The flow has to work standing at the crag, in airplane mode, because that is exactly where undocumented crags are. A contribution path that needs signal documents only the crags that were already documented.
| Item | Status | Notes |
|---|---|---|
| Add a crag: pin, name, access, parking, approach | Not started | Fully offline; drafts live in the outbox |
| Duplicate detection before a crag is created | Not started | Proximity plus fuzzy name. Without it we get six Stanages |
Capture a topo photo with shotFrom / shotBearing | Not started | Already columns on photos — this is what they were for |
| Draw a route line onto a photo, in-app | Not started | Finger trace, loupe magnifier, undo, belay anchors. The hard one |
| Fast bulk route entry after tracing | Not started | A list you tab through, not a form per route |
| Add pitches, a descent and an approach to a route | Not started | The phase 2 shape, from the contributor's side |
| Add a photo to an existing sector | Not started | |
| Attribution: every crag records its author | Not started | Shown on the crag screen, permanently. Needs identity |
| Submission states: draft, submitted, published | Not started | Nothing writes straight into the guidebook |
Done means: someone can document an unrecorded quarry on a Sunday afternoon with no signal, and it is in the app — credited to them — by Tuesday.
Phase 7 — Corrections, maintainers and moderation
Letting the app get better without letting it get dangerous. This is where principle 7 — curated data, contributed corrections — becomes machinery.
Roles, deliberately few:
| Role | Can | Earned by |
|---|---|---|
| Anyone | Propose an edit, report a problem, add a photo, log an opinion of a grade | Having the app |
| Contributor | The above, and small factual edits merge without review after a track record | Accepted proposals |
| Maintainer | Merges proposals for crags they maintain; answerable for their accuracy | Authoring a crag, or adopting one |
| Moderator | Merges anywhere, resolves disputes, handles safety escalations | Invitation |
And the rules those roles operate under:
- Edits are proposals, not writes. A proposal is a field-level diff with a reason attached. The route screen shows the published value; the proposal shows what would change and why.
- Safety-critical fields never auto-merge. Grade, gear notes, access status, bolt condition, descent and approach always need a human, regardless of the proposer's track record. No amount of reputation buys the right to silently change what somebody takes to a runout, or which gully they walk down in the dark.
- Every route has a visible history. "E2 5c since March 2026, changed from E1 5b by @someone, because…". Guidebooks have never been able to do this, and it is the most convincing argument that the app is more trustworthy than the book rather than merely more convenient.
- Reporting a problem is one tap and works offline. "Bolt looks bad", "the abseil station is gone", "the access sign has changed". Safety reports post a banner on the route immediately, before any review — a false warning costs an argument, a missing one costs more.
- Condition reports age in public. The phase 2 decay rule enforced socially: a route whose last condition report is three seasons old says so.
- Crags get adopted, not orphaned. A maintainer who goes quiet for a year has their crags offered to whoever is actually climbing there.
| Item | Status | Notes |
|---|---|---|
| Propose a field-level correction, with a reason | Not started | Offline; queued through the outbox |
| Route and crag change history, visible in the app | Not started | |
| One-tap problem report, with immediate safety banners | Not started | Safety-critical path — no review latency |
| Community condition reports on routes and descents | Not started | The highest-value contribution on an alpine route |
| Maintainer role and crag ownership | Not started | Needs identity, and an ADR on the trust model |
| Moderation queue and reviewer tooling | Not started | Probably a small web app |
| Trust levels that let small edits through | Not started | Never for safety fields |
| Grade and quality consensus from logged opinions | Not started | Displayed alongside, never replacing, the published grade |
| Tag consensus: what the crowd thinks a route is like | Not started | "Is it polished?" is a vote, not an editorial judgement |
| Contribution licence, shown at the point of contributing | Not started | Legal, and coupled to phases 8 and 9 — needs an answer |
Done means: a wrong grade at a crag nobody at Crag Topo has ever visited gets fixed by someone who has, within a week, and everybody can see who changed it and why.
Phase 8 — Paying contributors
Documenting a crag properly is a week of somebody's life. Maintaining one is a standing commitment. If that work is unpaid we get the crags near cities and nothing else — which is precisely the coverage a book already has.
So contributors get a share of revenue. Every part of how is an open question, and this section states the options rather than the answers — see decisions we owe.
Where the money comes from. Subscription, per-crag purchase, or licensed premium packs alongside free community content. These have very different consequences for contribution: a per-crag purchase model pays well for popular crags and nothing at all for obscure ones, which are exactly the crags a community can document and a publisher cannot.
How it is divided. A pooled royalty distributed by use is the obvious shape, with roughly an author share for whoever created the crag, a larger and ongoing maintainer share contingent on actually maintaining it — answering proposals, keeping access and conditions current — and a moderator pool funded off the top, because moderation benefits every crag and cannot be attributed to one.
What counts as use. Downloads, route views, ticks logged, or time spent. Whichever it is becomes the thing people optimise for, so it wants choosing carefully rather than by default.
Then the parts that are unglamorous and non-negotiable:
| Item | Status | Notes |
|---|---|---|
| Revenue model decided | Not started | ADR. Blocks everything else in this phase |
| Contribution licence granting commercial use | Not started | You cannot pay people for content you have no right to sell |
| Attribution ledger — who contributed what, immutably | Not started | Also the audit trail if a split is ever disputed |
| Usage accounting that survives offline use | Not started | Non-trivial: the app is deliberately designed not to phone home |
| Payouts, KYC, tax, thresholds, country coverage | Not started | Stripe Connect or equivalent. A real compliance cost |
| Anti-gaming: a crag earns nothing until verified by a second climber | Not started | Money attracts invented crags. It will happen in week one |
| A contributor dashboard: what you earned, and why | Not started | Transparency is the trust feature, not the accounting feature |
Done means: somebody who documents and maintains a crag properly is measurably better off for having done it, and can see exactly how the number was arrived at.
Phase 9 — Social and sharing
Two halves that share a phase because they share a dependency: inside the app, a feed; outside it, everything the app can put on somebody else's screen.
The feed
Decided in ADR-0009: there is a feed, in the Strava sense, and there is a wall down the middle of it. Engagement never influences guidebook data, safety information is never ranked by popularity, and the app is fully usable by someone who never opens the tab. That wall is now principle 8.
Sharing out
A route line is a beautiful object and it currently cannot leave the app. That is a missed opportunity twice over: it is the cheapest growth the product has, and every share is an attribution surface for the contributor who drew the line.
The pieces, roughly in order of value per unit of work:
- The tick card. Your ascent over the topo, line highlighted, name, grade, crag, style. The Strava share-card equivalent, and the single most-shared object in any app of this kind.
- Your photo, with the line on it. Your partner's photo of you climbing, with the route line drawn over the rock and a grade badge. This is the one people will actually post.
- Straight into Instagram Stories, as a sticker layer over a background rather than a flat screenshot — iOS supports handing both to Instagram directly. A share that arrives as a real sticker gets moved, resized and kept; a screenshot gets deleted.
- A sticker pack. iMessage stickers of route lines, grade badges, and the crags themselves. Low effort, disproportionate reach, and it puts the app in a conversation rather than a feed.
- Attribution travels with the image. Crag, route, the contributor who drew the line, and a link back. This is not branding — it is the promise made in phase 8 being kept in public.
- The link opens the route. A universal link into the app, and an App Clip for whoever does not have it, landing on the route rather than a marketing page.
And one restriction that has to be built in rather than added later:
- Sensitive crags share without their location. Access-restricted, sensitive or deliberately unpublicised venues get a share card that names the route and not the map reference. Some crags stay quiet by agreement, and a share sheet is a very effective way to break one.
| Item | Status | Notes |
|---|---|---|
| Follow people; a feed of their ascents | Not started | ADR-0009 |
| Sessions: a day at a crag as one feed item | Not started | Also the thing that makes logging fast |
| Reactions and comments | Not started | Comments bring moderation obligations with them |
| Crag conditions posts, expiring after 48 hours | Not started | "It's dry" is the most useful post on any climbing feed |
| Privacy model: what is visible, to whom, by default | Not started | Decide before the first post exists, not after |
| Share a route or tick as an image, sized for Stories | Not started | Rendered on device so it works offline |
| Draw a route line over your own photo, then share | Not started | Reuses the phase 6 tracing tool |
| Direct hand-off to Instagram Stories as a sticker | Not started | |
| iMessage sticker pack | Not started | Ships as an app extension |
| Attribution and a universal link on every share | Not started | Blocked on the contribution licence — sharing is redistribution |
| Location-suppressed shares for sensitive crags | Not started | Build it with the feature, not after the first complaint |
Done means: you find out your mate did their project without either of you texting about it, what you post about your own day looks good enough that you want to, and nothing about the guidebook got worse.
Phase 10 — Route lines on the live camera
Point the phone at the wall; the lines appear on it. The single hardest problem in climbing — which of those is Left Unconquerable — solved directly rather than worked around.
Staged, because the accuracy ceiling rises in steps and each step ships on its own:
| Stage | What it does | Accuracy |
|---|---|---|
| A | GPS, compass and shotBearing pick the likely topo and overlay it loosely | "Roughly there" |
| B | Visual feature matching against the stored topo gives a real homography | Line-accurate |
| C | ARKit world anchors hold the overlay steady as you walk along the base | Stable |
Stage A is honest and useful on its own: it tells you which topo you are looking at, which is most of the value. Stage B is where it becomes magic. Compass alone will not get there — iron in the rock makes the device compass unreliable at exactly the crags where this matters most.
| Item | Status | Notes |
|---|---|---|
| Camera view that identifies which topo you are facing | Not started | Stage A. Needs nothing new in the data model |
| Homography from live frame to stored topo photo | Not started | Stage B. On-device Vision; must work with no network |
| Route lines projected onto the live frame | Not started | Normalised coordinates project directly — as designed |
| ARKit anchoring so the overlay survives movement | Not started | Stage C |
| An always-available fall back to the flat topo | Not started | Non-negotiable — AR must never be the only way to identify a route |
Done means: you walk up to a crag you have never been to, hold up your phone, and know which line is which before you have taken your shoes off.
Phase 11 — 3D, gear, bolts and beta
Where phase 10 ends — a line on a flat image, projected — this begins: the rock as geometry, with things attached to it in three dimensions.
The sequence matters, because each one is a strictly harder annotation than the last:
- Sector geometry. Photogrammetry from contributed photos. A big crag does not photograph flat; Malham and Kilnsey misrepresent badly enough on a single image that people set off up the wrong route.
- Bolts and anchors in 3D. Where the clips are, how far apart, where the lower-off is. This is a safety feature before it is a convenience one — bolt spacing is what tells you whether the second clip is above a ledge.
- Gear placements. "Blue Camalot at the break." Trad protection notes are currently prose, and prose is a poor medium for where.
- Holds and beta. Sequences drawn onto the geometry, the bouldering case first, where the problems are short and the beta is most of the point.
The hard parts, stated plainly: capture quality from crowd-sourced photos, model size against an offline download budget, on-device rendering cost, and the fact that a hold annotation is only meaningful if the geometry is accurate to a few centimetres.
| Item | Status | Notes |
|---|---|---|
| Guided capture flow for photogrammetry | Not started | What makes 3D actually happen — it tells you when you have enough photos |
| Sector geometry pipeline and storage | Not started | Format, LOD tiers and download budget all need an ADR |
| Route lines drawn onto geometry, not just photos | Not started | RouteLine is keyed (routeId, photoId); (routeId, modelId) is additive |
| Bolt and anchor positions in 3D | Not started | Safety-critical: same never-auto-merge rule as phase 7 |
| Gear placement annotations | Not started | |
| Hold and beta sequences | Not started | Bouldering first |
| Models never auto-download | Not started | They would eat the phase 4 storage budget on their own |
Phase 12 — Integrations
A climber with fifteen years of ticks on UKC will not switch to an app that starts them at zero. Import is not a nice-to-have; it is the cost of entry.
| Item | Status | Notes |
|---|---|---|
externalRefs on crags and routes | Not started | Generic from day one — UKC, theCrag, 8a.nu, Mountain Project |
| Import a UKC logbook | Not started | Via the user's own data export, not scraping. Talk to UKC first |
| Route matching across databases | Not started | The genuinely hard part: same route, different name, different grade |
| Unmatched ticks kept as records, not dropped | Not started | A tick we cannot match is still that person's history |
| Export everything you have logged, any time | Not started | Ship this alongside import. Do not become the thing you are replacing |
| Push ticks back out | Not started | Needs partner cooperation; not something to build against a closed API |
| Health or Strava export of a session | Not started | Cheap once sessions exist |
Done means: a UKC regular can move across in an afternoon without losing anything, and could move away again just as easily.
What is deliberately not on here
- Training analytics. Hangboard protocols, load management, finger-strength tracking. Not what this app is, and the market is well served. Note the narrowing: training towards a named objective is a different thing and is now on the wishlist, because the objective is a route and we are the only ones who know what the route demands.
- Gym climbing. A different data model, a different update cadence, a different product.
- Android. Not never — but it needs a new ADR superseding ADR-0003, and doing it before the iOS app is genuinely good would make both worse.
- A web app. Nothing rules it out. The likely first case is a contributor tool — tracing sixty route lines is nicer with a mouse — rather than a consumer app.
The previous entry here, "no feed", has been reversed by ADR-0009 and is now phase 9.
Keeping this page honest
Per CLAUDE.md, shipping a roadmap
item means updating this table in the same PR. Do not delete a shipped row — flip it to
Shipped and link to the documentation that now describes it, so the page doubles as a record of what happened when.