# Project export: Voba

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2024
- Tagline: Helping elementary school students learn vocabulary through create-your-own-adventure stories.
- Devpost: https://devpost.com/software/voba
- GitHub: https://github.com/Tapiocaba/voba
- Demo: https://voba-stories.web.app/
- Video: https://www.youtube.com/embed/mMceEj9T85s?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 4 GitHub contributor(s) — Yuen Ler Chow (90 commits), Lisa Lin (26 commits), paula1284 (25 commits), jeremyzhang1 (21 commits)

## Devpost submission (written by the team)

### Inspiration

According to the National Assessment for Educational Progress (NAEP), ⅔ of fourth grade students are not meeting a proficient reading level. This has been the result of a combination of reduced public education funding, the impact of the COVID-19 pandemic and online earning, and the ongoing debate about the use of phonics vs. whole language for literary education. After talking to a teacher from Seattle, we identified some firsthand challenges that educators face due to this decline – a strong need for improvement in reading comprehension for proficiency in other subjects was labeled as a top concern. However, we thought that it was still important to continuously integrate technology in students’ lives, especially with many classrooms already adopting tablets and computers in class. Thus, why not take advantage of the tools of the future? With these thoughts in mind, we created Voba – a tool to make learning vocabulary fun via a choose-your-own adventure game.

### What it does

Voba is an educational tool that allows students to create their own stories based off of teacher-assigned or self-added vocabulary words. By allowing students to directly engage with storytelling, we allow them to engage more directly with the vocabulary and make every experience different. With the number of possibilities that come with every direction a story could take, it allows for unlimited fun! Voba supports 3 different learning modes: Creative Mode: This mode is a free-for-all story generation party, where the AI agent generates a starter story based on the vocabulary checklist and multiple options to continue the story with sentences that utilize the vocabulary in the list. This encourages students to actively and fearlessly try using new words while introducing unfamiliar vocabulary through the way they were meant to be used. Creative Mode: This mode is a free-for-all story generation party, where the AI agent generates a starter story based on the vocabulary checklist and multiple options to continue the story with sentences that utilize the vocabulary in the list. This encourages students to actively and fearlessly try using new words while introducing unfamiliar vocabulary through the way they were meant to be used. Test Mode: This mode employs a multiple-choice system where instead of generating sentences which ALL work, the agent will come up with 3 incorrect uses of the vocabulary and 1 correct use. If the student gets it wrong, the companion (Vovo) will help them understand why the answer was incorrect. Test Mode: This mode employs a multiple-choice system where instead of generating sentences which ALL work, the agent will come up with 3 incorrect uses of the vocabulary and 1 correct use. If the student gets it wrong, the companion (Vovo) will help them understand why the answer was incorrect. Mixed Mode: This mode combines elements of both Creative and Mixed mode. Here, we have 2 correct and 2 incorrect answers, which allows students both the ability to explore but also to understand the use of vocabulary through varied contexts. Mixed Mode: This mode combines elements of both Creative and Mixed mode. Here, we have 2 correct and 2 incorrect answers, which allows students both the ability to explore but also to understand the use of vocabulary through varied contexts. In addition to this main learning mode, we also incorporated the following to support learning and information retention: Highlighted Key Words + Definitions: In every generated sentence, the words on the vocabulary list will be highlighted. When the student hovers over it, it will show the definition of the word, helping them understand and process how it is used in that context. Highlighted Key Words + Definitions: In every generated sentence, the words on the vocabulary list will be highlighted. When the student hovers over it, it will show the definition of the word, helping them understand and process how it is used in that context. Audio: Utilizing OpenAI’s text-to-speech model, we implemented audio for every sentence so students can also hear how the word is used in the sentence. This reinforced another pillar of learning vocabulary – the auditory versions. It can also help them grasp pronunciation and tone. Audio: Utilizing OpenAI’s text-to-speech model, we implemented audio for every sentence so students can also hear how the word is used in the sentence. This reinforced another pillar of learning vocabulary – the auditory versions. It can also help them grasp pronunciation and tone. Vocabulary List View: We implemented both a ‘student’ and ‘teacher’ mode. If a student simply wants to review vocabulary words, then they can view the “vocabulary list” from their home page and click through it to see that and a definition of the word. If they click on the word, then it will say the pronunciation of the word out loud. If you are entered as a teacher, then you can add in words. Vocabulary List View: We implemented both a ‘student’ and ‘teacher’ mode. If a student simply wants to review vocabulary words, then they can view the “vocabulary list” from their home page and click through it to see that and a definition of the word. If they click on the word, then it will say the pronunciation of the word out loud. If you are entered as a teacher, then you can add in words. Vocabulary Word Review Tracking: When playing the game, the application and the AI agent will keep track of which words the student has reviewed and how often, providing both the student and the teacher (for progress tracking purposes) a way to see their progress visually. The AI Agent can also use this data to know which words to review, allowing it to focus on words that are in-need of review and bring up words that haven’t been used in a while. Vocabulary Word Review Tracking: When playing the game, the application and the AI agent will keep track of which words the student has reviewed and how often, providing both the student and the teacher (for progress tracking purposes) a way to see their progress visually. The AI Agent can also use this data to know which words to review, allowing it to focus on words that are in-need of review and bring up words that haven’t been used in a while. Mascot Companion: For each mode, we have a mascot companion to accompany the student on their adventure! Vovo the Elephant provides encouragement upon correct answers, completion of the story, and provides feedback about incorrect answers in Quiz and Mixed mode. Having a cute mascot helps put the students at ease and become more engaged in the story. Mascot Companion: For each mode, we have a mascot companion to accompany the student on their adventure! Vovo the Elephant provides encouragement upon correct answers, completion of the story, and provides feedback about incorrect answers in Quiz and Mixed mode. Having a cute mascot helps put the students at ease and become more engaged in the story. Advanced Sentence Generation: For every sentence generated, the agent can also use 1-2 words, showing the students how multiple difficult vocabulary words can be combined in a sentence. Advanced Sentence Generation: For every sentence generated, the agent can also use 1-2 words, showing the students how multiple difficult vocabulary words can be combined in a sentence. With a combination of these features, it creates a fun, seamless experience for students to learn new words and reinforce the learning. It also offers a unique take on the creative process with story generation and AI as well, as it also encourages students to learn the storytelling process!

