Skip to main content

Vocabography

·818 words·4 mins

A Personal Vocab Journal
#

What I Built
#

Vocabography is a mini web app that acts as my personal vocab journal. The idea behind it is simple, instead of a regular app giving me a word every single day to remember, I bring in the words I actually encounter in real life (let’s say from a book I’m reading, a conversation, or a show) and add them myself. Each word gets an auto-fetched dictionary definition, then I add my own example sentence using the word. After some days, the app quizzes me by blanking out the word in my own sentence, rather than a default example. And finally the results are added in the score section where I can track my progress.

Live Site
#

🔗 vocabography.web.app/

How it works
#

  1. Catch a word. Just type in the word.
  2. Auto-lookup. Vocabography automatically fetches its definition and part of speech from the Free Dictionary API (no API key needed).
  3. Make it yours. Write your own example sentence using the word.
  4. Store it. Everything gets saved in the journal as well as in the firestore database (so it’s accessible whether you are on a phone or laptop).
  5. Streak. Click the 🔥 in the nav bar to see a GitHub-style heatmap of every day you’ve added a word, plus your current and longest streaks.
  6. Search your collection. The Collection tab lists every word you’ve ever added, most recent first, styled like index cards pulled from a catalog drawer.
  7. Review & score. Vocabography quizzes you with your own sentence, blanking out the word you have to recall. Get it right and the interval grows (3 → 7 → 21 days) and you earn points. If you get it wrong it resets back to 3 days. The quiz pops up automatically the moment a word becomes due, and the 🏆 tab tracks your total points, correct/missed counts, and accuracy.
  8. Themes. You can easily toggle between a dark ink-and-parchment theme and a warm cream light theme from the nav bar.

Tech stack
#

  • Styled with Tailwind CSS v4
  • Built with Vite
  • Written in React + TypeScript
  • Stored in Firebase Firestore (a cloud database), where word entries live in a words collection, while streak and quiz stats live together in a single document called meta
  • Theme preference is stored separately in localStorage, since it’s a device’s local setting, not journal content

No login here, for now it’s just for me. Rules are open on purpose (you can check firestore.rules).

Complete Code
#

github.com/waleeja07-wk/vocabography

Project structure
#

├── firebase.json           # Firebase CLI config (points hosting at dist/, deploys firestore.rules)
├── firestore.rules         # Firestore security rules (open access, single-user app)
├── vite.config.ts          # Vite build configuration
├── tsconfig.json           # TypeScript compiler settings
├── package.json            # Dependencies and npm scripts
├── .env.local              # Firebase config keys (It is gitignored)
src/
├── types/word.ts           # LoggedWord, ReviewState, StreakData, QuizStats, AppSettings
├── lib/                    # Pure business logic, no React
│   ├── firebase.ts         # Firebase app + Firestore instance initialization
│   ├── storage.ts          # Firestore read/write for words, streak, and quiz stats
│   ├── settings.ts         # localStorage read/write for theme
│   ├── dictionaryApi.ts    # Free Dictionary API integration, with retry handling
│   ├── streak.ts           # Streak calculation
│   ├── spacedRepetition.ts # Quiz interval scheduling and scoring
│   └── dateUtils.ts        # Shared date helpers
├── hooks/                  # Thin React layer over lib/
│   ├── useWords.ts         # Owns word data, loading/error state, and all mutations
│   ├── useStreak.ts
│   ├── useReviewQueue.ts
│   └── useSettings.ts
└── components/
    ├── AddWordForm.tsx     # Search for a word, then write your sentence
    ├── WordCard.tsx        # Word added, catalog-card style
    ├── HistoryList.tsx     # All the words currently added, most recent first
    ├── NavBar.tsx          # Home / Collection / Streak / Quiz + theme toggle
    ├── ActivityHeatmap.tsx # GitHub-style daily activity map
    ├── QuizScorePanel.tsx  # Total points, correct vs incorrect
    └── ReviewQuiz.tsx      # Fill in the blank review, auto-popup on due day

Run Locally
#

  1. Install dependencies:
    npm install
  2. Create a Firebase project at console.firebase.google.com, enable Firestore, and register a web app to get your config values.
  3. Create a .env.local file in the project root:
    VITE_FIREBASE_API_KEY=...
    VITE_FIREBASE_AUTH_DOMAIN=...
    VITE_FIREBASE_PROJECT_ID=...
    VITE_FIREBASE_STORAGE_BUCKET=...
    VITE_FIREBASE_MESSAGING_SENDER_ID=...
    VITE_FIREBASE_APP_ID=...
  4. Deploy the Firestore rules in firestore.rules:
    firebase deploy --only firestore:rules
  5. Run the dev server:
    npm run dev

Deployment
#

Deployed with Firebase Hosting:

npm run build
firebase deploy --only hosting

6-hour is just a myth
#

This internship task was estimated to be completed in 6 hours. But it took almost 10x that for writing, rebuilding, debugging, and actually understanding what I was building, But yeah, it added up. Every effort was worth it..

Improvements planned for future
#

Things I’d love to add if I keep working on this:

  • Add Firebase Authentication so multiple people can each keep their own private word collection, with security rules enforcing per-user data isolation (request.auth.uid == resource.data.userId).
  • Show upcoming review dates in the history view.
  • Export your journal as a shareable list.
Waleeja Khan
Author
Waleeja Khan
Tech girlie 💻