# Project export: Storyscape

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: Cal Hacks 11.0
- Tagline: We brought choose your own adventure back! In the form of guided text adventures, Storyscape enables elementary and middle school students to learn the English language the way they want.
- Devpost: https://devpost.com/software/storyscape
- GitHub: https://github.com/catfeeshing/storyscape
- Demo: https://storyscape.courses/
- Result: winner (Google: Most creative app)
- Team: 3 GitHub contributor(s) — airwuu (35 commits), Carolyn Cui (23 commits), Tejas Bhartiya (3 commits)

## Devpost submission (written by the team)

### Inspiration

All our team members enjoy reading as a hobby across numerous genres. Unfortunately, reading comprehension and literacy overall have been declining, which poses a massive problem for future generations. There are countless factors at play here, and we can't solve all of them, but we can definitely work to kindle a spark that might just blossom into a love for reading. Many of these adjacent tools are made for classroom settings. On the contrary, we're built for students, by students, and by readers, for readers.

### What it does

Storyscape is an application aimed at developing elementary and middle schoolers' grasp over the English language. Turn on your mic and get ready to read some words! To be specific, we have identified three core skills to be problematic: diction, sentence structure variety, and expressiveness. You will be given an unlimited amount of examples for each of these and the opportunity to practice and replicate these examples. With the help of our cat assistant, you can learn how to read passages expressively and eloquently!

### How we built it

Storyscape is built on five major technologies: Google Gemini Flash -- speedy, cost-efficient, great at storytelling Hume AI -- personable, easy to integrate TTS, and great for sentiment analysis React/Next.js -- a popular JS framework that simplifies many best practices built for vercel Vercel -- easy deployment to the web Firebase -- a handy tool for auth, functions, storage and analytics

### Challenges we ran into