### How we built it

Frontend: React, TailwindCSS AI: OpenAI Text-to-Speech, OpenAI GPT-4, LangChain API: FastAPI, AWS API Gateway Infrastructure / Management: AWS Lambda, AWS S3, Firebase hosting Design: Canva

### Challenges we ran into

Front-end and back-end integration: It was difficult to piece together the infrastructure, frontend, and backend components, especially with all of us working on different parts at the same time. Passing and Serving Audio Files via. API: Since none of us had ever worked with text-to-speech AIs, it was difficult to figure out the best way to ensure that the entire sentence generated got to the audio files and then sent back to the app. Prompt Generation: It’s difficult to get the correct use of the word according to the given definition, as many words have many different definitions! On top of this, we had to ensure that the AI didn’t come up with words that were too complex for a 2nd grader to understand. Lastly, we had to ensure that the story would follow a kind of “storytelling structure,” with an introduction, climax, conclusion, but still be interesting instead of formulaic.

### Accomplishments we're proud of

Two of our group members were first-time hackathon participants, so we’re really proud of how much everyone was able to contribute to both the brainstorming and implementation of the project. Each member of the team took charge of a specific part and learned something new! TLDR; we’re super proud that we built a full-stack project with multiple APIs! LangChain: None of us had ever used LangChain before, so the majority of our debugging involved LangChain issues and how we maintained the use of the vocabulary words, frequency of word use, keeping it at the appropriate level, and more. Child friendly UI design: We felt that we were able to effectively capture this! In our research, we saw that a lot of child-focused websites (i.e. National Geographic Kids, PBS Kids, etc) were very sloppily designed. We wanted to strike the balance between fun and bold but also structured. Fun!: All of us were really pleasantly surprised about how fun this entire app is, even for us as college students. It brings back a kind of nostalgia for childrens’ stories while being genuinely engaging enough for us to play around with it for hours without fail (We coincidentally got so many pirate stories. So many.) We pushed ourselves a lot out of our comfort zone with the scope of the project. Most of us only have ever had some front-end experience, so creating a full-stack project was extremely new to us, especially with 2 new hackers!

