Sports technology

A coach for the conversations, not the touches

Players get endless technical coaching and almost no help with the conversations that actually move a career. ProLine is an AI coach built only for footballers, answering in UK football's own language, calibrated to the player in front of it, and refusing to trade in false hope.

Sports technologyNext.js 15OpenAIStripe
ProReady shown across a laptop and two browser windows
About the product

The football conversation you cannot afford to get wrong

The founder had spent enough time inside non-league and academy football to notice something the coaching industry ignores. Players get endless technical coaching and almost no help with the conversations that actually move a career: how to ask a manager for feedback without it sounding like a complaint, when to push for a clause, what to say in the first week under a new manager. Generic AI assistants were worse than useless for this, answering football questions with motivational filler, in American vocabulary, with no memory of who the player was.

We built ProReady as a full product, not a chat wrapper. ProLine, the coaching interface, streams answers token by token while holding the last twenty messages of the thread plus a persistent player profile, position, club, level, goals and weaknesses, in the model's context on every request. Around it sits the machinery a subscription business needs: authentication with row-level security on all six tables, a three-tier subscription with a deliberately capped founder plan, a ten-message free allowance enforced server-side, and an admin command centre.

The piece the founder cares about most is the least visible. ProLine's entire personality is a versioned row in the database, editable from an admin screen, and it applies to the very next message with no deploy and no developer. The product's core intellectual property is a document its owner can edit on a Tuesday afternoon.

Industry
Sports technology and football player development
Platform
Responsive web application with a separate admin portal
Timeline
About ten weeks, October to December 2025
Team
One developer

What we did

  • Frontend development
  • Backend and API development
  • Database design
  • Authentication and RLS policy design
  • AI prompt engineering
  • Stripe billing integration
  • Admin tooling
  • Containerisation

Stack

Next.js 15React 19TypeScriptTailwind CSS 4SupabaseOpenAIStripeZodDocker
Goals

What the build had to achieve

Realistic, not motivational

The whole product hangs on refusing to be a cheerleader. The system prompt forbids false hope, guarantees and medical advice, and requires the model to acknowledge hard realities like limited playing time. Getting that tone right was a product decision before it was an engineering one.

Remember the player

Advice that ignores whether you are seventeen in an academy or twenty-four in a semi-pro league is worth nothing. Every request carries a persistent player profile and the last twenty messages of the thread, so ProLine answers the player in front of it rather than a generic footballer.

The owner controls the AI, not the developer

Prompt tuning is the highest-frequency change in a product like this. Rather than a constant in the codebase, the prompt is a versioned database record with draft, active and archived states, edited and test-run from the admin panel.

Earn trust with someone's career

Players type things into ProLine they would not say in a changing room. Access control is enforced in the database, not just the app: row-level security on every table, three roles, and a security migration that closed a policy allowing a signed-in player to write into another player's thread.

Inside the product

ProReady, screen by screen

A laptop showing the ProReady landing page on a near-black background, with a small Introducing ProReady pill above a two-line headline reading The Bridge Between Players, Managers, and Progress, with Managers and Progress picked out in blue. Beneath it, copy describing a personal football communication coach built to help handle manager talks, career decisions and pressure like a pro, above a white Start Free Trial button and an outlined Learn More button.
01

The promise in one line

A player arrives on a dark, deliberately unsentimental landing page. The register is the product's whole positioning: this is a communication coach for manager talks, career decisions and pressure, not a motivational app.

Two browser windows on proready.app. The first is headed Why Players Trust ProLine, with six cards covering real football experience, focus on realism not positivity, managing emotions, being tailored to each player, growing smarter with every conversation, and 24/7 availability, above a pull quote saying football is more than ability, it is timing, tone and mentality. The second is the pricing page with three tiers: Founder Access at 9.99 pounds a month badged 99 spots left and limited to the first 100 members, Pro Access at 24.99 pounds a month marked most popular, and Starter Access at 19.99 pounds a month, each listing what is included.
02

Realism over motivation, priced in three tiers

The positioning the whole product is built around: grounded advice rather than false hope. Alongside it, three plans including a Founder tier capped at the first hundred members, with the remaining spots counted live from the database.

A browser window at the ProReady registration page on a black background, showing a card headed Join ProReady with copy about unlocking ProLine's communication intelligence for ambitious footballers. It has fields for full name, email address and password, filled with a demo player's details, above a white button reading Join The Squad and a link for existing accounts to sign in.
03

