Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ Anything describing the mock interview has to match the client (`../client`), wh
- Setup is seniority (junior/mid/senior/staff), difficulty (easy/standard/hard) and 3/5/8/12 questions. The role is **not** collected: it comes from the account's job context, and the same profile drives the questions and the scoring
- The interviewer speaks its questions, gates the microphone while it does, and can follow up **twice** on one question. A language with no voice makes it write them instead
- The session ends in a scored report: overall score, strengths, gaps, then per-question score, justification and a stronger answer, exportable as DOCX or Markdown
- Pricing is per unit of work, not per minute: 20 credits a question, 10 a follow-up, 40 for the report, and its transcription is unmetered (`app/cfg/payment.py` in `../backend`). Quote both halves whenever the site talks about credits, or the copy implies a mock session is metered by the clock
- Pricing is per minute, the same as a live session: 10 credits a minute from the first question to the report (`CREDITS_PER_MINUTE` in `../backend/app/cfg/payment.py`). Any session needs a minute of credit to start and stops when the credits run out; a mock still delivers its report. It used to be priced per question, follow-up and report - copy that says so is stale

`CREDIT_RATES` in `src/lib/plans.ts` mirrors those rates for the components (the pricing section's metering note reads it, alongside the credit packs it already mirrored from the same backend file). Markdown can't import it, so `src/content/docs/mock-interview.md` restates the numbers and `src/config/faq.ts` restates them again for the JSON-LD; a rate change is those three places plus the backend.
`CREDIT_RATES` in `src/lib/plans.ts` mirrors that rate for the components (the pricing section's metering note reads it, alongside the credit packs it already mirrored from the same backend file), and `mockSessionMinutes` mirrors the desktop app's length estimate. Markdown can't import either, so `src/content/docs/mock-interview.md` restates the numbers in its cost table and the FAQ answers restate them as text (`src/config/faq.ts` reads those for the JSON-LD); a rate change is those places plus the backend.

### The language list is data, not copy

Expand Down
29 changes: 15 additions & 14 deletions src/components/sections/PricingSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { LocalizedLink } from '@/i18n/LocalizedLink';
import type { Locale } from '@/i18n/config';
import { format, pluralize } from '@/i18n/format';
import { getMessages } from '@/i18n/messages';
import { CREDIT_RATES, mockSessionPrice } from '@/lib/plans';
import { CREDIT_RATES, mockSessionMinutes } from '@/lib/plans';

import { PricingCards } from './PricingCards';

Expand All @@ -28,19 +28,21 @@ const TierValueCell: React.FC<{ value: TierValue; included: string }> = ({ value
);

/**
* How the two kinds of session are metered.
* What each kind of session spends.
*
* The heading above quotes the per-minute rate, which is the whole story for a
* live interview and none of it for a mock one: that is charged per question,
* per follow-up and once for the report, and its transcription isn't metered
* at all. Rates come from CREDIT_RATES so this and the mock interview page
* can't quote different numbers at each other.
* Both are metered by the minute at the same rate, but a reader comparing
* them wants to see what a typical session of each comes to, and that a
* session stops when the credits run out. Rates come from CREDIT_RATES so
* this and the mock interview page can't quote different numbers at each
* other.
*/
const MeteringNote: React.FC<{ locale: Locale }> = ({ locale }) => {
const { pricing } = getMessages(locale);
const t = pricing.metering;
// Each amount carries its own noun: "1 кредит", "10 кредитов", "40 кредитов".
const credits = (n: number) => `${n} ${pluralize(locale, n, pricing.creditNoun)}`;
const minutes = (n: number) => `${n} ${pluralize(locale, n, pricing.minuteNoun)}`;
const mockMinutes = mockSessionMinutes(8);

return (
<Reveal className="mx-auto mt-6 max-w-3xl">
Expand All @@ -51,8 +53,8 @@ const MeteringNote: React.FC<{ locale: Locale }> = ({ locale }) => {
<dt className="text-sm font-medium text-foreground">{t.live}</dt>
<dd className="mt-1 text-sm leading-relaxed text-muted-foreground">
{format(t.liveText, {
rate: credits(CREDIT_RATES.livePerMinute),
thirty: credits(CREDIT_RATES.livePerMinute * 30),
rate: credits(CREDIT_RATES.perMinute),
thirty: credits(CREDIT_RATES.perMinute * 30),
})}
</dd>
</div>
Expand All @@ -68,10 +70,9 @@ const MeteringNote: React.FC<{ locale: Locale }> = ({ locale }) => {
</dt>
<dd className="mt-1 text-sm leading-relaxed text-muted-foreground">
{format(t.mockText, {
question: credits(CREDIT_RATES.mockPerQuestion),
followUp: credits(CREDIT_RATES.mockPerFollowUp),
report: credits(CREDIT_RATES.mockPerReport),
session: credits(mockSessionPrice(8)),
rate: credits(CREDIT_RATES.perMinute),
minutes: minutes(mockMinutes),
session: credits(CREDIT_RATES.perMinute * mockMinutes),
})}
</dd>
</div>
Expand Down Expand Up @@ -117,7 +118,7 @@ export const PricingSection = ({ locale, standalone = false }: PricingSectionPro
{ label: tier.rateLimit.label, trial: tier.rateLimit.trial, paid: tier.rateLimit.paid },
];

const rate = CREDIT_RATES.livePerMinute;
const rate = CREDIT_RATES.perMinute;

return (
<Section id={SECTIONS.pricing} aria-labelledby="pricing-heading">
Expand Down
2 changes: 1 addition & 1 deletion src/content/docs/how-it-works.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,4 @@ Session transcript/suggestion content is retained in memory for the active app s

Credits are consumed while AI-assisted features are active (including transcription and suggestion generation). Credit balance is refreshed periodically during a running session and updates after successful payments.

A mock interview is metered differently, because its wall clock is a poor measure of the work delivered: it is charged per question, per follow-up and once for the report, and its transcription is not metered at all. The client quotes the price before the session begins and the balance is checked against it up front, so a session that starts can reach its report.
A mock interview is metered the same way, at the same rate, from its first question to its report. Any session needs at least a minute of credit to start, the app warns at five minutes and at one minute left, and a session stops when the balance reaches zero - a mock interview still delivers its report.
2 changes: 1 addition & 1 deletion src/content/docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ The model is provided for you - there is nothing to connect or configure. New ac
### Credits & Payments

- Credits are consumed while the assistant is running (AI suggestions and transcription)
- A mock interview is priced per question, follow-up and report instead of by the minute, so think-time is free
- A mock interview is billed by the minute at the same rate, and any session stops when your credits run out
- Credit balance is displayed live inside the app
- Buy credits directly from the **Buy Credits** page within the app, with payment history and status tracking

Expand Down
2 changes: 1 addition & 1 deletion src/content/docs/live-interview.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ The **Clear** button removes all transcripts, reply suggestions, and code sugges

Credits are consumed while the assistant is running - covering AI reply suggestions and transcription. Your remaining credit balance is shown live in the titlebar, and in the status bar while in stealth mode.

A [mock interview](/docs/mock-interview) is charged differently: per question, follow-up and report rather than by the minute, with its transcription unmetered. The price of a session is quoted in its setup dialog before it starts.
A session needs at least a minute of credit to start. The app warns you when about five minutes and one minute are left, and when your credits run out the session stops and offers to save the transcript. A [mock interview](/docs/mock-interview) is billed the same way, at the same rate.

To buy credits:

Expand Down
22 changes: 11 additions & 11 deletions src/content/docs/mock-interview.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ This is the half of the app to reach for first: you can run a session tonight, w
| Profile / CV | **Account** | Questions and scoring are both grounded in it. |
| Job context | **Account** | Stands in for the role, which the setup dialog no longer asks for. |
| Microphone | **Configuration** | Your answers are transcribed from it. |
| Credits | Bought in the app | A session is priced per question - see [What a Session Costs](#what-a-session-costs). |
| Credits | Bought in the app | Billed by the minute - see [What a Session Costs](#what-a-session-costs). |

If your name or profile is missing, the app says so and sends you to **Account** rather than starting a session you would have to abandon.

Expand All @@ -32,7 +32,7 @@ Choose **Mock interview** on the home screen. The setup dialog asks for three th
| -------------- | -------------------------------- | -------------------------------------------------------------------------------------- |
| **Seniority** | Junior, Mid, Senior, Staff | Sets how deep the questions go and how much the answers are expected to carry. |
| **Difficulty** | Easy, Standard, Hard | Independent of seniority - a hard junior interview is a real thing. |
| **Questions** | 3, 5, 8 or 12 | The price of each length is shown beside it; a length your balance cannot cover is disabled. |
| **Questions** | 3, 5, 8 or 12 | Each length shows roughly how long it runs; the dialog says how far your balance goes. |

The interview language is the same setting the live assistant uses, edited in the same place - change it here and the live assistant follows, and the other way round.

Expand Down Expand Up @@ -82,18 +82,18 @@ From the report you can **practice again** with the same setup, or finish and re

## What a Session Costs

A live interview is metered by the minute. A mock interview is priced by the work delivered instead, because a large part of its wall clock is the interviewer generating a question, speaking it, scoring the turn and writing the report - none of which you can act during - and most of the rest is your think-time, which is the behaviour the feature exists to train.
A mock interview is billed like a live one: **10 credits a minute**, from the first question to the report.

| Unit | Credits |
| --------------------------- | ------- |
| Question | 20 |
| Follow-up | 10 |
| Report | 40 |
| Transcription, for the whole session | 0 |
| Length | Usually runs | Roughly costs |
| ------------ | ------------ | ------------- |
| 3 questions | 8 minutes | 80 credits |
| 5 questions | 13 minutes | 130 credits |
| 8 questions | 20 minutes | 200 credits |
| 12 questions | 30 minutes | 300 credits |

So a 5-question session costs **140 credits** before follow-ups and at most 240 if every question draws both of them; an 8-question session is **200** and at most 360.
These are estimates: the session is billed for the time it actually takes, so long answers and follow-ups make it longer. The setup dialog shows the estimate and how many minutes your balance covers.

The app quotes the guaranteed price in the setup dialog and checks your balance against it before the first question, so a session that starts is a session that reaches its report. Follow-ups are charged as they are delivered, and are quietly declined rather than allowed to eat into what the report needs.
You need at least a minute of credit to start. The app warns you when about five minutes and one minute are left, and if your credits run out mid-interview the session ends there, keeps the answer you were giving, and still produces your report.

Your 1-hour free trial is 600 credits, which covers a couple of full sessions.

Expand Down
4 changes: 2 additions & 2 deletions src/i18n/messages/en/faq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ export const faq = {
question: 'What does a mock interview cost?',
category: 'billing',
answer:
'A mock interview is priced per question rather than per minute, so thinking about your answer is free. Each question costs 20 credits, each follow-up 10, and the report at the end 40; the transcription that runs throughout is not metered at all. A 5-question session is therefore 140 credits before follow-ups and an 8-question session 200, and the app quotes the price and checks your balance before the interview starts. Your 1-hour free trial is 600 credits, which covers a couple of full sessions.',
'The same as the live assistant: 10 credits a minute, from the first question to the report. A 5-question session usually runs about 13 minutes (about 130 credits) and an 8-question one about 20 (about 200), and the app shows that estimate and how far your balance goes before you start. You need at least a minute of credit to begin, and if your credits run out mid-interview it ends there and you still get your report. Your 1-hour free trial is 600 credits, which covers a couple of full sessions.',
},
{
question: 'How do credits work?',
category: 'billing',
answer:
'A live session is metered by the clock: 10 credits per minute of reply suggestions, code analysis and transcription, so a 30-minute interview costs roughly 300 credits. A mock interview is priced by the work delivered instead - see the question above. You can purchase credit packs starting from 600 credits ($5 for ~60 minutes) up to 30,000 credits ($175 for ~3,000 minutes).',
'Every session is metered by the clock at 10 credits per minute, live or mock, so a 30-minute interview costs roughly 300 credits. A session needs at least a minute of credit to start, the app warns you at five minutes and at one minute left, and it stops when your credits run out. You can purchase credit packs starting from 600 credits ($5 for ~60 minutes) up to 30,000 credits ($175 for ~3,000 minutes).',
},
{
question: 'What payment methods do you accept?',
Expand Down
4 changes: 2 additions & 2 deletions src/i18n/messages/en/mockInterview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ export const mockInterview = {
body: 'One setting covers the live assistant and the mock alike. {voices} of them the interviewer speaks aloud; where a language has no voice available it writes its questions instead, and the follow-ups and the scoring are unchanged.',
},
pricing: {
title: 'Priced by the question, not the clock',
body: 'Think-time is free. You pay for each question, each follow-up and the final report; the transcription that runs the whole way through is not metered at all.',
title: 'Priced by the minute, like the live assistant',
body: 'One rate for both: 10 credits a minute from the first question to the report. If your credits run out, the interview ends there and you still get your report.',
},
report: {
title: 'The report leaves with you',
Expand Down
4 changes: 2 additions & 2 deletions src/i18n/messages/en/pricing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ export const pricing = {
title: 'What a session spends',
live: 'Live interview',
liveText:
'{rate} a minute while the assistant is running, so a 30-minute call is about {thirty}.',
'{rate} a minute while the assistant is running, so a 30-minute call is about {thirty}. It stops when your credits run out.',
mock: 'Mock interview',
mockText:
'{question} a question, {followUp} a follow-up and {report} for the report, with the transcription unmetered - so an 8-question session is {session} before follow-ups, and thinking time is free.',
'{rate} a minute from the first question to the report, so an 8-question session of about {minutes} costs about {session}. If your credits run out, it ends and you still get your report.',
},

plans: {
Expand Down
4 changes: 2 additions & 2 deletions src/i18n/messages/ru/faq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ export const faq: Faq = {
question: 'Сколько стоит пробное собеседование?',
category: 'billing',
answer:
'Пробное собеседование оплачивается за вопрос, а не за минуту, поэтому время на обдумывание ответа бесплатно. Каждый вопрос стоит 20 кредитов, каждый уточняющий вопрос - 10, а итоговый отчёт - 40; расшифровка, которая идёт всё время, вообще не тарифицируется. Таким образом, сессия из 5 вопросов - это 140 кредитов без учёта уточняющих вопросов, а из 8 вопросов - 200, причём приложение называет цену и проверяет баланс до начала собеседования. Ваш бесплатный пробный час - это 600 кредитов, чего хватает на пару полных сессий.',
'Так же, как живой помощник: 10 кредитов в минуту от первого вопроса до отчёта. Сессия из 5 вопросов обычно длится около 13 минут (примерно 130 кредитов), а из 8 вопросов - около 20 (примерно 200), и приложение показывает эту оценку и то, на сколько хватит баланса, ещё до начала. Чтобы начать, нужна хотя бы минута кредитов, а если кредиты закончатся посреди собеседования, оно на этом завершится, и отчёт вы всё равно получите. Ваш бесплатный пробный час - это 600 кредитов, чего хватает на пару полных сессий.',
},
{
question: 'Как работают кредиты?',
category: 'billing',
answer:
'Живая сессия тарифицируется по времени: 10 кредитов в минуту за подсказки для ответов, анализ кода и расшифровку, так что 30-минутное собеседование стоит примерно 300 кредитов. Пробное собеседование оплачивается по объёму выполненной работы - см. вопрос выше. Можно купить пакеты кредитов: от 600 кредитов (5 $ примерно за 60 минут) до 30 000 кредитов (175 $ примерно за 3000 минут).',
'Любая сессия, живая или пробная, тарифицируется по времени - 10 кредитов в минуту, так что 30-минутное собеседование стоит примерно 300 кредитов. Чтобы начать, нужна хотя бы минута кредитов, приложение предупреждает, когда остаётся пять минут и одна минута, а когда кредиты заканчиваются, сессия останавливается. Можно купить пакеты кредитов: от 600 кредитов (5 $ примерно за 60 минут) до 30 000 кредитов (175 $ примерно за 3000 минут).',
},
{
question: 'Какие способы оплаты вы принимаете?',
Expand Down
Loading