### What we learned

How to design for a specific audience – building for elementary school students is much different than building for high school / college students. A lot of the coding, colors, design, and prompt engineering had to keep our young users in mind. How to design for a specific audience – building for elementary school students is much different than building for high school / college students. A lot of the coding, colors, design, and prompt engineering had to keep our young users in mind. Everyone on the team learned a new technology, whether it’s on the back-end, front-end, or AI / infrastructure side. Everyone on the team learned a new technology, whether it’s on the back-end, front-end, or AI / infrastructure side. Effective communication and prioritization of tasks – we were extremely ambitious and had to scale and alter the idea as it developed further and we began programming. Effective communication and prioritization of tasks – we were extremely ambitious and had to scale and alter the idea as it developed further and we began programming.

### What's next

Looking ahead, we envision Voba evolving into a more comprehensive tool for students to have fun and learn vocabulary on their own and as a tool for instructors to use. Teacher Portal: A dedicated dashboard for teachers to manage classrooms, track class and student progress, assign grades, and offer reward incentives. Expanded Learning Models: We could introduce more game modes that test different things, for instance, a pure quiz mode or a ‘kid’ mode. Multiple-meaning words: Include multiple definitions for each word UI/UX Enhancements for Accessibility: Implementing research-backed strategies to help students learn, especially those with learning impediments, disabilities and more. This could involve: Expanding the audio function for blind and visually-impaired students Integration of illustrations for a more engaging story Color-blind mode, slower paced assignments, difficulty adjustments Progress Tracker + Badges: To encourage students to play, we could implement some more incentives that either a teacher could implement or a student could obtain on their own time. Saving Stories: After students have created their stories, we’d love to implement an export function to allow them to continue building on them or to share it with their friends and family!

## README (from the GitHub repository)

![logo.png](./logo.png)

# Voba

Helping elementary school students learn vocabulary through create-your-own-adventure stories. A project for Treehacks 2024.

