# Project export: Study.AI

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: CruzHacks 2024
- Tagline: A comprehensive AI-powered study website where you can turn your notes into test questions, flashcards, and more!
- Devpost: https://devpost.com/software/studyai-ay8we0
- GitHub: https://github.com/briankhoi/cruzhacks24/
- Team: 4 GitHub contributor(s) — Brian (24 commits), Anderson Compalas (5 commits), alisunnyday (4 commits), Keith Zhou (2 commits)

## Devpost submission (written by the team)

### Inspiration

We were inspired by study platforms like Quizlet and Pomodoro timers, and wanted to come together to create our dream website that combined all their great functionalities!

### What it does

StudyAI is a comprehensive study platform where you can schedule to-dos, time-block your studying with Pomodoro timers, and upload your notes to receive custom, AI-powered practice questions and flashcards.

### How we built it

We utilized MongoDB Atlas, Google's Gemini API, ExpressJS, Node.js, and Auth0 for the backend. Our frontend was designed with ReactJS, CSS, and SCSS.

### Challenges we ran into

We all came in not knowing how to use MongoDB/MongoDB Atlas or APIs, and two of our group came in not knowing how to use ReactJS, so we had to learn how to use these on the fly within our limited timeframe. Moreover, it's our first time developing a full-stack app, so managing things between both ports involved a learning curve.

### Accomplishments we're proud of

We all communicated very well in regards to project roles, timelines, and expectations. Additionally, we're committed to learning the material and working together to make a polished final product.

### What we learned

Our group members all came out of this experience having learned something new: whether it be website design, working with APIs, or staying awake for long hours!

### What's next

for StudyAI In the near future, we hope to round out our database query functionalities and further polish the UI. Looking to the future, we hope to improve our AI capabilities to help a broader range of students reach their academic goals.

## README (from the GitHub repository)

project name here

credits
alison sun
brian nguyen
anderson compalas
keith zhou


## Detected evidence (automated analysis)

