How to Customize the Behavior of Everyone‑Can‑Use‑English: A Complete Configuration Guide
You customize everyone‑can‑use‑english by editing configuration files in src/main/settings.ts, modifying constants in src/constants/index.ts, or extending the API client in src/api/client.ts.
The Enjoy application—the core of the open‑source everyone‑can‑use‑english project—is an Electron‑based desktop app that teaches English through AI‑powered conversations. Its behavior is controlled through three architectural layers: persistent settings, hardcoded constants, and a typed REST API client. This guide shows you exactly how to modify each layer using the actual source code from ZuodaoTech/everyone‑can‑use‑english.
Where Configuration Lives in the Codebase
| Layer | File | Purpose |
|---|---|---|
| Persistent Settings | src/main/settings.ts |
User‑specific options stored via electron-settings |
| Default Constants | src/constants/index.ts |
API URLs, model lists, agent definitions |
| API Client | src/api/client.ts |
Typed Axios wrapper for remote operations |
Understanding these three files unlocks every customization point in everyone‑can‑use‑english.
Customizing Persistent Settings via IPC
The settings.ts module registers IPC handlers that let renderer processes read and write configuration values. These handlers cover library location, API endpoints, and more.
Available IPC Commands
app-settings-set-library– changes where your media library is storedapp-settings-set-api-url– switches to a custom backendapp-settings-get-*variants for reading values
Example: Changing the API URL at Runtime
// In any renderer component
await window.electron.ipc.invoke(
'app-settings-set-api-url',
'https://my.custom.api/v1'
);
The handler at lines 78‑118 of src/main/settings.ts writes this value to disk via electron-settings. The app loads it automatically on restart.
Example: Moving the Library Directory
async function changeLibraryPath(newPath: string) {
await window.electron.ipc.invoke('app-settings-set-library', newPath);
// Trigger UI refresh if needed
}
The library path logic (lines 15‑30) ensures cross‑platform consistency in where files are stored.
Modifying Default Constants in src/constants/index.ts
Constants are immutable defaults imported throughout the app. Edit this file to change API endpoints, model availability, or AI tutor personalities.
Change the Web API Endpoint
Line 34 defines WEB_API_URL:
// src/constants/index.ts
export const WEB_API_URL = "https://api.enjoy.bot";
Or set the WEB_API_URL environment variable—settings.ts lines 63‑66 prefer environment values over hardcoded defaults:
export const apiUrl = () => {
return process.env.WEB_API_URL || settings.getSync("apiUrl") || WEB_API_URL;
};
Customize Available AI Models
Lines 45‑60 define WHISPER_MODELS and NOT_SUPPORT_JSON_FORMAT_MODELS. Add or remove entries to control which transcription and chat models appear in the UI:
export const WHISPER_MODELS = [
{ name: "tiny", size: "39 MB" },
{ name: "base", size: "74 MB" },
{ name: "small", size: "244 MB" },
// Add custom model here
{ name: "large-v3-custom", size: "1.5 GB" },
];
Create Custom LLM Agent Personas
Lines 91‑119 define AGENT_FIXTURE_AVA and AGENT_FIXTURE_ANDREW—the default AI tutors. Clone and modify these to create new teaching personas.
// src/constants/index.ts
export const AGENT_FIXTURE_SOFIA = {
name: "Sofia",
description: "Your friendly British English tutor.",
language: "en-GB",
config: {
engine: "enjoyai",
model: "gpt-4o",
prompt: "You are a patient British teacher focusing on pronunciation and idioms.",
temperature: 0.9,
ttsEngine: "enjoyai",
ttsModel: "azure/speech",
ttsVoice: "en-GB-SofiaNeural",
},
};
Then expose Sofia in your UI components by importing and listing this fixture alongside AGENT_FIXTURE_AVA.
Extending the API Client in src/api/client.ts
The Client class provides typed methods for all remote operations. Customize it to add endpoints, inject middleware, or modify request behavior.
Add a New Custom Endpoint
Follow the existing pattern: use decamelizeKeys for request payloads and let responses auto‑convert via the configured interceptor:
// Inside class Client (src/api/client.ts)
customPrompt(data: { prompt: string; context?: string }): Promise<CustomResponse> {
return this.api.post('/api/custom_prompt', decamelizeKeys(data));
}
Inject Request/Response Interceptors
Lines 38‑50 set up basic interceptors. Add your own for logging, retry logic, or token refresh:
// After existing interceptors in constructor
this.api.interceptors.response.use(undefined, async (error) => {
const { config } = error;
if (!config || config.__retryCount >= 3) {
return Promise.reject(error);
}
config.__retryCount = config.__retryCount || 0;
config.__retryCount++;
await new Promise(r => setTimeout(r, 1000 * config.__retryCount));
return this.api.request(config);
});
Override GPT Configuration Per Feature
Import DEFAULT_GPT_CONFIG and spread‑modify it:
import { DEFAULT_GPT_CONFIG } from '@/constants';
import { Client } from '@/api/client';
const strictConfig = {
...DEFAULT_GPT_CONFIG,
temperature: 0.6, // More deterministic output
maxCompletionTokens: 500, // Shorter responses
};
const client = new Client({
baseUrl: apiUrl(),
locale: 'en',
...strictConfig
});
DEFAULT_GPT_CONFIG is defined at lines 80‑88 of src/constants/index.ts.
Adapting the UI to Custom Behavior
Renderer components consume settings via IPC and display agent fixtures from constants. Key files to modify:
| File | Customization Purpose |
|---|---|
src/renderer/components/preferences/index.ts |
Add new preference controls |
src/renderer/components/llm-chats/index.ts |
Display custom agent fixtures |
src/constants/gpt-presets.ts |
Pre‑defined GPT configurations for commands |
When you add new IPC commands in settings.ts, register corresponding UI handlers in the preferences component to expose them to users.
Environment‑Based Configuration
Several settings support environment variable overrides:
| Variable | Affects |
|---|---|
WEB_API_URL |
Remote API endpoint (preferred over settings file) |
DATABASE_NAME |
Local database filename |
| Custom variables | Your own extensions in settings.ts |
This lets you deploy everyone‑can‑use‑english across staging and production environments without code changes.
Summary
- Persistent settings live in
src/main/settings.ts—modify via IPC handlers that wrapelectron-settings - Default constants live in
src/constants/index.ts—edit API URLs, model lists, and agent fixtures here - API client lives in
src/api/client.ts—extend with new methods and Axios interceptors - UI components consume these layers through typed IPC calls and fixture imports
- Environment variables override hardcoded values for deployment flexibility
These customization points let you tailor everyone‑can‑use‑english for personal workflows, institutional deployments, or experimental features without forking the entire codebase.
Frequently Asked Questions
How do I change the API server that everyone‑can‑use‑english connects to?
Set the WEB_API_URL environment variable to your custom endpoint. If that's unavailable, invoke the IPC command 'app-settings-set-api-url' with your URL, or directly edit line 34 of src/constants/index.ts. The apiUrl() helper in settings.ts checks environment variables first, then settings storage, then the hardcoded default.
Can I add my own AI tutor personality to the application?
Yes. Define a new agent fixture object in src/constants/index.ts following the pattern of AGENT_FIXTURE_AVA (lines 91‑101). Include name, description, language, and a full config object with engine, model, prompt, and TTS settings. Then import and render this fixture in src/renderer/components/llm-chats/index.ts.
Where is user data like library location actually stored?
The electron-settings npm package handles persistence. In src/main/settings.ts (lines 15‑30), the library path is resolved to an OS‑appropriate directory. All settings are stored in JSON format within the Electron user data folder, making them portable and easy to back up.
How do I add retry logic for failed API requests?
Extend the Axios instance in src/api/client.ts by adding a response interceptor after line 50. Access this.api.interceptors.response.use() to handle errors, inspect the config object for retry state, and return this.api.request(config) after a delay. The code example in this guide demonstrates exponential backoff.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →