An open-source typing practice application that uses literary quotes to help users improve their typing speed and accuracy. EchoType selects random quotes from books and allows users to practice typing them, providing real-time feedback and statistics.
- Features
- Demo
- Installation
- Usage
- Project Structure
- Architecture and Design
- Technologies Used
- Contributing
- License
- Acknowledgements
- Contact
- Random Quote Selection: Fetches random quotes from a curated collection of books to provide a unique typing experience each time.
- Multiple Typing Modes:
- Short: Practice with short quotes for quick sessions.
- Medium: Medium-length quotes for moderate difficulty.
- Long: Longer quotes for advanced practice.
- Real-Time Feedback:
- Displays correct and incorrect keystrokes.
- Highlights the current character to be typed.
- Updates typing statistics such as Errors, Words Per Minute (WPM), and Accuracy.
- Results Screen:
- Upon completion, displays a detailed results screen with typing statistics.
- Provides interactive graphs showing typing speed and accuracy over time.
- Keyboard Shortcuts:
- Fetch New Quote: Quickly fetch a new quote using a keyboard shortcut (e.g.,
Tab
key).
- Fetch New Quote: Quickly fetch a new quote using a keyboard shortcut (e.g.,
- Book Filtering and Selection:
- Filter Books:
- Filter available books based on Title, Author, or Language.
- Multi-select support for filtering by multiple titles, authors, or languages.
- Browse and Select Books:
- View a list of available books after applying filters.
- Select a specific book to practice typing quotes exclusively from that book.
- Reset Filters: Easily reset all filters to default settings.
- Filter Books:
- Progress Tracking:
- Visual progress bar showing your typing progress through the quote.
- Typing statistics updated in real-time.
- Book Information:
- Displays detailed information about the book, including title, author, language, and release date.
- Feedback Submission:
- User Feedback Modal:
- Allows users to submit feedback directly from the application.
- Feedback is stored securely in the backend for further review.
- Data Privacy:
- Users must agree to the processing of personal data before submitting feedback.
- Feedback includes a unique ID and timestamp but does not require user authentication.
- User Feedback Modal:
- Desktop-Only Support:
- If the screen width is less than 1100 pixels, the application displays a message indicating that only the desktop version is supported.
- Loading Animation:
- An animated loading screen provides visual feedback during data fetching.
- Performance Optimization:
- Utilizes React's
useMemo
anduseCallback
hooks for efficient rendering. - Memoization of computations and functions to enhance performance.
- Utilizes React's
- Accessibility:
- Focus management and keyboard event handling improve accessibility.
- Node.js (v14 or later)
- npm or yarn
- AWS Amplify CLI (if interacting with AWS backend)
git clone https://github.com/ilya-dyaglev/echotype.git
cd echotype
Using npm:
npm install
Using yarn:
yarn install
If you plan to use AWS Amplify for data fetching and backend services, configure it by initializing Amplify:
amplify init
Follow the prompts to set up your AWS configuration.
To start the development server:
npm start
Or using yarn:
yarn start
The application will run on http://localhost:3000
by default.
- Desktop-Only Support:
- The application is optimized for desktop devices. If your screen width is less than 1100 pixels or height less than 850, a message will be displayed indicating that only the desktop version is supported.
- Header:
- Contains the logo, typing mode selection, and a call-to-action.
- Includes buttons to open the filter modal or fetch a new quote.
- Control Bar:
- Use the buttons to select the typing mode:
- Short
- Medium
- Long
- Use the buttons to select the typing mode:
- Typing Area:
- Click on the typing area to focus and begin typing.
- The quote is displayed with real-time feedback on your keystrokes.
- Statistics are updated as you type.
- Results Screen:
- Displays your typing statistics upon completion.
- Provides interactive graphs showing typing speed and accuracy over time.
- Options to retake the test.
- Filter Modal:
- Accessed via the "Browse Books" button.
- Features:
- Title, Author, and Language Filters:
- Multi-select filters to narrow down books.
- Available Books Section:
- Displays books matching the applied filters.
- Select a specific book to practice with quotes exclusively from that book.
- Reset Filters:
- Quickly reset all filters to default settings.
- Title, Author, and Language Filters:
- How to Use:
- Click "Browse Books" to open the filter modal.
- Select titles, authors, or languages to filter the books.
- View the available books in the list.
- Optionally select a specific book from the list.
- Click "Apply Filters" to update the quotes based on your selection.
- Feedback Submission:
- Accessed via the "Feedback" option in the footer.
- How to Submit Feedback:
- Click on the "Feedback" link in the footer.
- A modal will appear prompting you to enter your feedback.
- Provide your feedback in the text area.
- Check the box to agree to the processing of your personal data.
- Click "Submit Feedback" to send your feedback.
- Progress Bar:
- Shows your progress through the quote.
- Book Information:
- Displays details about the current book, including title, author, language, and release date.
- Other Quote Button:
- Click to fetch a new quote, optionally from a different book if no specific book is selected.
- Fetch New Quote:
- Press the
Tab
key to fetch a new quote.
- Press the
- Backspace:
- Correct mistakes by deleting the previous character.
- Standard Shortcuts:
- Browser shortcuts like
Ctrl+R
orCmd+R
are not blocked.
- Browser shortcuts like
- Hover over graphs:
- Tooltips display detailed information at each data point.
- Graphs:
- Typing Speed Over Time: Shows WPM progression.
- Accuracy Over Time: Shows accuracy percentage over time.
echotype/
├── amplify/
│ ├── backend/
│ │ ├── data/
│ │ │ └── resource.ts
│ │ ├── jobs/
│ │ │ └── bookScrapper/
│ │ │ ├── handler.ts
│ │ │ └── resource.ts
│ │ └── backend.ts
├── public/
├── src/
│ ├── components/
│ │ ├── Header.tsx
│ │ ├── ControlBar.tsx
│ │ ├── Button.tsx
│ │ ├── CTA.tsx
│ │ ├── Main.tsx
│ │ ├── TypingArea.tsx
│ │ ├── Results.tsx
│ │ ├── FilterModal.tsx
│ │ ├── FeedbackModal.tsx
│ │ ├── UnsupportedScreenSize.tsx
│ │ ├── CustomTable.tsx
│ │ ├── ProgressContainer.tsx
│ │ └── Footer.tsx
│ ├── styles/
│ │ ├── App.css
│ │ ├── Header.css
│ │ ├── ControlBar.css
│ │ ├── TypingArea.css
│ │ ├── Results.css
│ │ ├── FilterModal.css
│ │ ├── FeedbackModal.css
│ │ ├── UnsupportedScreenSize.css
│ │ ├── CustomTable.css
│ │ └── Main.css
│ ├── types.ts
│ ├── App.tsx
│ ├── main.tsx
│ └── ...
├── package.json
└── README.md
- amplify/: Contains AWS Amplify backend configurations and resources.
- components/: Contains all React components used in the application.
- FeedbackModal.tsx: Component for the feedback submission modal.
- UnsupportedScreenSize.tsx: Component that displays a message when the screen width is less than 1100 pixels.
- styles/: Contains CSS files for styling the components.
- types.ts: TypeScript definitions for shared types, such as
FeedbackData
. - App.tsx: The main application component that manages state and data fetching.
- main.tsx: Entry point of the React application.
EchoType is built using React and TypeScript on the frontend and AWS Amplify for backend services. The application leverages AWS services such as DynamoDB and Lambda functions to store and process data. The architecture emphasizes modularity, scalability, and maintainability.
- Component-Based Structure: React components are organized logically to promote reusability and separation of concerns.
- State Management: Uses React hooks like
useState
,useEffect
,useMemo
, anduseCallback
for efficient state and side-effect management. - Data Fetching: Integrates with AWS Amplify to fetch data from the backend services.
- Desktop-Only Support:
- UnsupportedScreenSize Component:
- Detects the screen width and displays a message if it is less than 1100 pixels.
- Implemented using React's
useEffect
hook to listen for window resize events. - Enhances user experience by ensuring the application is used in an optimal environment.
- Integration in App.tsx:
- The application conditionally renders either the main app or the
UnsupportedScreenSize
component based on screen width.
- The application conditionally renders either the main app or the
- UnsupportedScreenSize Component:
- Feedback Submission:
- FeedbackModal Component:
- Allows users to submit feedback via a modal form.
- Validates user input and ensures data privacy compliance.
- Utilizes TypeScript interfaces (
FeedbackData
) for type safety.
- Integration in App.tsx:
- The
handleFeedbackSubmit
function processes the feedback data and sends it to the backend. - Feedback is stored in the
FeedbackData
table in DynamoDB.
- The
- FeedbackModal Component:
- Performance Optimization:
- Memoization of computations and functions to prevent unnecessary re-renders.
- Referential stability of functions and data using React hooks.
The backend is built using AWS Amplify and consists of several AWS services:
- AWS Lambda Functions: For serverless compute, handling tasks like data processing and scheduled jobs.
- AWS DynamoDB: A NoSQL database for storing book metadata, quotes, and user feedback.
- AWS Amplify: Simplifies the process of configuring AWS services and integrates them with the frontend.
amplify/
├── backend.ts
├── data/
│ └── resource.ts
└── jobs/
└── bookScrapper/
├── handler.ts
└── resource.ts
- backend.ts: The main configuration file that defines backend resources.
- data/: Contains data models and schema definitions.
- jobs/: Contains AWS Lambda functions for scheduled jobs, such as the book scraper.
import { defineBackend } from '@aws-amplify/backend';
import { data } from './data/resource';
import { bookScrapper } from './jobs/bookScrapper/resource';
export const backend = defineBackend({
data,
bookScrapper,
});
- Purpose: Defines the backend resources using AWS Amplify.
- Resources:
- data: Data models and storage configurations.
- bookScrapper: Scheduled job to populate the database with book data.
Defines the data models and schemas used in the application.
import { type ClientSchema, a, defineData } from '@aws-amplify/backend';
const schema = a.schema({
BookMetadata: a.model({
bookId: a.id().required(),
sourceId: a.integer().required(),
sourceUrl: a.string().required(),
title: a.string().required(),
author: a.string().required(),
releaseDate: a.datetime().required(),
language: a.string().required(),
license: a.string().required(),
smallQuotes: a.string().array().required(),
mediumQuotes: a.string().array().required(),
largeQuotes: a.string().array().required(),
createdAt: a.datetime().required(),
updatedAt: a.datetime().required(),
}).identifier(['bookId']),
FeedbackData: a.model({
feedbackId: a.string().required(),
userId: a.string().nullable(),
emailDestination: a.string().required(),
feedbackContent: a.string().required(),
createdAt: a.datetime().required(),
updatedAt: a.datetime().required(),
}).identifier(['feedbackId']),
}).authorization((allow) => [allow.publicApiKey()]);
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({
schema,
authorizationModes: {
defaultAuthorizationMode: 'apiKey',
apiKeyAuthorizationMode: {
expiresInDays: 30,
},
},
});
- Models:
- BookMetadata: Stores metadata and quotes for books.
- Fields:
bookId
,sourceId
,sourceUrl
,title
,author
,releaseDate
,language
,license
,smallQuotes
,mediumQuotes
,largeQuotes
,createdAt
,updatedAt
.
- Fields:
- FeedbackData: Stores user feedback submissions.
- Fields:
feedbackId
,userId
(nullable),emailDestination
,feedbackContent
,createdAt
,updatedAt
.
- Fields:
- BookMetadata: Stores metadata and quotes for books.
- Authorization:
- Allows public access using an API key (for demo purposes).
- API key is set to expire in 30 days.
- Frontend:
- FeedbackModal Component:
- Collects feedback content and ensures the user agrees to data processing.
- Generates a unique
feedbackId
using UUID. - Captures timestamps for
createdAt
andupdatedAt
. - Submits the feedback data to the
handleFeedbackSubmit
function inApp.tsx
.
- FeedbackModal Component:
- Backend:
- Data Storage:
- Feedback data is stored in the
FeedbackData
DynamoDB table. - Includes fields like
feedbackId
,userId
(set tonull
if not authenticated), andfeedbackContent
.
- Feedback data is stored in the
- Security:
- Data is transmitted securely via AWS Amplify's API.
- No personal user data is stored unless provided in the feedback content.
- Data Storage:
A scheduled AWS Lambda function that fetches book data and populates the DynamoDB table.
- Functionality:
- Fetches random book content from Project Gutenberg.
- Processes content with OpenAI GPT to generate structured book metadata and quotes.
- Stores data in DynamoDB.
- Purpose: Configures the Lambda function to run on a schedule (every 15 minutes).
- Environment Variables:
- GPT_API_SECRET: OpenAI API key.
- DYNAMODB_TABLE_NAME: DynamoDB table name.
- Timeout: Sets the function timeout to 120 seconds.
- AWS Lambda: Runs serverless functions for data processing and scheduled tasks.
- AWS DynamoDB: Stores book metadata, quotes, and user feedback.
- AWS Amplify: Orchestrates the configuration and deployment of AWS resources.
- Public API Key: For demo purposes, the application uses a public API key for accessing data.
- Environment Variables: Sensitive information like API keys are stored securely and accessed via environment variables.
- Data Privacy:
- Users must agree to data processing before submitting feedback.
- Feedback data is stored securely and only includes personal information if provided by the user.
- React with TypeScript: For building the user interface.
- AWS Amplify: For backend services, including data storage and serverless functions.
- AWS Lambda: For running serverless functions.
- AWS DynamoDB: For NoSQL database storage.
- OpenAI GPT: For generating book metadata and quotes.
- Recharts: For rendering interactive graphs and charts.
- Material-UI (MUI): For UI components and styling.
- UUID: For generating unique identifiers.
- Day.js: For date and time formatting.
- CSS: For custom styling.
- HTML5 and ES6+ JavaScript.
Contributions are welcome! Please follow these steps:
- Fork the repository.
- Create your feature branch:
git checkout -b feature/YourFeature
. - Commit your changes:
git commit -m 'Add some feature'
. - Push to the branch:
git push origin feature/YourFeature
. - Open a pull request.
Please ensure your code adheres to the project's coding standards and includes appropriate documentation and tests.
This project is licensed under the MIT License - see the LICENSE file for details.
- Project Gutenberg: The quotes and literary texts used in this application are sourced from Project Gutenberg, a library of over 70,000 free eBooks in the public domain.
- OpenAI: Utilized for generating book metadata and quotes using GPT models.
- Contributors: Thanks to all contributors who have helped improve EchoType.
For any inquiries or feedback, please contact:
- Email: idyaglev@echotype.io
- GitHub: ilya-dyaglev
Enjoy practicing your typing skills with EchoType!