Three fields and a squad number

Sign-up is name, email and password. A profile row is created automatically by a database trigger on the new auth user, so a player lands in the product with somewhere for their memory to live.

A laptop showing the ProReady dashboard with tiles for total threads, total messages, messages this month and tokens used, a subscription panel showing a Free plan with four of ten free messages consumed, and a conversation list including entries titled confidence has gone after two bad games, contract offer pushing for an appearance clause, trial at a National League club next week, and asking the gaffer why I am not starting. Two browser windows beside it show the player information record listing position as right winger, current club, age 21, goals, strengths and areas to improve.
04

The app remembers the player

Threads, messages and token usage at a glance, and beneath them a structured player record: position, club, age, goals, strengths and areas to improve. That record is injected into the system prompt on every single message, so advice is calibrated without the player restating their situation.

A browser window showing the ProReady subscription panel on a black background. It is headed Subscription with a Free plan badge and an Upgrade button, above a free messages meter reading four of ten with a blue progress bar and a line stating four messages remaining.
05

The allowance is always visible

Ten free messages, counted in the database and checked before any model call, so the limit cannot be bypassed from the browser. The remaining balance sits on the dashboard and above the chat input rather than appearing as a surprise.

A laptop showing a modal over the dimmed ProLine conversation, headed Free Messages Used with a padlock icon and the line you have used all your free messages. A meter reads messages used ten of ten. Beneath, an upgrade to continue list covering unlimited conversations with ProLine, the personalised player memory system, professional career guidance and feedback, and cancel anytime with no commitment, above a blue View Pricing Plans button and a Maybe Later option.
06

The upgrade moment, mid-conversation

The server refuses the eleventh message with an HTTP 402 and the usage payload, and the app turns that refusal into an offer inside the conversation the player was already having, rather than bouncing them to a pricing page.

Challenges

The parts that were genuinely hard

01

Answers that appeared on screen and then vanished

The problem

A reply would stream beautifully into the chat, and then be gone when the player reopened the thread the next day. Nothing in the client was wrong, and the failure was invisible in development, where the process stays alive.

What we did

The route was sending its terminal done event and closing the stream before persisting the assistant message. On a serverless platform, closing the response is a signal the function may be reclaimed, so the write that followed sometimes never ran and left no error, because the process was already gone. We reordered the stream lifecycle so the database write completes first and the stream closes last, and added explicit error capture on both the primary write and the truncation-retry write, which had been failing silently.

The outcome

Conversation history became reliable, and the class of bug that produces no logs was removed rather than patched.

02

Coaching advice that stopped mid-sentence

The problem

ProLine would give three excellent steps and cut off during the fourth. Raising the token ceiling alone is a cost decision, not a fix: a longer limit still truncates eventually, and the product had no way to even detect that it had happened.

What we did

We raised the output ceiling, turned on the provider's usage reporting so real token counts land in the database, and taught the route to read the finish reason. When it indicates a length cut-off, the route fires a second, short, non-streaming completion asking the model to finish concisely, merges the continuation, and records the truncation, the retry count and the continuation tokens on the message row. The system prompt was rewritten at the same time to require closure.

The outcome

Truncation stopped being a silent quality failure and became a measurable, self-healing event.

03

Live payments succeeded and subscriptions did not activate

The problem

Real customers paid, the payment provider reported success, and their accounts stayed unsubscribed. Two faults compounded. A billing-mode change had moved the period end off the subscription root and onto the subscription item, so the webhook was writing an invalid date. Worse, the handler logged its failures and returned HTTP 200, which tells the provider the event was accepted, so it never retried. Every failure destroyed its own evidence and its own recovery path.

What we did

We read the period end from the root with a fallback to the first subscription item, and changed the handler to throw on missing metadata or a failed database write so the provider's retry machinery does its job. Founder-badge assignment moved into the subscription lifecycle handler so it survives a checkout event arriving out of order.

The outcome

Failed webhook deliveries became visible and self-retrying instead of silent. Both fixes shipped the same day the problem was reported on live payments.

04

A security policy that let players write into each other's threads

The problem

The first cut of the message-insert policy checked only that the row's user id matched the signed-in user. It never checked that the thread belonged to them. The application never sends a mismatched thread id, so the hole was invisible from the UI and from any end-to-end test. It only exists at the database boundary, which is exactly where an authenticated attacker operates.

