Promotee — Interview Practice Flashcard App
A web app designed and developed for people preparing for interviews, speaking tests, or presentations in a language other than their first language. Users can import their own questions and answers from a CSV file and practise speaking them in multiple modes — in order, randomly, or by category — without creating an account or storing the content on a server. The implementation also includes keyboard interaction, reduced-motion support, and live-region announcements for dynamic updates.
Period: Jun 2025 – Sep 2025
Where this experience applies
Experience covering web app UX design, frontend implementation, state management, accessibility implementation, and validation.
- Designing a web app that handles user-provided data
- Making forms usable with the keyboard and announcing dynamic state changes to screen readers
- Connecting design decisions with implementation and validation
Overview
Promotee is a flashcard app for people preparing for interviews, speaking tests, or presentations in a language other than their first language. Users can import their own questions and answers from a CSV file and practise speaking them in their original order, randomly, or by category. The app supports long-form answers and multilingual characters, with a limit of up to 300 entries per import. Because the questions and answers are provided through CSV files, the app can be used with multiple languages. No account is required. The imported content and practice status are managed temporarily in a Zustand store, are not stored on a server, and are cleared when the page is reloaded.
Background
Based on my own experience as a non-native English speaker, I wanted a way to repeatedly practise prepared answers for situations such as job interviews. Existing tools had limitations that made them difficult to use for this purpose: AI mock interviews offered only generic questions, and most flashcard apps were designed for short words or phrases rather than full answers. I also wanted a tool that would help me speak my answers, not just read them. The app allows users to bring their own questions and answers instead of relying on a fixed set of learning materials. Because it handles interview preparation content, I designed it without requiring an account or storing the imported content on a server — and without gamification or social features that would distract from the practice itself.
Challenge
- Import questions and answers from CSV files, support long-form answers and multilingual characters up to 300 entries, and provide multiple practice modes
- Temporarily track whether each card has been remembered and allow users to repeat cards that remain unremembered
- Provide the practice flow without requiring an account or server-side storage
- Make forms and card interactions usable with the keyboard, and announce state changes and notifications through live regions
- Adjust motion and loading behaviour across screens containing animation and video
Users
- People preparing for interviews in a language other than their first language
- People preparing for speaking tests such as IELTS or TOEFL
- People who want to practise with questions and answers they have prepared themselves
- People who want to review their content in order, randomly, or by category
- People who do not want their interview preparation content stored on a server
Approach
Practice Flow and State Management
- Implemented a flow for importing questions and answers from a CSV file and practising them in their original order, randomly, or by category
- Allowed users to mark each card as remembered or not yet remembered and continue practising unremembered cards until the page is reloaded
- Managed imported data and practice status in a Zustand store without persistent storage
Page Structure and Keyboard Interaction
- Structured pages using landmarks such as `header`, `main`, and `footer`
- Implemented a skip link that takes users directly to the main content
- Used elements such as `label` and `fieldset` for forms
- Checked basic interactions on key screens using Tab, Shift+Tab, Enter, Space, and the arrow keys
- Added consistent `:focus-visible` styles so that the current focus position can be identified
State Changes and Notifications
- Used `aria-live="polite"` for card-status updates such as “Marked as remembered”
- Wrapped React Toastify in a custom component to provide assertive live-region announcements for toast messages
- Added text prefixes to identify the notification type and hid decorative icons from screen readers
- Kept some error messages visible until dismissed rather than removing them automatically
Contrast and Motion
- Checked colour combinations using WebAIM Contrast Checker
- Adjusted text and background colours that did not meet WCAG AA contrast ratios
- Applied the operating system’s `prefers-reduced-motion` setting and the app’s own motion setting to card-flip and completion animations
- Removed rotation and confetti from state changes when reduced motion is enabled
Video and Performance
- Replaced GIFs used in the interface with WebM and MP4 video files
- Adjusted `preload` settings by page according to the purpose of the hero and instructional videos
Checks and Validation
- Ran ESLint with eslint-plugin-jsx-a11y to check the source code for accessibility issues
- Ran axe audits on key screens for both desktop and mobile
- Imported dummy data locally to reproduce the required interaction states on screens that depend on client-side state
- Used VoiceOver to manually check basic interactions, forms, navigation, and state announcements on key screens
Design and Implementation Details
No Account or Persistent Storage
Interview content imported by the user is handled within a Zustand store and is not sent to or stored on the server. Reloading the page clears both the imported content and the current practice status.
Communicating State Changes Beyond Visual Feedback
Card-status changes and toast notifications are communicated through text and live regions rather than relying only on colour or animation.
Page-specific Loading Behaviour
Video formats and `preload` settings were selected according to where each video appears and how it is used, rather than applying the same loading behaviour across all pages.
Distraction-free by Design
Promotee has no gamification, no social features, and no login. The interface is intentionally quiet — focused on repetition and the practice of speaking, rather than performance or engagement metrics.
Outputs
- Publicly available web app
- CSV import and flashcard practice functionality
- Ordered, random, and category-based practice modes
- Temporary remembered/not-yet-remembered state and repeat practice
- Keyboard interaction and visible focus styles
- Reduced-motion behaviour
- Notifications using live regions
- Accessibility implementation demo
- Axe and contrast-checking results
- Responsive layout for desktop and mobile
Results
Best Practices / SEO
100 on key screens (2025)
Performance
97+ including dynamic screens (2025)
- Released a web app that allows users to import a CSV file and practise interview questions in multiple modes without creating an account
- Implemented a structure in which imported CSV content and practice status are not stored on the server
- Checked basic interactions on key screens using the keyboard and VoiceOver
- Implemented adjustments covering contrast, motion, focus, forms, and dynamic notifications
Selected Materials
Contrast Check and Adjustment
Tailwind green-500 on white measured 2.27:1 and was changed to green-700 at 5.01:1 to meet the WCAG AA contrast requirement.
Reflection
- The implementation confirmed that visual judgement alone is not sufficient for evaluating colour contrast and that contrast ratios need to be measured
- Automated audits, keyboard checks, and screen-reader checks cover different aspects of an interface
- Screens with dynamic state changes required checks based on the actual interaction flow in addition to code review and automated audits
Validation Scope
- Dynamic screens were audited locally using dummy data to reproduce the required application state
- Screen-reader checks covered basic interactions on key screens using VoiceOver on macOS