Indexed codebase: 25 recognized source files, 80 KB.
- CSS (language) — detected in the code
- Express (technology) — detected in the code
- Google Gemini (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- MongoDB (technology) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- Node.js (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (41 of 41)

```
.DS_Store
client/.gitignore
client/package.json
client/postcss.config.js
client/public/index.html
client/public/manifest.json
client/public/pdf.worker.mjs
client/public/robots.txt
client/README.md
client/src/App.js
client/src/components/askbard.css
client/src/components/askbard.js
client/src/components/bardtest.js
client/src/components/flashcards.js
client/src/components/flashcards.scss
client/src/components/generateModal.js
client/src/components/generatemodal.scss
client/src/components/navbar.css
client/src/components/navbar.js
client/src/components/navbar.scss
client/src/components/notesmodal.js
client/src/components/notesmodal.scss
client/src/components/quiz.js
client/src/components/studyportal.js
client/src/components/studyportal.scss
client/src/components/timer.css
client/src/components/timer.js
client/src/components/todo.css
client/src/components/todo.js
client/src/index.js
client/src/pages/home.css
client/src/pages/home.js
client/src/pages/home.scss
client/tailwind.config.js
package.json
README
server/.gitignore
server/db/conn.js
server/package.json
server/routes/record.js
server/server.js
```

### Dependencies

- client/package.json: @auth0/auth0-react@^2.2.4, @testing-library/jest-dom@^5.17.0, @testing-library/react@^13.4.0, @testing-library/user-event@^13.5.0, autoprefixer@^10.4.17, bootstrap@^5.3.2, flowbite-react@^0.7.2, pdfjs-dist@^4.0.379, postcss@^8.4.33, react@^18.2.0, react-bootstrap@^2.10.0, react-dom@^18.2.0, react-router-dom@^6.21.3, react-scripts@5.0.1, sass@^1.70.0, tailwindcss@^3.4.1, web-vitals@^2.1.4
- package.json: @auth0/auth0-react@^2.2.4, @google/generative-ai@^0.1.3, express@^4.18.2, express-openid-connect@^2.17.1, react-pdf@^7.7.0
- server/package.json: cors@^2.8.5, dotenv@^16.3.2, express@^4.18.2, mongodb@4.0

### Recent commits (newest first)

- dashboard format, brief ui restyle of generate modal
- merge
- dashboard rework
- notemodal
- finished stitching dashboard
- gpt ui fixed
- border
- stitch + merge conflict
- resolved merge conflicts and stitch home
- alison final
- timer component
- quiz menu
- work on notes modal
- other todo fixes
- flashcard system
- mongodb updates for quiz and flashcards working
- wired gemini output to mongodb doc
- Update README
- Merge branch 'main' of https://github.com/briankhoi/cruzhacks24
- alison todo stylin

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

### package.json

```
{
  "dependencies": {
    "@auth0/auth0-react": "^2.2.4",
    "@google/generative-ai": "^0.1.3",
    "express": "^4.18.2",
    "express-openid-connect": "^2.17.1",
    "react-pdf": "^7.7.0"
  }
}

```

### server/package.json

```
{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "dotenv": "^16.3.2",
    "express": "^4.18.2",
    "mongodb": "4.0"
  }
}

```

### client/package.json

```
{
  "name": "client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@auth0/auth0-react": "^2.2.4",
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "autoprefixer": "^10.4.17",
    "bootstrap": "^5.3.2",
    "flowbite-react": "^0.7.2",
    "pdfjs-dist": "^4.0.379",
    "postcss": "^8.4.33",
    "react": "^18.2.0",
    "react-bootstrap": "^2.10.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.21.3",
    "react-scripts": "5.0.1",
    "sass": "^1.70.0",
    "tailwindcss": "^3.4.1",
    "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"
    ]
  }
}

```

### server/server.js

```javascript
const express = require("express");
const app = express();
const cors = require("cors");
require("dotenv").config({ path: "./config.env" });
const port = process.env.PORT || 5000;
const { MongoClient } = require("mongodb");

// enable cors to allow requests from the client
app.use(cors({
  origin: "http://localhost:3000",
  credentials: true,
}));
app.use(express.json());

const Db = process.env.ATLAS_URI;
const client = new MongoClient(Db, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

let usersCollection;

client.connect(err => {
  if (err) console.error(err);
  console.log("Connected to MongoDB");
  const db = client.db("study");
  usersCollection = db.collection("users");
});

// for oauth0
const { auth } = require("express-openid-connect");

const config = {
  authRequired: false,
  auth0Logout: true,
  secret: process.env.AUTH_SECRET,
  baseURL: "http://localhost:5000",
  clientID: process.env.CLIENT_ID,
  issuerBaseURL: process.env.BASE_URL,
  afterCallback: (req, res, session, state) => {
    return {
      ...session,
      returnTo: "/home",
    };
  },
};

// auth router attaches /login, /logout, and /callback routes to the baseURL
app.use(auth(config));

// req.isAuthenticated is provided from the auth router
app.get("/", (req, res) => {
  res.redirect("http://localhost:3000/home");
});

// send info back to client regarding auth state of user
app.get("/api/user", async (req, res) => {
  if (req.oidc.isAuthenticated()) {
    const user = req.oidc.user;
    const existingUser = await usersCollection.findOne({ sub: user.sub });
    if (!existingUser) {
      // User does not exist, create a new user
      await usersCollection.insertOne(user);
    }
    res.json({
      isAuthenticated: true,
      user: user,
    });
  } else {
    res.json({
      isAuthenticated: false,
    });
  }
});

// add new flashcard to user document in mongodb
app.post("/api/user/update/flashcard", async (req, res) => {
    const { sub, flashcard } = req.body;
    const user = await usersCollection.findOneAndUpdate(
      { sub: sub },
      { $push: { flashcard: flashcard } },
      { new: true, useFindAndModify: false }
    );
    res.json(user);
});

// add new quiz to user document in mongodb
app.post("/api/user/update/quiz", async (req, res) => {
    const { sub, quiz } = req.body;
    const user = await usersCollection.findOneAndUpdate(
      { sub: sub },
      { $push: { quizzes: quiz } },
      { new: true, useFindAndModify: false }
    );
    res.json(user);
});

app.get('/logout', (req, res) => {
  req.session.destroy();
  res.clearCookie('connect.sid');
  // redirect to homepage after logout
  res.redirect("http://localhost:3000/home");
});

app.listen(port, () => {
  console.log(`Server is running on port: ${port}`);
});

app.use((req, res, next) => {
    res.set('Cache-Control', 'no-store')
    next()
  })
```

### client/src/index.js

```javascript
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
// import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import { Auth0Provider } from "@auth0/auth0-react";
import 'bootstrap/dist/css/bootstrap.min.css';

const root = document.getElementById('root');
ReactDOM.createRoot(root).render(
  <BrowserRouter>
    <Auth0Provider
      domain={process.env.REACT_APP_AUTH0_DOMAIN}
      clientId={process.env.REACT_APP_AUTH0_CLIENT_ID}
      authorizationParams={{
        redirect_uri: window.location.origin
      }}
    >
      <App />
    </Auth0Provider>
  </BrowserRouter>
);

```

### client/src/App.js

```javascript
import React from "react";
// We use Route in order to define the different routes of our application
import { Route, Routes } from "react-router-dom";
 // We import all the components we need in our app
import Bardtest from "./components/bardtest";
import HomePage from "./pages/home";
// import AuthPage from "./pages/auth";

 const App = () => {
 return (
   <div>
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
      integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM"
      crossorigin="anonymous"
    />
     {/* <Navbar /> */}
     <Routes>
       <Route exact path="/" element={<HomePage />} />
       <Route exact path="/callback" element={<HomePage />} />
       <Route exact path="/home" element={<HomePage />} />
       <Route exact path="/bard" element={<Bardtest />} />
     </Routes>
   </div>
 );
};
 export default App;
```

### client/postcss.config.js

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

```

### client/tailwind.config.js

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./src/**/*.{js,jsx,ts,tsx}',
  'node_modules/flowbite-react/lib/esm/**/*.js',
  ],
  theme: {
    extend: {},
  },
  plugins: [
    require('flowbite/plugin'),
  ],
};
```

### server/db/conn.js

```javascript
const { MongoClient } = require("mongodb");
const Db = process.env.ATLAS_URI;
const client = new MongoClient(Db, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});
 
var _db;
 
module.exports = {
  connectToServer: function (callback) {
    client.connect(function (err, db) {
      // Verify we got a good "db" object
      if (db)
      {
        _db = db.db("employees");
        console.log("Successfully connected to MongoDB."); 
      }
      return callback(err);
         });
  },
 
  getDb: function () {
    return _db;
  },
};
```

### client/public/index.html

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/icon.png" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="AI study website"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/icon.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>study.ai | Study efficiently with the power of AI!</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

```

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