The technology stack used is:
And Chrome Extension Development Documentation. Currently, the manifest version used by Chrome and Edge is v3, and Firefox uses v2. Please pay attention to compatibility.
Some free open source tools are also integrated:
- Fork this repository to your GitHub account
- Clone your forked repository locally
npm install
npm run prepareCreate a new branch for your changes
# Chrome/Edge development
npm run dev
# Firefox development
npm run dev:firefox
# Safari development
npm run dev:safariThis will create output directories:
dist_dev- Chrome/Edge extensiondist_dev_firefox- Firefox extensiondist_dev_safari- Safari extension
For Firefox on Android development, use the helper script:
./script/android-firefox.shThis script will:
- Check prerequisites (web-ext, adb)
- Detect connected Android devices
- Build the extension automatically
- Install and run on Firefox for Android
# Build all platforms
npm run build
# Build specific platform
npm run build:firefox
npm run build:safari- Open
chrome://extensions/oredge://extensions/ - Enable "Developer mode"
- Click "Load unpacked" and select the
dist_devfolder
- Open
about:debugging - Click "This Firefox"
- Click "Load Temporary Add-on"
- Select the
manifest.jsonfile fromdist_dev_firefoxfolder
Use the provided script which handles the entire process automatically.
npm run testnpm run test-cThis will generate coverage reports in the coverage/ directory.
Note: This step is optional! All PRs will automatically run this step.
Use the provided setup script to initialize the e2e testing environment:
# Initialize e2e environment (install dependencies and build outputs)
bash script/setup-e2e.sh --init --build
# Start test servers
bash script/setup-e2e.sh --start-serversThe setup script will:
- Install/upgrade global dependencies (
http-server,pm2) - Download browser for Puppeteer (if needed)
- Build e2e test output (
dist_e2e/) - Start test servers on ports 12345 and 12346
npm run test-e2eFor headless Puppeteer testing:
export USE_HEADLESS_PUPPETEER=true
npm run test-e2eAfter testing, stop the servers:
pm2 stop all && pm2 delete allThe setup-e2e.sh script supports multiple options:
# Show help
bash script/setup-e2e.sh --help
# Initialize only (install dependencies)
bash script/setup-e2e.sh --init
# Build e2e output only
bash script/setup-e2e.sh --build
# Initialize and build
bash script/setup-e2e.sh --init --build
# Run all steps (init + build + build production)
bash script/setup-e2e.sh --all- Use single quotes whenever possible
- Keep code concise while being grammatically correct
- No semicolons at the end of lines
- Use LF (
\n) line endings
For Windows users:
git config core.autocrlf falseThe project uses Husky for pre-commit hooks. These will run automatically when you commit:
git add .
git commit -m "feat: add new feature description"
# or
git commit -m "fix: fix bug description"Use conventional commit messages:
feat:for new featuresfix:for bug fixesdocs:for documentation changesstyle:for formatting changesrefactor:for code refactoringtest:for adding testschore:for maintenance tasksi18n:for internationalization
Create a Pull Request to the main branch of this repository.
- All tests pass
- Documentation updated if needed
time-tracker-4-browser/
├── src/ # Source code
│ ├── manifest.ts # Chrome/Edge manifest
│ ├── manifest-firefox.ts # Firefox manifest
│ ├── api/ # API layer
│ ├── background/ # Service Worker
│ ├── content-script/ # Content scripts
│ ├── pages/ # UI pages
│ │ ├── app/ # Main app (background page)
│ │ ├── popup/ # Extension popup
│ │ │ ├── skeleton.ts # Popup skeleton
│ │ │ └── index.ts # Popup entry
│ │ └── side/ # Side panel
│ ├── service/ # Business logic
│ ├── database/ # Data access layer
│ ├── i18n/ # Internationalization
│ ├── util/ # Utilities
│ └── common/ # Shared code
├── test/ # Unit tests
│ └── __mock__/ # Test mocks
├── test-e2e/ # End-to-end tests
├── types/ # TypeScript declarations
├── rspack/ # Build configuration
├── script/ # Build and utility scripts
│ ├── android-firefox.sh # Android development helper
│ └── setup-e2e.sh # E2E test environment setup
├── public/ # Static assets
├── doc/ # Documentation
├── dist_dev/ # Chrome/Edge dev build
├── dist_dev_firefox/ # Firefox dev build
└── dist_dev_safari/ # Safari dev build
src/manifest.ts- Chrome/Edge extension manifest (Manifest V3)src/manifest-firefox.ts- Firefox extension manifest (Manifest V2)src/background/- Service Worker and background scriptssrc/content-script/- Scripts injected into web pagessrc/pages/- Extension UI (popup, side panel, options)
Please use the code formatting tools that come with VSCode. Please disable Prettier Eslint and other formatting tools
- Use single quotes whenever possible
- Keep the code as concise as possible while being grammatically correct.
- No semicolon at the end of the line
- Please use LF (\n). In Windows, you need to execute the following command to turn off the warning:
git config core.autocrlf false
Except for certain professional terms, the text of the user interface can be in English. For the rest, please use i18n to inject text. See the code directory src/i18n
- Add new fields in the definition file
xxx.ts - Then add the corresponding text of this field in English (en) in the corresponding resource file
xxx-resource.json - Call
t(msg => msg...)in the code to get the text content, which can make full use of TypeScript to inspect translated texts.
Crowdin is a collaborative translation platform that allows native speakers to help translate multilingual content. The project's integration with Crowdin is divided into two steps. Collaborators usually need't to perform these steps.
- Upload English text and other language text in code
# Upload original English text
ts-node ./script/crowdin/sync-source.ts
# Upload texts in other languages in local code
ts-node ./script/crowdin/sync-translation.ts
Because the above two scripts rely on the Crowdin access secret in the environment variable, I integrated them into Github's Action
- Export translations from Crowdin
ts-node ./script/crowdin/export-translation.ts