Plugins
The Plugins sidebar group is the bridge between the Enjoy web app and other Enjoy surfaces — most notably the browser extension. Use it whenever you want to learn outside the web app, or when you want to bring content from a streaming site into your library.
Where to Find It
Open the web app sidebar and scroll down to the Plugins group near the bottom. It sits between the main feature group and the secondary entries (Settings, Account, Logout).
The current entries are:
| Plugin | What it does |
|---|---|
| Chrome Extension | Opens the Chrome Web Store listing for the Enjoy browser extension in a new tab. |
Chrome Extension
The Chrome extension brings Enjoy's learning features to YouTube, Netflix, and other supported sites. After installing it, you can:
- Open the sidepanel to read transcripts, vocabulary, and notes without leaving the page
- Use Echo Mode to shadow a YouTube line and get instant pronunciation feedback
- Use Dictation Mode to type what you hear and improve listening accuracy
- Save media to your Enjoy library so it syncs to the web app and other devices
Shared Account and Sync
The extension uses the same Enjoy account as the web app. Vocabulary, recordings, and notes you create in the extension sync through the Sync feature and appear in the web app's Vocabulary and library views.
Installation
For a step-by-step walkthrough, see the extension's Installation guide.
Adding a New Plugin
To register a new entry in the Plugins group, add an item to the navPlugins array in apps/web/src/components/layout/app-sidebar.tsx:
const navPlugins = [
{
title: t("plugins.chromeExtension", { ns: "common" }),
url: "https://chromewebstore.google.com/detail/enjoy-echo/...",
icon: IconBrandChrome,
target: "_blank",
},
// Add new plugin entries here
]Each entry needs:
| Field | Purpose |
|---|---|
title | Localized label via t(...) with a defaultValue fallback |
url | External link or in-app route |
icon | Tabler icon component (or another icon from the project's icon set) |
target | "_blank" for external links, omit for in-app routes |
The group label itself is sourced from the common namespace:
<SidebarGroupLabel>{t("plugins.title", { ns: "common", defaultValue: "Plugins" })}</SidebarGroupLabel>⚠️ Nested-key gotcha: When a key resolves to a JSON object in the translation file, calling
t("plugins")(without specifying a child key) returns the object rather than a string. i18next then renders an error string in production. Always specify a leaf key (t("plugins.title")) and provide adefaultValueso the sidebar still renders if the namespace is missing.