[voba-stories.web.app/](https://voba-stories.web.app/)

## Inspiration

According to the National Assessment for Educational Progress (NAEP), ⅔ of fourth grade students are not meeting a proficient reading level. This has been the result of a combination of reduced public education funding, the impact of the COVID-19 pandemic and online earning, and the ongoing debate about the use of phonics vs. whole language for literary education. After talking to a teacher from Seattle, we identified some firsthand challenges that educators face due to this decline – a strong need for improvement in reading comprehension for proficiency in other subjects was labeled as a top concern.

However, we thought that it was still important to continuously integrate technology in students’ lives, especially with many classrooms already adopting tablets and computers in class. Thus, why not take advantage of the tools of the future? With these thoughts in mind, we created Voba – a tool to make learning vocabulary fun via a choose-your-own adventure game.

## What it does

Voba is an educational tool that allows students to create their own stories based off of teacher-assigned or self-added vocabulary words. By allowing students to directly engage with storytelling, we allow them to engage more directly with the vocabulary and make every experience different. With the number of possibilities that come with every direction a story could take, it allows for unlimited fun!

Voba supports 3 different learning modes:

1. **Creative Mode**: This mode  is a free-for-all story generation party, where the AI agent generates a starter story based on the vocabulary checklist and multiple options to continue the story with sentences that utilize the vocabulary in the list. This encourages students to actively and fearlessly try using new words while introducing unfamiliar vocabulary through the way they were meant to be used.

2. **Test Mode**: This mode employs a multiple-choice system where instead of generating sentences which ALL work, the agent will come up with 3 incorrect uses of the vocabulary and 1 correct use. If the student gets it wrong, the companion (Vovo) will help them understand why the answer was incorrect.

3. **Mixed Mode**: This mode combines elements of both Creative and Mixed mode. Here, we have 2 correct and 2 incorrect answers, which allows students both the ability to explore but also to understand the use of vocabulary through varied contexts.

In addition to this main learning mode, we also incorporated the following to support learning and information retention:

1. **Highlighted Key Words + Definitions**: In every generated sentence, the words on the vocabulary list will be highlighted. When the student hovers over it, it will show the definition of the word, helping them understand and process how it is used in that context.

2. **Audio**: Utilizing OpenAI’s text-to-speech model, we implemented audio for every sentence so students can also hear how the word is used in the sentence. This reinforced another pillar of learning vocabulary – the auditory versions. It can also help them grasp pronunciation and tone.

3. **Vocabulary List View:** We implemented both a ‘student’ and ‘teacher’ mode. If a student simply wants to review vocabulary words, then they can view the “vocabulary list” from their home page and click through it to see that and a definition of the word. If they click on the word, then it will say the pronunciation of the word out loud. If you are entered as a teacher, then you can add in words.

4. **Vocabulary Word Review Tracking**: When playing the game, the application and the AI agent will keep track of which words the student has reviewed and how often, providing both the student and the teacher (for progress tracking purposes) a way to see their progress visually. The AI Agent can also use this data to know which words to review, allowing it to focus on words that are in-need of review and bring up words that haven’t been used in a while.

5. **Mascot Companion**: For each mode, we have a mascot companion to accompany the student on their adventure! Vovo the Elephant provides encouragement upon correct answers, completion of the story, and provides feedback about incorrect answers in Quiz and Mixed mode. Having a cute mascot helps put the students at ease and become more engaged in the story.

6. **Advanced Sentence Generation**: For every sentence generated, the agent can also use 1-2 words, showing the students how multiple difficult vocabulary words can be combined in a sentence.

With a combination of these features, it creates a fun, seamless experience for students to learn new words and reinforce the learning. It also offers a unique take on the creative process with story generation and AI as well, as it also encourages students to learn the storytelling process!

## How we built it

**Frontend:** React, TailwindCSS 

**AI:** OpenAI Text-to-Speech, OpenAI GPT-4, LangChain

**API:** FastAPI, Lambda 

**Infrastructure / Management:** AWS Lambda, AWS S3, Firebase hosting

**Design:** Canva

## Challenges we ran into

**Front-end and back-end integration**: It was difficult to piece together the infrastructure, frontend, and backend components, especially with all of us working on different parts at the same time.

**Passing and Serving Audio Files via. API:** Since none of us had ever worked with text-to-speech AIs, it was difficult to figure out the best way to ensure that the entire sentence generated got to the audio files and then sent back to the app.

**Prompt Generation:** It’s difficult to get the correct use of the word according to the given definition, as many words have many different definitions! On top of this, we had to ensure that the AI didn’t come up with words that were too complex for a 2nd grader to understand. Lastly, we had to ensure that the story would follow a kind of “storytelling structure,” with an introduction, climax, conclusion, but still be interesting instead of formulaic.

## Accomplishments that we're proud of

Two of our group members were first-time hackathon participants, so we’re really proud of how much everyone was able to contribute to both the brainstorming and implementation of the project. Each member of the team took charge of a specific part and learned something new! 

1. **TLDR**; we’re super proud that we built a full-stack project with multiple APIs! 
2. **LangChain**: None of us had ever used LangChain before, so the majority of our debugging involved LangChain issues and how we maintained the use of the vocabulary words, frequency of word use, keeping it at the appropriate level, and more.
3. **Child friendly UI design**: We felt that we were able to effectively capture this! In our research, we saw that a lot of child-focused websites (i.e. National Geographic Kids, PBS Kids, etc) were very sloppily designed. We wanted to strike the balance between fun and bold but also structured. 
4. **Fun!:** All of us were really pleasantly surprised about how fun this entire app is, even for us as college students. It brings back a kind of nostalgia for childrens’ stories while being genuinely engaging enough for us to play around with it for hours without fail (We coincidentally got so many pirate stories. So many.)

We pushed ourselves a lot out of our comfort zone with the scope of the project. Most of us only have ever had some front-end experience, so creating a full-stack project was extremely new to us, especially with 2 new hackers! 

## What we learned

1. How to design for a specific audience – building for elementary school students is much different than building for high school / college students. A lot of the coding, colors, design, and prompt engineering had to keep our young users in mind. 

2. Everyone on the te

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 37 recognized source files, 81 KB.
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- AWS (technology) — claimed on Devpost, not found in the code
- FastAPI (technology) — claimed on Devpost, not found in the code
- Firebase (technology) — claimed on Devpost, not found in the code
- LangChain (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (44 of 44)

```
.firebaserc
.gitignore
api/__init__.py
api/explain_why_wrong.py
api/get_audio.py
api/get_initial_story.py
api/get_sentence_options.py
api/get_story_continue.py
api/hello.py
api/helpers/__init__.py
api/helpers/helpers.py
api/local_server.py
api/requirements.txt
firebase.json
package.json
postcss.config.js
public/index.html
public/manifest.json
public/robots.txt
README.md
src/App.js
src/components/AdventureOptions.js
src/components/ElephantPopup.js
src/components/FloatingCircles.js
src/components/Footer.js
src/components/LandingGameModes.js
src/components/Nav.js
src/components/VocabChecklist.js
src/components/VocabWords.js
src/css/App.css
src/css/ElephantPopup.css
src/css/FloatingCircles.css
src/css/index.css
src/css/landing.css
src/css/onboarding.css
src/css/StoryPage.css
src/css/Vocab.css
src/index.js
src/pages/ChooseModePage.js
src/pages/LandingPage.js
src/pages/OnboardingPage.js
src/pages/StoryPage.js
src/pages/VocabPage.js
tailwind.config.js
```

### Dependencies

- package.json: @fortawesome/fontawesome-svg-core@^6.5.1, @fortawesome/free-solid-svg-icons@^6.5.1, @fortawesome/react-fontawesome@^0.2.0, @testing-library/jest-dom@^5.17.0, @testing-library/react@^13.4.0, @testing-library/user-event@^13.5.0, autoprefixer@^10.4.17, axios@^1.6.7, jspdf@^2.5.1, postcss@^8.4.35, react@^18.2.0, react-dom@^18.2.0, react-intersection-observer@^9.8.0, react-router-dom@^6.22.1, react-scripts@^5.0.1, react-transition-group@^4.4.5, tailwindcss@^3.4.1, web-vitals@^2.1.4

### Recent commits (newest first)

- Update OpenAI temperature in helpers.py
- Update OpenAI model temperature and conclude condition***
- Fix incorrect instructions in get_sentence_options function
- Update story instructions and prompts
- Refactor story generation instructions and options
- Update OpenAI model and add line break in StoryPage
- Refactor code to improve performance and readability
- Refactor API requests to use fetch and stream response
- asd
- Update API endpoint URL in StoryPage.js
- streaming
- Fix response content in get_audio.py
- Fix encoding issue in get_audio.py
- Remove unused models
- Update import statement in explain_why_wrong.py
- Refactor API URLs
- Update API URLs and remove unused files
- Refactor API endpoint handlers
- Update API routes
- rename

## Key source files (fetched from GitHub, selected and truncated for size)

### package.json

```
{
  "name": "treehacks2024",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^6.5.1",
    "@fortawesome/free-solid-svg-icons": "^6.5.1",
    "@fortawesome/react-fontawesome": "^0.2.0",
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^1.6.7",
    "jspdf": "^2.5.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-intersection-observer": "^9.8.0",
    "react-router-dom": "^6.22.1",
    "react-scripts": "^5.0.1",
    "react-transition-group": "^4.4.5",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "autoprefixer": "^10.4.17",
    "postcss": "^8.4.35",
    "tailwindcss": "^3.4.1"
  }
}

```

### api/requirements.txt

```
��a i o h t t p = = 3 . 9 . 3  
 a i o s i g n a l = = 1 . 3 . 1  
 a n n o t a t e d - t y p e s = = 0 . 6 . 0  
 a n y i o = = 4 . 2 . 0  
 a t t r s = = 2 3 . 2 . 0  
 c e r t i f i = = 2 0 2 4 . 2 . 2  
 c h a r s e t - n o r m a l i z e r = = 3 . 3 . 2  
 c l i c k = = 8 . 1 . 7  
 c o l o r a m a = = 0 . 4 . 6  
 d a t a c l a s s e s - j s o n = = 0 . 6 . 4  
 d i s t r o = = 1 . 9 . 0  
 f a s t a p i = = 0 . 1 0 9 . 2  
 f r o z e n l i s t = = 1 . 4 . 1  
 g r e e n l e t = = 3 . 0 . 3  
 h 1 1 = = 0 . 1 4 . 0  
 h t t p c o r e = = 1 . 0 . 3  
 h t t p x = = 0 . 2 6 . 0  
 i d n a = = 3 . 6  
 j s o n p a t c h = = 1 . 3 3  
 j s o n p o i n t e r = = 2 . 4  
 l a n g c h a i n = = 0 . 1 . 7  
 l a n g c h a i n - c o m m u n i t y = = 0 . 0 . 2 0  
 l a n g c h a i n - c o r e = = 0 . 1 . 2 3  
 l a n g c h a i n - o p e n a i = = 0 . 0 . 6  
 l a n g s m i t h = = 0 . 0 . 8 7  
 m a n g u m = = 0 . 1 7 . 0  
 m a r s h m a l l o w = = 3 . 2 0 . 2  
 m u l t i d i c t = = 6 . 0 . 5  
 m y p y - e x t e n s i o n s = = 1 . 0 . 0  
 n u m p y = = 1 . 2 6 . 4  
 o p e n a i = = 1 . 1 2 . 0  
 p a c k a g i n g = = 2 3 . 2  
 p y d a n t i c = = 2 . 6 . 1  
 p y d a n t i c _ c o r e = = 2 . 1 6 . 2  
 p y t h o n - d o t e n v = = 1 . 0 . 1  
 P y Y A M L = = 6 . 0 . 1  
 r e g e x = = 2 0 2 3 . 1 2 . 2 5  
 r e q u e s t s = = 2 . 3 1 . 0  
 s n i f f i o = = 1 . 3 . 0  
 S Q L A l c h e m y = = 2 . 0 . 2 7  
 s t a r l e t t e = = 0 . 3 6 . 3  
 t e n a c i t y = = 8 . 2 . 3  
 t i k t o k e n = = 0 . 6 . 0  
 t q d m = = 4 . 6 6 . 2  
 t y p i n g - i n s p e c t = = 0 . 9 . 0  
 t y p i n g _ e x t e n s i o n s = = 4 . 9 . 0  
 u r l l i b 3 = = 2 . 2 . 0  
 u v i c o r n = = 0 . 2 7 . 1  
 y a r l = = 1 . 9 . 4  
 
```

### src/index.js

```javascript
import React from 'react';
import ReactDOM from 'react-dom/client';
import './css/index.css';
import App from './App';


const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

```

### src/App.js

```javascript
import React, { useState } from 'react';

import OnboardingPage from './pages/OnboardingPage';
import Nav from './components/Nav';
import VocabPage from './pages/VocabPage';
import StoryPage from './pages/StoryPage';
import LandingPage from './pages/LandingPage';
import ChooseModePage from './pages/ChooseModePage';
import VocabWords from './components/VocabWords';

import './css/App.css';

const App = () => {
  const [onboardingComplete, setOnboardingComplete] = useState(false);
  const [userDetails, setUserDetails] = useState({ name: '', grade: '', id: '' });
  const [currentPage, setCurrentPage] = useState('landing');
  const [mode, setMode] = useState('creative');
  const [vocabWords, setVocabWords] = useState([]);

  const handleOnboardingComplete = (name, grade) => {
    setUserDetails({ name, grade });
    setOnboardingComplete(true);
    setVocabWords(VocabWords[grade]);
    setCurrentPage('vocab'); // go to vocab once onboarding is complete
  };

  const handleContinueToMode = () => {
    setCurrentPage('chooseMode');
  };

  const setCurrentMode = (mode) => {
    setMode(mode);
    setCurrentPage('story');
  }

  // Render LandingPage if currentPage is 'landing'
  if (currentPage === 'landing') {
    return <LandingPage setCurrentPage={setCurrentPage} />;
  }

  // Render Onboarding if onboarding is not complete
  if (!onboardingComplete) {
    return <OnboardingPage onOnboardingComplete={handleOnboardingComplete} />;
  }

  // Main app content
  return (
    <div>
      <Nav setCurrentPage={setCurrentPage} />
      <div style={{ paddingTop: 150, paddingLeft: 100, paddingRight: 100 }}>
        {currentPage === 'vocab' &&
          <VocabPage
            userDetails={userDetails}
            onContinueToMode={handleContinueToMode}
            vocabWords={vocabWords}
            onChangeVocabWords={(newWords) => {
              setVocabWords(newWords);
            }
            }
          />}
        {currentPage === 'story' && <StoryPage userDetails={userDetails} mode={mode} vocabWords={vocabWords} />}
        {currentPage === 'chooseMode' && <ChooseModePage userDetails={userDetails} setCurrentMode={setCurrentMode} />}
      </div>
    </div>
  );
};

export default App;

```

### postcss.config.js

```javascript
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

```

### tailwind.config.js

```javascript
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  theme: {
    extend: {
      colors: {
        'pastel-pink': '#fddfdf',
        'pastel-green': '#cdfacc',
        'pastel-blue': '#a2d2ff',
        'pastel-yellow': '#f9e79f',
      },
    },
  },
  plugins: [
  ],
};

```

### api/hello.py

```python
from http.server import BaseHTTPRequestHandler

class handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type','text/plain')
        self.end_headers()
        self.wfile.write('Hello, world!'.encode('utf-8'))
        return

```

### api/explain_why_wrong.py

```python
from http.server import BaseHTTPRequestHandler
from urllib.parse import parse_qs, urlparse
from api.helpers.helpers import explain_why_wrong

class handler(BaseHTTPRequestHandler):
    def do_GET(self):
        # Parse query parameters
        query_components = parse_qs(urlparse(self.path).query)
        sentence = query_components.get('sentence', [None])[0]
        word = query_components.get('word', [None])[0]
        
        if sentence and word:
            # Simulate the explanation logic
            
            self.send_response(200)
            self.send_header('Content-type', 'text/plain')
            self.end_headers()
            explanation = explain_why_wrong(sentence=sentence, word=word)
            for chunk in explanation:
                self.wfile.write(chunk.encode())
                self.wfile.flush()

        else:
            self.send_response(400)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            self.wfile.write('{"detail": "Missing sentence or word parameter"}'.encode())

# Note: Adjust the import statement and uncomment the actual logic as per your setup

```

### api/get_audio.py

```python
from http.server import BaseHTTPRequestHandler
from urllib.parse import parse_qs, urlparse
from api.helpers.helpers import client

class handler(BaseHTTPRequestHandler):
    def do_GET(self):
        # Parse query parameters
        query_components = parse_qs(urlparse(self.path).query)
        audio_str = query_components.get('audio_str', [None])[0]
        
        if audio_str:
            # Simulate the audio generation logic
            # This is a placeholder for your actual audio generation logic
            response = client.audio.speech.create(
                model="tts-1",
                voice="shimmer",
                input=audio_str,
            )
            
            # Placeholder response, replace with actual response handling
            self.send_response(200)
            self.send_header('Content-type', 'audio/mpeg')
            self.end_headers()
            self.wfile.write(response.content)
        else:
            self.send_response(400)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            self.wfile.write('{"detail": "Missing audio_str parameter"}'.encode())


```

### api/get_initial_story.py

```python
from http.server import BaseHTTPRequestHandler
from urllib.parse import parse_qs, urlparse
from api.helpers.helpers import get_story_start  # Ensure this path is correct based on your project structure

class handler(BaseHTTPRequestHandler):
    def do_GET(self):
        # Parse query parameters
        query_components = parse_qs(urlparse(self.path).query)
        vocab_list = query_components.get('vocab_list', [None])[0]
        mode = query_components.get('mode', [None])[0]
        
        # Validate and process the request
        if mode in ["creative", "test", "mixed"] and vocab_list is not None:
            
            self.send_response(200)
            self.send_header('Content-type', 'text/plain')
            self.end_headers()

            story = get_story_start(vocab_list=vocab_list, mode=mode)
            
            for chunk in story:
                self.wfile.write(chunk.encode())
                self.wfile.flush()

        else:
            self.send_response(400)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            self.wfile.write('{"detail": "Error: Invalid mode provided or missing vocab_list"}'.encode())

```

[26 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]