# Account and Plans (/en/docs/account-and-plans)
Translation does not need an account. Install the extension, pick a provider, and read — nothing on this page is required for that.
An account exists for the parts that have to live on a server: your [Notebase](/docs/notebase), your review schedule, your statistics, and anything an assistant reaches over [MCP](/docs/mcp).
## What an account adds [#what-an-account-adds]
| | Without an account | Signed in |
| ----------------------------------------------- | --------------------- | ---------------------- |
| Page, selection, input and subtitle translation | Yes | Yes |
| Your own API keys | Yes | Yes |
| Glossary, custom prompts, custom CSS | Yes | Yes |
| Built-in AI, for Custom AI Actions | Small daily allowance | Larger daily allowance |
| Notebase, card templates, review, statistics | No | Yes |
| AI subtitles, for videos without captions | No | Pro and Ultra only |
| MCP | No | Ultra only |
Everything in the first three rows is stored in your browser profile, which is why it works signed out — and why it does not follow you to another computer unless you sync it yourself. See [Configuration, Sync & Backups](/docs/config-backup).
## The built-in AI allowance [#the-built-in-ai-allowance]
Read Frog ships two providers of its own — **Built-in AI** and **Advanced Built-in AI**, the second using a stronger model. Both draw on an allowance rather than an API key of yours.
**Below Ultra, that allowance funds Custom AI Actions and nothing else.** Page translation, selection translation, note suggestions, video subtitle translation (including AI smart segmentation and the video summary), input translation and language detection are all deliberately unfunded on the free and Pro tiers — Read Frog reports them as needing an upgrade rather than as being out of quota. Ultra funds every one of them from a single weekly pool.
| | Custom AI Actions | Everything else |
| --------------- | -------------------------------------------- | ---------------- |
| Not signed in | Small daily allowance, keyed to your network | Not funded |
| Signed in, free | Larger daily allowance | Not funded |
| Pro | Larger daily allowance again | Not funded |
| Ultra | One weekly pool | Same weekly pool |
So on any plan below Ultra, **whole-page translation runs on a provider of your own**, which is the normal way to use Read Frog: Google Translate and Microsoft Translator need no key at all, and an LLM provider needs yours. Assigning your own provider to a feature in [API Providers](/docs/providers/overview) stops it drawing on the allowance entirely — **your own API key has no Read Frog limit**, only whatever your provider charges you.
The **AI subtitles quota** that comes with Pro and Ultra is a separate thing and is not part of the table above. It is a monthly allowance of transcription minutes that generates subtitles from speech for videos that have none, and it never draws on the built-in AI allowance; see [AI Segmentation & Quota](/docs/video-subtitles/ai-segmentation#ai-subtitles-quota). Translating those subtitles into your language follows the table above: below Ultra, it runs on a provider of your own.
Daily allowances reset each UTC day. The Ultra pool is a rolling week anchored to your subscription rather than a calendar week, so a heavy reading day is not capped by that day alone. Because it is one pool, video subtitle translation — by far the most expensive feature per minute of use — shares it with everything else. AI subtitle transcription minutes are counted separately and never come out of this pool.
## What the paid plans unlock [#what-the-paid-plans-unlock]
Current prices are on the [pricing page](https://readfrog.app/pricing); they are not repeated here so this page cannot go stale. What the tiers change:
* **Pro** raises the Custom AI Actions allowance and adds a monthly allowance of AI subtitle transcription minutes (see [AI Segmentation & Quota](/docs/video-subtitles/ai-segmentation#ai-subtitles-quota)). Page translation, subtitle translation and the other features still run on a provider of your own.
* **Ultra** is the only plan whose built-in AI allowance funds anything beyond Custom AI Actions, and it comes with more transcription minutes than Pro. It is also the only one that can connect an AI assistant over [MCP](/docs/mcp). That restriction is enforced on the server, so an assistant on a lower plan is refused at connection time rather than failing later.
## Signing in [#signing-in]
Sign in from the extension popup or at [readfrog.app](https://readfrog.app); it is the same account either way, and the extension picks up the session from the website. If the popup still shows **Guest** after signing in on the website, reload the page you are on — the extension reads the session when a tab loads.
## Deleting your account [#deleting-your-account]
Account deletion is available from the account settings on the website and removes your notes, cards and review history. It is not reversible, and it does not uninstall the extension or clear the settings stored in your browser profile — do that from the browser's extensions page.
# Configuration, Sync & Backups (/en/docs/config-backup)
Open **Options → Config** to move or recover settings. Interface language is configured separately under **Options → General**.
## Export safely [#export-safely]
The export dialog lets you include or exclude provider API keys. Exclude keys for normal backups, bug reports, shared files, and version control. Include them only when moving your own configuration through storage you trust.
If only one side changed, Read Frog can use the newer copy. If both local and remote values changed, the conflict dialog lets you choose local or remote values per field, or select all local/all remote before confirming.
Validate the merged configuration in the dialog before applying it. Manual sync avoids silent background overwrites, but it also means changes do not appear on another device until you start sync there.
## Automatic and manual backups [#automatic-and-manual-backups]
Read Frog checks for changed configuration about every 60 minutes and creates an automatic backup only when something changed. It keeps up to eight backups. You can also:
* create a manual backup before an experiment;
* restore a selected backup;
* export a backup to a file;
* delete backups you no longer need.
Backups are local to the browser profile unless you export or sync them. Before editing large Site Rules or prompt sets, make a manual backup with a recognizable timestamp.
## Interface language [#interface-language]
**Options → General → Interface Language** controls the Read Frog UI independently from the browser's display language. Changing it does not change translation source/target languages or website language detection.
## Beta Experience and reset [#beta-experience-and-reset]
Beta Experience enables experimental features that explicitly depend on it. Text to Speech is labeled Public Beta but no longer requires this switch.
Reset restores the default configuration. It is appropriate when a migrated or heavily edited setup cannot be repaired, but it removes customized providers, prompts, rules, and tool choices. Export without keys for support, and create a secure backup if you need credentials, before resetting.
## Recovery sequence [#recovery-sequence]
When a configuration change causes a problem:
1. export the current state without API keys for inspection;
2. restore the most recent known-good local backup;
3. if necessary, import a trusted export;
4. reconnect Google Drive and resolve conflicts deliberately;
5. use Reset only after the earlier recovery paths fail.
This order preserves the most evidence and gives you the easiest route back.
# Contribution Guide (/en/docs/contributing)
## Getting Started [#getting-started]
### Step 1: Fork the repository and clone it to your local machine [#step-1-fork-the-repository-and-clone-it-to-your-local-machine]
```bash
# Clone the repository from your fork
git clone https://github.com/xxxxx/read-frog.git
# Enter the project directory
cd read-frog
# Add the upstream remote to sync with the original repository
git remote add upstream https://github.com/mengxi-ream/read-frog.git
```
### Step 2: Install dependencies and start development [#step-2-install-dependencies-and-start-development]
```bash
# Install dependencies
pnpm i
# Start the development server
pnpm dev
```
This will start the extension development environment. The extension will automatically open in your default browser.
## Development Tips [#development-tips]
### Using npx with pnpm Node.js Management [#using-npx-with-pnpm-nodejs-management]
We're using pnpm's built-in Node.js version management (introduced in pnpm 10.14). You may encounter `EBADDEVENGINES` errors when running `npx` commands. There are two solutions:
**Solution 1: Use `pnpm dlx` or `pnpx` instead of `npx`**
```bash
# Instead of npx
npx some-package@latest
# Use pnpm dlx
pnpm dlx some-package@latest
# Or use pnpx (alias for pnpm dlx)
pnpx some-package@latest
```
**Solution 2: Align Node.js version with pnpm**
When it's not convenient to replace `npx` (e.g., for user-scoped MCP installations in Claude Code), align your Node.js version:
```bash
# Install and use the required Node.js version globally
pnpm env use --global 22.18.0
```
### Open the extension in the specific browser [#open-the-extension-in-the-specific-browser]
You can create/modify the `web-ext.config.ts` file in the root directory to explicitly specify the browser path.
```javascript
// web-ext.config.ts
import { defineWebExtConfig } from "wxt";
export default defineWebExtConfig({
binaries: {
chrome: "path/to/your/chrome.exe",
firefox: "path/to/your/firefox.exe",
edge: "path/to/your/edge.exe",
},
});
```
### pnpm dev can't load the extension automatically [#pnpm-dev-cant-load-the-extension-automatically]
If you use Chrome version 137 or higher, you need to download [Chrome for Testing](https://developer.chrome.com/blog/chrome-for-testing/) for development. See [details](https://wxt.dev/guide/essentials/config/browser-startup.html).
### Persistent Chrome Profile [#persistent-chrome-profile]
**By default, web-ext creates a new profile every time you run the dev script.**
If you want to keep logins, devtools extensions, and browser settings between development sessions, create or update `web-ext.config.ts` in the project root.
The persistent profile configuration is slightly different across operating systems:
### macOS: Too Many Open Files Error (EMFILE) [#macos-too-many-open-files-error-emfile]
If you encounter this error on macOS when running `pnpm dev`:
This happens because Chokidar (the file watching library used by Vite/WXT) defaults to using macOS's native FSEvents, which requires a file descriptor for each watched file/directory. Large projects can exceed the system limit.
**Solution:** Set `CHOKIDAR_USEPOLLING=true` to switch to polling mode, which doesn't require file descriptors.
Create or update the `.env` file in the project root:
```bash
# .env
CHOKIDAR_USEPOLLING=true
```
After this, `pnpm dev` will work without the EMFILE error.
**Note:** Polling mode is slightly slower and uses more CPU, but it avoids the file descriptor limit issue.
## Submitting Code [#submitting-code]
### Create a new branch [#create-a-new-branch]
```bash
# For new features
git checkout -b feat/the-feature
# For bug fixes
git checkout -b fix/the-bug
# For docs modify
git checkout -b docs/the-docs
```
### Merge Branch [#merge-branch]
If the remote main branch gets updated and creates conflicts in our PR, you can resolve it by merging the remote branch in advance
.
```bash
# Switch to the main branch
git checkout main
# Pull the latest code from upstream
git pull upstream main
# Switch back to your local branch
git checkout docs/xxxx
# Merge the main branch into your local branch
git rebase main
# Push the code again if there are conflicts after rebase
git push --force-with-lease origin docs/xxxx
# If there are no conflicts, push the code again
git push origin docs/xxxx
```
| What you see | What it means |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| **Bold** words | The core of the main clause. Everything else adds detail |
| Blue words, wavy line | A predicate: the whole verb group, such as *has been meeting* |
| Other lines under words | The role of a phrase: subject, object, complement or adverbial. The key under the sentence shows which line is which |
| A shaded box with a label | A clause. The label says what it does: a relative clause, an object clause, a condition clause… |
| A circled word | The word that opens a clause, such as *which*, *that* or *if* |
| A red star with a small label | Something that tends to trip readers up: a passive, an inversion, a missing word… |
Hover over or tap any part to see what it is and which word it belongs to. The rest of the sentence fades while you look. The speaker button reads the sentence aloud.
Two switches show the same sentence in two more ways:
| Switch | What you see |
| ------------ | --------------------------------------------------------------------------------------- |
| **Skeleton** | Every clause folds into its label and every modifier into "…". Only the bones are left |
| **Breaks** | The slashes a teacher would pencil in, so you can read the sentence one chunk at a time |
## Dictionary [#dictionary]
Select a word or a short phrase and click **Dictionary**.
The card shows the word in its base form with its pronunciation, part of speech and CEFR level, then one definition: the one that fits the page. Below it is the sentence where you found the word, with the word in bold, and the sentence's translation. The speaker buttons read the word and the sentence aloud.
Its output fields are **Term**, **Phonetic**, **Part of Speech**, **Sentence**, **Term in Sentence**, **Definition**, **Sentence Translation** and **Difficulty**. **Term in Sentence** tells the card which words to bold.
1. Open an action you created, click **Configure with AI** next to its name, then click **Copy prompt**.
2. Paste the prompt into ChatGPT, Claude, DeepSeek, Kimi or any other AI chat.
3. Say what you want, such as "An idiom card: pinyin, literal meaning, meaning and story". The assistant asks what it needs to know, then gives you each setting, ready to paste.
4. Paste each setting into the editor, and check the card in the layout preview.
The prompt includes the action's current settings, so you can also ask for changes to an action you already have: "Make it look like character tiles", "Hide the meaning until I click". It never includes your API keys.
## Prompt Tokens [#prompt-tokens]
The system prompt, the prompt and every field description can use these tokens. Read Frog replaces them with plain text before it sends the request.
| Token | Replaced with |
| -------------------- | ----------------------------------------------------------------------------------------- |
| `{{selection}}` | The selected text |
| `{{paragraphs}}` | The paragraphs that contain the selection, joined with blank lines, up to 2000 characters |
| `{{targetLanguage}}` | Your target language |
| `{{webTitle}}` | The page title |
| `{{webUrl}}` | The full URL of the page |
| `{{webContent}}` | The main content of the page, up to 2000 characters |
## How Output Schema Works [#how-output-schema-works]
The output schema lists the fields the AI fills in. Each field has:
* **Field name**: also the label the plain field list shows above the value, so name it in the language you read
* **Field type**: **Text** or **Number**
* **Description**: what goes in the field, and in which language
The output schema has two jobs:
1. It tells the model which fields must be returned.
2. It gives the layout the values to show.
The field description is not only a note for humans: it is the model's main guide for that field. Use it to set the language, length, format and other rules.
A few things to know:
* Fields arrive in order while the answer streams in, so put what you want to read first at the top.
* Fewer fields give faster and more reliable answers. Try to stay at eight or fewer.
* There is no list type. For a list, use a **Text** field whose description asks for a JSON array, and show it as a list in the layout.
* Renaming a field also updates the layout's references to it.
* To read a field aloud, add a speak button to the layout. It replaces the old **Enable speaking** option.
## Layout [#layout]
The layout decides how the card looks and what happens when you click it. An empty layout shows the plain field list: each field's name above its value.
Under **Layout**, click **Edit** to open the layout editor.
* On the left is the layout's source. **Field**, **Speak button**, **If filled** and **Context** insert ready-made pieces at the cursor, and **Syntax** explains what you can write.
* On the right is a live preview. Check it at **320** and **500** pixels wide (the popup's narrowest and default widths), in the light and the dark theme. **Sample data** changes the values it shows, and **Replay** plays the answer streaming in.
* **Restore default** replaces the layout with the plain field list or, when your fields fit, a built-in card.
A built-in action's layout is read-only: click **Customize** to edit a copy.
### Writing a Layout [#writing-a-layout]
A layout is HTML with [Liquid](https://liquidjs.com/) tags. It updates as the answer streams in, so each field fills in when it arrives.
| Write | To |
| -------------------------------------- | ---------------------------------------------------------------- |
| `{{ ["Field name"] }}` | Show a field. A plain English name also works bare: `{{ Word }}` |
| `{% if ["Field name"] %}…{% endif %}` | Show something only once the field has a value |
| `{{ ctx.selection }}` | Show the selected text |
| `newline_to_br`, `lines`, `parse_json` | Keep line breaks, split text into lines, or read a JSON list |
Filters go after a pipe, as in `{{ ["Notes"] | newline_to_br }}`. Put CSS in a `
{% if Idiom %}
{{ Idiom }}
{% endif %} {% if Meaning %}{{ Meaning }}
{% endif %} ``` Layouts can't run scripts or load anything from the web: no `