What we did

We wrote a dedicated security migration replacing the policy with one that also requires the target thread to be owned by the caller, added a unique index on the subscriptions table to kill the double-click checkout race, and added covering indexes for the admin and usage queries.

The outcome

Authorisation for the most sensitive table in the product is enforced by Postgres, not by the correctness of the client. In a product where players describe conflicts with their manager, that distinction is the whole trust proposition.

05

A coach with no memory

The problem

Early on, every message was answered in isolation. A player explained their situation, got good advice, asked a follow-up, and was answered as a stranger. Naively replaying an entire thread is both expensive and unbounded, and a football coach needs two different kinds of memory: what was said in this conversation, and what is permanently true about this player.

What we did

We separated them. The route loads the last twenty messages of the thread for conversational context, and a persistent player-memory document from the profile for identity, position, level, club, goals and weaknesses, injecting both into the system prompt on every request. Per-message input and output token counts are recorded so the cost of that context is measurable rather than assumed.

The outcome

Follow-up questions work the way a player expects, and the context window stays bounded and priced.

Approach

How the work ran

  1. 01

    Discovery and research

    The engagement started from a written specification and a set of client change requests rather than a blank page. The product documentation, database schema and API design were committed before any feature code: the very first commit is the project documentation and frontend spec.

  2. 02

    UI and UX

    A working UI prototype was built and reviewed with the client before the backend existed, then revised against their feedback in two rounds. A dark, high-contrast interface was chosen to match the product's register, professional and unsentimental rather than bright and motivational, and a separate mobile responsiveness plan was written and worked through.

  3. 03

    Development and testing

    Backend integration landed in vertical slices: authentication, then streaming chat, then billing, then the admin panel, with every route handler validating its input through a schema and returning centralised error shapes. Testing was manual and checklist-driven rather than automated, with a written QA checklist and an API smoke script.

  4. 04

    Deployment and support

    The app is built for containerised deployment, with standalone output, a multi-stage Dockerfile and a compose file, and shipped with written runbooks for database configuration, live-mode billing setup and webhook configuration. Support continued after launch against real payment traffic: the two webhook fixes above were written and shipped on the day the problem appeared, and a framework security patch was applied two days before.

Features

What shipped

Streaming football coaching

ProLine answers over Server-Sent Events, so text appears as the model produces it instead of after a five-second pause. The client applies optimistic updates, parses the stream incrementally, and can abort a request in flight.

Player memory

A structured profile, position, current club, age, goals, strengths and areas to improve, is stored per player and injected into the system prompt on every message, so advice is calibrated to an academy teenager or a semi-pro in their twenties without the player restating it.

Ten free messages, enforced server-side

The allowance is counted in the database and checked before any model call, so it cannot be bypassed from the client. When it runs out the API returns HTTP 402 with the usage payload, and the app turns that into an upgrade prompt inside the conversation the player was already having.

Three-tier billing with a capped founder programme

Starter, Pro and a Founder plan limited to the first hundred members, with remaining spots counted live from the database and a waitlist page for the overflow. Subscription state is written by signature-verified webhooks and reconciled through a sync endpoint.

Owner-editable AI prompt with a test harness

The active system prompt is a versioned database row. A super-admin can edit it, run it against a synthetic player profile before publishing, and switch the model, and the change applies to the next message with no deploy.

Admin command centre

Five server-paginated views over users, conversations, subscriptions, platform analytics and prompts, each re-checking the caller's role on the server, with an audit-log table behind them.

Results

Measured, not estimated

143 kB

First load on the heaviest route

The full ProLine chat workspace, with streaming, history and the brief rail, over 142 kB of shared JavaScript across the product.

87 / 100

Lighthouse performance

On the landing page, with 93 accessibility, 96 best practices and 100 SEO, first paint in 0.8 seconds and effectively no layout shift. Measured by us against a local production build under default mobile throttling, so it is our own measurement rather than field data.

2.09 s

Average AI response latency

Measured by the product itself: every assistant message records its own latency and the admin analytics panel averages them. This figure comes from the development database, so it is an engineering measurement rather than a production service level.

Build the product your users cannot get anywhere else

From a written spec to live subscription payments in ten weeks: authentication, streaming AI, billing and an admin panel your team can actually run.

Have a Project To Discuss?

Contact Us