Learn Japanese while you browse.
tango is a small learning platform made of two parts:
The extension works locally with bundled lessons and local browser storage. The API is the foundation for account-based and server-backed features.
The production API runs on Render, uses Neon-hosted PostgreSQL, and sends application logs and observability data to New Relic.
| Area | Choice |
|---|---|
| Client | TypeScript, React 18, Vite, Chrome Manifest V3 |
| API | Go, Echo, JWT |
| Data | PostgreSQL and Redis |
| Local orchestration | Docker Compose and Taskfile |
| Current state | MVP |
flowchart LR
Browser[Web pages] --> Extension[tango Chrome extension]
Extension --> Local[(Chrome local storage)]
Extension -->|HTTPS JSON API| API[tango Go API]
API --> Postgres[(PostgreSQL)]
API --> Redis[(Redis)]
Lessons[Lesson YAML] --> Sync[Content sync]
Sync --> Postgres
sequenceDiagram
participant A as Alarm
participant W as Service worker
participant T as Active tab
participant C as Content script
participant S as Chrome storage
A->>W: Schedule a practice prompt
W->>S: Read settings and progress
W->>T: Find an injectable tab
W->>C: Send the next card
C-->>W: Answer or dismiss
W->>S: Save progress and pending state
.
├── apps/
│ ├── client/ Chrome extension
│ │ ├── src/background/ Service worker, scheduling, API client
│ │ ├── src/content/ Bundled lessons
│ │ ├── src/contentScript/ Cards injected into web pages
│ │ ├── src/popup/ Toolbar popup
│ │ ├── src/sidepanel/ Progress and controls
│ │ └── src/options/ User settings
│ └── backend/ Go API and content services
│ ├── cmd/ API and sync entry points
│ ├── content/lessons/ Lesson YAML source
│ ├── internal/handler/ HTTP handlers
│ ├── internal/service/ Application logic
│ ├── internal/database/ Connections and migrations
│ ├── compose.yml Local PostgreSQL and Redis
│ └── Taskfile.yml Development commands
└── README.md
>=14.18.0 and npmapps/backend/go.modcd apps/backend
go mod download
cp .env.sample .env
task dev
This starts PostgreSQL and Redis, applies migrations, and runs the Go API with hot reload. Check the API with:
curl http://localhost:8080/status
In a second terminal:
cd apps/client
npm install
npm run dev
Then open chrome://extensions, enable Developer mode, choose Load unpacked, and select apps/client/build.
Open a normal http:// or https:// page to try a card. Chrome internal pages, the Web Store, and other restricted pages cannot receive injected cards.
flowchart TD
Install[npm install] --> Watch[npm run dev]
Watch --> Build[apps/client/build]
Build --> Load[Load unpacked in Chrome]
Load --> Try[Open a normal web page]
Run backend commands from apps/backend and client commands from apps/client.
| Command | Result |
|---|---|
task dev |
Start local services, migrate, and run the API with Air |
task test |
Run all Go tests |
task build |
Build the API binary as bin/tango |
task infra:down |
Stop local services and remove their volumes |
npm run dev |
Watch and build the extension |
npm run build |
Type-check and create a production extension build |
npm run zip |
Build and create a versioned Chrome release archive |
npm run fmt |
Format client source and documentation |
| Method | Route | Auth | Use |
|---|---|---|---|
GET |
/status |
None | Health check |
POST |
/api/v1/login |
None | Sign in and issue a session/JWT |
POST |
/api/v1/lessons |
JWT | Create lesson content |
GET |
/api/v1/progress |
JWT | Read progress |
POST |
/api/v1/progress/:item_id/attempt |
JWT | Record an attempt |
GET |
/api/v1/settings |
JWT | Read settings |
PUT |
/api/v1/settings |
JWT | Update settings |
The local client API default is localhost:8080. Confirm the production API URL, /api/v1 routing, CORS, OAuth client, and authentication flow before connecting a release build to a deployed API.
Backend configuration is loaded from the TANGO_* environment variables. Start with apps/backend/.env.sample.
| Group | Covers |
|---|---|
TANGO_PRIMARY_* |
Environment name |
TANGO_SERVER_* |
Port, timeouts, and CORS |
TANGO_DATABASE_* |
PostgreSQL connection and pool settings |
TANGO_REDIS_* |
Redis address |
TANGO_AUTH_* |
JWT signing configuration |
TANGO_INTEGRATION_* |
External services such as Resend |
TANGO_OBSERVABILITY_* |
Logs, health checks, and New Relic |
Do not commit .env files, OAuth secrets, JWT secrets, API keys, or store credentials.
cd apps/backend && task test
cd apps/client && npm run build
For browser behavior, use the manual checklist in apps/client/TESTING.md. It covers scheduling, quiet hours, pending cards, card types, lesson unlocking, progress, and badge behavior.
TANGO_* production configuration./status, authentication, database, Redis, and application errors.The repository does not yet include a production container, cloud-provider configuration, or CI/CD workflow. The Compose file is for local development dependencies.
cd apps/client
npm run zip
Before uploading the generated archive:
apps/client/package.json.build/ output in a clean Chrome profile.Store publishing is manual at present.
The extension uses storage, alarms, tabs, scripting, activeTab, sidePanel, and identity permissions. These support local learning state, scheduling, card injection, controls, and Google sign-in. Review the manifest and privacy disclosures before every release.
Keep changes scoped to the relevant app. Run the backend tests, client build, and browser checklist when user-facing behavior changes. Update the relevant README or QA checklist alongside workflow changes.
MIT. See apps/client/LICENSE.