A vocabulary flashcard app that turns plain text into Anki-compatible decks. Paste your word lists, let AI fill in the gaps, and export ready-to-study .apkg files.
- Text-to-Deck — Paste vocabulary lists in various formats (
=:-|tab) and get structured flashcards - AI Definitions & Examples — Cloudflare Workers AI generates missing definitions and example sentences
- Grammar Check — LanguageTool integration catches errors before you study
- Anki Export — Native
.apkggeneration with optional AI pronunciation audio (EN, ES, FR, ZH, JP, KR) - Offline-First PWA — Works without internet, syncs when back online
- Cloud Sync — Supabase real-time sync keeps decks in sync across devices
- Google OAuth — One-click sign-in with Google
Note
AI features (definition generation, example sentences, TTS) require a Cloudflare account with Workers AI access.
- Node.js 18+
- pnpm
- Supabase project
- Cloudflare account (for AI features)
-
Clone the repository
git clone https://github.com/yourusername/vocabspark.git cd vocabspark -
Install dependencies
pnpm install
-
Set up environment variables
cp .env.example .env.local
Fill in your
.env.local:NEXT_PUBLIC_SUPABASE_URL=your_supabase_url NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key NEXT_PUBLIC_APP_URL=http://localhost:3000
-
Set up Supabase tables
Run the following SQL in your Supabase SQL editor:
-- Tables create table decks ( id text primary key, user_id uuid not null references auth.users(id) on delete cascade, name text not null, description text, card_count int default 0, created_at timestamptz default now(), updated_at timestamptz default now() ); create table cards ( id text primary key, deck_id text not null references decks(id) on delete cascade, user_id uuid not null references auth.users(id) on delete cascade, word text not null, definition text not null, example text, audio_url text, position int default 0, created_at timestamptz default now(), updated_at timestamptz default now() ); create table user_settings ( id uuid default gen_random_uuid() primary key, user_id uuid not null references auth.users(id) on delete cascade unique, delimiter text default ',', auto_sync boolean default true, grammar_language text default 'auto', ai_enabled boolean default true, ai_language text default 'en', cards_per_page int default 50, deck_view_mode text default 'grid', created_at timestamptz default now(), updated_at timestamptz default now() ); -- Row Level Security alter table decks enable row level security; alter table cards enable row level security; alter table user_settings enable row level security; create policy "Users can manage own decks" on decks for all using (auth.uid() = user_id); create policy "Users can manage own cards" on cards for all using (auth.uid() = user_id); create policy "Users can manage own settings" on user_settings for all using (auth.uid() = user_id); -- Realtime alter publication supabase_realtime add table decks; alter publication supabase_realtime add table cards;
-
Start the dev server
pnpm dev
Deploy to Cloudflare Pages via OpenNext:
-
Add your Supabase credentials to
wrangler.jsonc -
Enable Workers AI binding in
wrangler.jsonc"ai": { "binding": "AI" }
-
Preview locally
pnpm preview
-
Deploy to production
pnpm deploy
- Fork the project
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Distributed under the MIT License.