A first version can have few features and still take a lot of work. That is not necessarily a problem. What matters most is choosing what someone will actually be able to accomplish with it.

“An app for coaches” gives you a direction. “A coach prepares a session and their athlete finds it on their phone” gives you a journey to build.

Start with the journey

Take that second example. The coach needs to create a session, assign it to the right person and know it is available. The athlete needs to be able to view it. You have to consider both sides of the exchange.

A beautiful creation page is not enough if nobody can find the session afterwards. On the other hand, that journey can already be useful without messaging, advanced statistics or a programme library.

What can someone complete from start to finish with this version?

That is the question I would keep visible throughout development. It lets you discuss scope through a concrete example instead of a list of modules.

Choose what can wait

For each addition, I ask whether it is needed for the chosen journey. A notification may matter if the athlete would otherwise not know a session is waiting. A detailed dashboard can wait if there is no data yet.

The answer depends on the context. A secondary feature in one product can be essential in another. I prefer to write down what we are postponing and why, rather than let it disappear in a conversation.

Handle the everyday cases

For a session, we can write a read permission rule small enough to discuss. The coach sees their draft. The assigned athlete sees the published session. Other accounts cannot access it.

session-access.ts
type Session = {
  coachId: string;
  athleteId: string;
  published: boolean;
};

// authenticatedId doit venir de la session vérifiée côté serveur.
export function canReadSession(
  session: Session,
  authenticatedId: string | null,
) {
  if (!authenticatedId) return false;
  if (session.coachId === authenticatedId) return true;
  return session.published && session.athleteId === authenticatedId;
}
A rule to call on the server before returning the session

This function does not replace authentication. The ID must come from a verified server session, never a field sent by the browser. The database query must respect these permissions too. This rule assumes one coach and one athlete per session. A team setup would need other explicit rules.

An account that has not created anything yet, a dropped connection, a form submitted twice. These are normal situations. A small version should explain what happens in those moments too.

Reducing scope does not remove the need to protect data, check access or make actions understandable. These are part of the journey. They do not matter any less because the product is new.

Observe before adding

Once the journey works, put it in the hands of a few people who need it. Watching where they hesitate often gives you a more precise question than “what feature should we add?”

Maybe a step is missing. Maybe a word is wrong. Maybe the original problem was not the one that mattered most. A first version also helps you discover that before building the rest.