One major problem we faced during the competition was the cold weather at night. We struggled to get some quality sleep due to the lack of comfortable sleeping arrangements :(

### Accomplishments we're proud of

We would actually use this app ourselves after some minor improvements! Created a polished and aesthetically pleasing web app demonstrating AI technologies Stayed up 24 hours in a row

### What we learned

This hackathon was a great opportunity to learn about all the different AI technologies that are out there and how we can implement them into our lives. We learned about sentiment analysis, some handy prompt engineering, and some techniques to interface with AI in a smart way.

### What's next

We're still working on adding themes into the text adventures. With better prompt engineering and utilisation of the best models to foster a closer connection to the text, Storyscape can become a true companion for those who want to augment their English skills.

## README (from the GitHub repository)

<div align="center">
<h1>Storyscape</h1>
    <a href="https://github.com/catfeeshing/storyscape/blob/main/LICENSE.txt"><img alt="GitHub license" src="https://img.shields.io/github/license/catfeeshing/storyscape?color=ff69b4&style=for-the-badge"></a>
    <a href="https://github.com/catfeeshing/storyscape/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/catfeeshing/storyscape?color=yellow&label=Project%20Stars&style=for-the-badge"></a>
  <a href="https://github.com/catfeeshing/storyscape/stargazers"><img alt="hackberkeley" src="https://img.shields.io/badge/Submitted:-Calhacks 11-blue?color=blue&label=Submitted%20To&style=for-the-badge"></a>
</div>
<div align="center">
    <a href="" target="_blank">
        <img src="https://github.com/user-attachments/assets/d12c10cf-4b49-4ed2-818f-0f98c308e583" 
        alt="Logo" width="" height="">
    </a>
</div>

## About
<img src="https://github.com/user-attachments/assets/db9ed1ee-e8d6-4199-ad74-6ae8f124766b" 
        alt="Logo" width="32%" height="30%">
<img src="https://github.com/user-attachments/assets/8071f4dc-9893-4704-8693-c9244e73bc59" 
        alt="Logo" width="32%" height="30%">
<img src="https://github.com/user-attachments/assets/ceb41778-71eb-4313-9b2c-f1d39320a880" 
        alt="Logo" width="32%" height="30%">

Storyscape is an application aimed at developing elementary and middle schoolers' grasp over the English language. Turn on your mic and get ready to read some words! 

To be specific, we have identified three core skills to be problematic: **diction, sentence structure variety, and expressiveness.** 
- Using Google Gemini's AI prompts, kids have an unlimited amount of themes to interact and learn from. 
- Hume's Semantic AI technologies determine user's tone, expressiveness, and evaluates reader comprehension!
## Inspiration
All our team members enjoy reading as a hobby across numerous genres, with some fond core memories about interactive "Choose your own adventure" type narratives. Unfortunately, reading comprehension and literacy overall have been declining, which poses a massive problem for future generations. There are countless factors at play here, and we can't solve all of them, but we can definitely work to kindle a spark that might just blossom into a love for reading. Many of these adjacent tools are made for classroom settings. 

On the contrary, we're built for students, by students, and by readers, for readers. We aim to bring interactivity and excitement back to reading for any in need of an opportunity to better their reading skills.

## How we built it
Storyscape is built on five major technologies:

1. Google Gemini Flash -- speedy, cost-efficient, great at storytelling
2. Hume AI -- personable, easy to integrate TTS, and great for sentiment analysis
3. React/Next.js -- a popular JS framework that simplifies many best practices built for vercel
4. Vercel -- easy deployment to the web
5. Firebase -- a handy tool for auth, functions, storage and analytics

## Challenges 
The majority of our challenges were mostly due to the fact that this project was completely created during a hackathon. Best practices in code and version management were forgone in favor of speed and "hackiness". This resulted in some questionable merges and confusing version control.
Another problem we faced during the competition was the cold weather at night. We struggled to get some quality sleep due to the lack of comfortable sleeping arrangements :(


## Detected evidence (automated analysis)

Indexed codebase: 40 recognized source files, 68 KB.
- CSS (language) — detected in the code
- Firebase (technology) — detected in the code
- Google Gemini (technology) — detected in the code
- JavaScript (language) — detected in the code
- Next.js (technology) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- HTML (language) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (47 of 47)

```
.gitignore
app/easy/layout.tsx
app/easy/page.tsx
app/easy/testpage.txt
app/error.tsx
app/hard/layout.tsx
app/hard/page.tsx
app/layout.tsx
app/levels/layout.tsx
app/levels/page.tsx
app/medium/layout.tsx
app/medium/page.tsx
app/page.tsx
app/providers.tsx
app/shelf/layout.tsx
app/shelf/page.tsx
components/ClientComponent.tsx
components/Controls.tsx
components/gemini.ts
components/icons.tsx
components/levelCard.tsx
components/login.tsx
components/Message.tsx
components/navbar.tsx
components/primitives.ts
components/prompt.tsx
components/theme-switch.tsx
components/user.tsx
config/fonts.ts
config/site.ts
fe/components/Message.tsx
firebase/firebase_barebones copy.ts
firebase/firebase_og.ts
firebase/firebase.ts
LICENSE
next-env.d.ts
next.config.js
next.config.mjs
package.json
postcss.config.js
postcss.config.mjs
README.md
styles/globals.css
tailwind.config.js
tailwind.config.ts
tsconfig.json
types/index.ts
```

### Dependencies

- package.json: @google/generative-ai@^0.21.0, @humeai/voice-react@^0.1.16, @nextui-org/button@2.0.38, @nextui-org/card@^2.0.34, @nextui-org/code@2.0.33, @nextui-org/input@2.2.5, @nextui-org/kbd@2.0.34, @nextui-org/link@2.0.35, @nextui-org/listbox@2.1.27, @nextui-org/navbar@2.0.37, @nextui-org/react@^2.4.8, @nextui-org/snippet@2.0.43, @nextui-org/switch@2.0.34, @nextui-org/system@2.2.6, @nextui-org/theme@2.2.11, @react-aria/ssr@3.9.4, @react-aria/visually-hidden@3.8.12, @types/node@20.5.7, @types/react@18.3.3, @types/react-dom@18.3.0, @typescript-eslint/eslint-plugin@7.2.0, @typescript-eslint/parser@7.2.0, autoprefixer@10.4.19, clsx@2.1.1, dotenv@^16.4.5, eslint@^8.57.0, eslint-config-next@14.2.1, eslint-config-prettier@^8.2.0, eslint-plugin-import@^2.26.0, eslint-plugin-jsx-a11y@^6.4.1, eslint-plugin-node@^11.1.0, eslint-plugin-prettier@^5.1.3, eslint-plugin-react@^7.23.2, eslint-plugin-react-hooks@^4.6.0, eslint-plugin-unused-imports@^3.2.0, firebase@^10.14.1, framer-motion@~11.1.1, intl-messageformat@^10.5.0, next@14.2.15, next-themes@^0.2.1, postcss@8.4.38, react@18.3.1, react-dom@18.3.1, react-firebase-hooks@^5.1.1, tailwind-variants@0.1.20, tailwindcss@3.4.3, typescript@5.0.4

### Recent commits (newest first)

- Merge branch 'main' of https://github.com/catfeeshing/storyscape
- theme retrieval wip
- Update page.tsx
- add title
- Update README.md
- Update README.md
- testing stuff
- stuff like homepage
- Merge branch 'main' of https://github.com/catfeeshing/storyscape
- redirect and window reload thing idk
- yuh
- yolo
- Merge branch 'main' of https://github.com/catfeeshing/storyscape
- yolo
- gg
- Merge branch 'main' of https://github.com/catfeeshing/storyscape
- shelf size
- Merge branch 'main' of https://github.com/catfeeshing/storyscape
- yes
- attempt

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

### package.json

```
{
	"name": "next-app-template",
	"version": "0.0.1",
	"private": true,
	"scripts": {
		"dev": "next dev --turbo",
		"build": "next build",
		"start": "next start",
		"lint": "eslint . --ext .ts,.tsx -c .eslintrc.json --fix"
	},
	"dependencies": {
		"@google/generative-ai": "^0.21.0",
		"@humeai/voice-react": "^0.1.16",
		"@nextui-org/button": "2.0.38",
		"@nextui-org/card": "^2.0.34",
		"@nextui-org/code": "2.0.33",
		"@nextui-org/input": "2.2.5",
		"@nextui-org/kbd": "2.0.34",
		"@nextui-org/link": "2.0.35",
		"@nextui-org/listbox": "2.1.27",
		"@nextui-org/navbar": "2.0.37",
		"@nextui-org/react": "^2.4.8",
		"@nextui-org/snippet": "2.0.43",
		"@nextui-org/switch": "2.0.34",
		"@nextui-org/system": "2.2.6",
		"@nextui-org/theme": "2.2.11",
		"@react-aria/ssr": "3.9.4",
		"@react-aria/visually-hidden": "3.8.12",
		"clsx": "2.1.1",
		"dotenv": "^16.4.5",
		"firebase": "^10.14.1",
		"framer-motion": "~11.1.1",
		"intl-messageformat": "^10.5.0",
		"next": "14.2.15",
		"next-themes": "^0.2.1",
		"react": "18.3.1",
		"react-dom": "18.3.1",
		"react-firebase-hooks": "^5.1.1"
	},
	"devDependencies": {
		"@types/node": "20.5.7",
		"@types/react": "18.3.3",
		"@types/react-dom": "18.3.0",
		"@typescript-eslint/eslint-plugin": "7.2.0",
		"@typescript-eslint/parser": "7.2.0",
		"autoprefixer": "10.4.19",
		"eslint": "^8.57.0",
		"eslint-config-next": "14.2.1",
		"eslint-config-prettier": "^8.2.0",
		"eslint-plugin-import": "^2.26.0",
		"eslint-plugin-jsx-a11y": "^6.4.1",
		"eslint-plugin-node": "^11.1.0",
		"eslint-plugin-prettier": "^5.1.3",
		"eslint-plugin-react": "^7.23.2",
		"eslint-plugin-react-hooks": "^4.6.0",
		"eslint-plugin-unused-imports": "^3.2.0",
		"postcss": "8.4.38",
		"tailwind-variants": "0.1.20",
		"tailwindcss": "3.4.3",
		"typescript": "5.0.4"
	}
}

```

### types/index.ts

```typescript
import { SVGProps } from "react";

export type IconSvgProps = SVGProps<SVGSVGElement> & {
  size?: number;
};

```

### app/layout.tsx

```typescript
import "@/styles/globals.css";
import { Metadata, Viewport } from "next";
import { Link } from "@nextui-org/link";
import clsx from "clsx";

import { Providers } from "./providers";

import { siteConfig } from "@/config/site";
import { fontSans } from "@/config/fonts";
import { Navbar } from "@/components/navbar";

export const metadata: Metadata = {
  title: {
    default: siteConfig.name,
    template: `%s - ${siteConfig.name}`,
  },
  description: siteConfig.description,
  icons: {
    icon: "/favicon.ico",
  },
};

export const viewport: Viewport = {
  themeColor: [
    { media: "(prefers-color-scheme: light)", color: "white" },
    { media: "(prefers-color-scheme: light)", color: "white" },
  ],
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html suppressHydrationWarning lang="en">
      <head />
      <body
        className={clsx(
          "min-h-screen bg-background font-sans antialiased overflow-hidden",
          fontSans.variable,
        )}
      >
        <Providers themeProps={{ attribute: "class", defaultTheme: "light" }}>
          <div className="relative flex flex-col h-screen">
            <Navbar />
            <main className="container mx-auto max-w-7xl pt-16 px-6 flex-grow">
              {children}
            </main>
            <footer className="w-full flex items-center justify-center py-3">
    
            </footer>
          </div>
        </Providers>
      </body>
    </html>
  );
}

```

### app/page.tsx

```typescript
import {Image} from "@nextui-org/image";
export default function Home() {
  return (
    <section className="flex flex-col items-center justify-center gap-4 py-8 md:py-10">
      {/* <h1>welcome to storyscape!</h1> */}
      {/* <div style={{backgroundImage: "url('htty-40 bg-center fixed inset-0 "></div> */}
     <div className="fixed inset-0 justify-center align-middle items-end opacity-50 z-[0]" >
      <Image
      alt="NextUI hero Image"
      src="https://images-ext-1.discordapp.net/external/wEQRfhDXRyLu5HGFlLBBK_9tY3qFY7gKZbrTHrKlNeg/https/cdn.vectorstock.com/i/500p/07/91/fantasy-land-horizontal-background-grass-hills-vector-52000791.jpg?format=webp&width=1226&height=730"
      width={10000}
      className="" 
    />
    </div>

    {/* <div className="flex items-left justify-left"> */}
      {/* left rectangle */}
      <div className="absolute inset-20 w-1/2 h-300 bg-gradient-to-r from-slate-200 to-white-200 opacity-70 p-40 rounded-3xl">
      <h1 className="text-6xl font-bold text-slate z+5">welcome to storyscape!</h1>
      <br></br>
      <p className="text-2xl font-medium text-slate z+5">exploring your words and your world through text. <br></br> learn the english you want, however you want!</p>
      <br></br>
      <button className="bg-slate-500 text-white p-4 rounded-lg z+5"><a href="/levels">begin your adventure</a></button>
      <br></br>
      <br></br>
      <p><b>featuring:</b></p>
      <ul>
        <li> - three different levels of difficulty </li>
        <li> - personal glossary to track your adventures </li>
        <li> - customize your text adventures </li>
      </ul>
    </div>

    {/* hero image */}
    <div className=" inset-0 justify-center align-middle items-end" >
      <Image
      alt="NextUI hero Image"
      src="https://media.discordapp.net/attachments/1296711558868762687/1297524375914020986/IMG_8108.png?ex=67163d3e&is=6714ebbe&hm=892d5283d1220cdc05d2b3454b18f522ebb2ee9200b7b5b1f9ae6b68eb6ce133&=&format=webp&quality=lossless&width=541&height=778"
      width={10000}
      className="origin-bottom-right rotate-6 translate-x-64 translate-y-10 transform w-[500px]" 
    />
    </div>
      
    </section>
    
  );
}

```

### app/levels/layout.tsx

```typescript
export default function BlogLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <section className="flex flex-col items-center justify-center gap-4">
      <div className="inline-block text-center justify-center w-full">
        {children}
      </div>
    </section>
  );
}

```

### app/easy/layout.tsx

```typescript
export default function AboutLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <section className="flex flex-col items-center justify-center gap-4">
      <div className="inline-block max-w-lg text-center justify-center">
        {children}
      </div>
    </section>
  );
}

```

### app/medium/layout.tsx

```typescript
export default function DocsLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <section className="flex flex-col items-center justify-center gap-4">
      <div className="inline-block max-w-3xl text-center justify-center">
        {children}
      </div>
    </section>
  );
}

```

### app/shelf/layout.tsx

```typescript
export default function AboutLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <section className="flex flex-col items-center justify-center gap-4">
      <div className="inline-block max-w-lg text-center justify-center">
        {children}
      </div>
    </section>
  );
}

```

### app/hard/layout.tsx

```typescript
export default function BlogLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
      <section className="flex flex-col items-center justify-center gap-4">
        <div className="inline-block max-w-3xl text-center justify-center">
          {children}
        </div>
      </section>
  );
}

```

### app/hard/page.tsx

```typescript
import { title } from "@/components/primitives";
import Prompt from '@/components/prompt'
import { fetchAccessToken } from "hume";


export default async function BlogPage() {
  const accessToken = await fetchAccessToken({

    apiKey: String(process.env.HUME_API_KEY),

    secretKey: String(process.env.HUME_SECRET_KEY),

    
  });
  if (!accessToken) {

    throw new Error();

  }
  return (

    <div className="flex transition-all ease-in-out">
      {/* ugly implementation of background */}
      
      <div className="z-40 text-black font-serif">
        <div className="animate-float"><div className="h-4 -rotate-[12deg] transform translate-x-[370px] translate-y-[140px] origin-bottom-right rounded-sm font-extrabold text-9xl">”</div></div>
        <div className="animate-float2"><div className="h-4 rotate-[10deg] transform translate-x-[-400px] translate-y-[100px] origin-bottom-right rounded-sm font-extrabold text-9xl">“</div></div>
        
        <div className=" p-4 pb-4 px-8 rounded-3xl bg-gradient-to-b from-white to-red-100 ">
        <Prompt token={accessToken} colors={["from-pink-500", "to-red-300"]} mode="hard" proompt="give me a paragraph" instruction="You are part of a web app that teaches kids from 1st grade through middle school how to read! Specifically, you are generating 20-30 word paragraphs in this age range. When told \\\'Give me a paragraph!\\\', you will generate exactly one paragraph that a 6th-8th grader might want to learn. Use harder English that an middle schooler could understand! Don't use markdown. No asterisks. Don't use words that are too big either. We encourage you to pull from existing teen literature in the public domain."/>

          <footer className="absolute text-3xl text-slate-600 left-6 bottom-6 ">Hard</footer>   
        </div>
      </div>
      
      <div className=""></div>
      <div className="absolute inset-0 bg-gradient-to-b from-red-200 to-white z-0"/>
      

    </div>
  );
}

```

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