# Project export: Deeper Connections

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: An interactive therapy tool in your pocket!
- Devpost: https://devpost.com/software/deeper-connections
- GitHub: https://github.com/armitakatarapu/Deeper-Connections
- Video: https://www.youtube.com/embed/UXVyfS0vV2M?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 3 GitHub contributor(s) — agampa27 (49 commits), Rajeev Raghuram (30 commits), armitakatarapu (29 commits)

## Devpost submission (written by the team)

### Inspiration

In today's world, the mental health crisis is on the rise, and finding a therapist has become increasingly difficult due to factors like the economy, accessibility, and finding the right fit. We believe everyone should have the opportunity to overcome their mental health challenges and have meaningful companions to rely on. Through the EVI (Empathic Voice Interface) model on Vercel, individuals are provided a safe space to express themselves without fear. Our mission is to empower people to openly share their thoughts and navigate through their mental health challenges, all for free, with just a click.

### What it does

Our project is a comprehensive mental health support system that includes our AI-powered therapy bot, user authentication, and personalized user profiles. By training Hume.ai's Empathic Voice Interface (EVI) with in-context learning and integrating the model into Vercel, we enable users to have meaningful conversations with the AI and work through their mental health challenges, getting advice, companionship, and more. Additionally, users can sign up or log in to create a profile that includes their personal information and emergency contacts, and our system ensures that all interactions are securely managed within the platform.

### How we built it

We gathered real-life therapist conversations. From there, we integrated a GPT 4-mini Hume AI model, training it with various real-world examples of therapist conversations with patients, understanding how they are feeling based on their tone and the way they are talking (sentiment analysis) and being able to provide them with the necessary advice they are looking for. We also altered the temperature to give them more specific responses to their particular questions but also allowed them to express themselves openly. For the front end, we first attempted to use React Native and Javascript before finally deciding to do HTML/CSS and Javascript to create a responsive and user-friendly website. After that, we needed database integration for the user authentication in which we attempted to use MongoDB, but we decided to utilize API localStorage. This setup allowed us to keep the front end lightweight while efficiently managing data from the backend database.

### Challenges we ran into

We encountered significant challenges connecting the front and back end, particularly establishing smooth communication between the two, which was more difficult than anticipated. While inputting our Hume AI into an HTML file, the HTML file was not able to capture the voice feature of Hume AI. To fix this, we deployed the model into a vercel app and implemented a link to the app in the HTML file. On the front-end side, we struggled with setting up a database for user authentication. Initially, we used MongoDB, but after facing connection issues, we had to explore alternative database solutions such as the API localStorage. What we learned &

### Accomplishments we're proud of

During this project, we gained hands-on experience tackling the mental health crisis and integrating AI tools into existing systems. We learned the importance of adaptability, especially when transitioning from MongoDB to other database solutions for user authentication. Additionally, we improved our skills in debugging, API development, and managing the interaction between the front end and back end. We’re proud of our resilience in the face of technical hurdles, git overwrites, and our ability to pivot when necessary. Despite these challenges, we successfully delivered a working solution, which is a major accomplishment for our team.

### What's next

In the future, to enhance the AI model's functionality, we can implement a system to flag trigger words during conversations with users. This feature would integrate with the emergency contact information from the "My Connections" page, adding an extra layer of protection as we tackle mental health crises.

## README (from the GitHub repository)

# Deeper-Connections
*An interactive therapy tool* 


## Detected evidence (automated analysis)

Indexed codebase: 29 recognized source files, 218 KB.
- CSS (language) — detected in the code
- Express (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- MongoDB (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code

## Codebase structure (from repository index)

### Files (36 of 36)

```
.gitignore
about.html
chatbot_model.ts
components.json
config.json
deeper-connections/.gitignore
deeper-connections/index.html
deeper-connections/package.json
deeper-connections/src/counter.ts
deeper-connections/src/main.ts
deeper-connections/src/style.css
deeper-connections/tsconfig.json
evi.html
eviPop.js
home.html
humeai.ts
index.html
interaction.html
login/login.css
login/login.html
login/login.js
myconnections.html
next-env.d.ts
package.json
pmp-lock.yaml
postcss.config.mjs
README.md
script.js
scriptConnect.js
server.js
sign.css
signIn.html
styles.css
styles1.css
utils/expressionColors.ts
vite.config.js
```

### Dependencies

- deeper-connections/package.json: hume@^0.15.16, typescript@~6.0.2, vite@^8.0.4
- package.json: @humeai/voice-react@^0.1.15, @radix-ui/react-slot@^1.0.2, @radix-ui/react-switch@^1.0.3, @radix-ui/react-toggle@^1.0.3, @types/node@^20, @types/react@^18, @types/react-dom@^18, @types/react-virtualized@^9.21.30, bcryptjs@^3.0.3, class-variance-authority@^0.7.0, clsx@^2.1.1, cors@^2.8.6, dotenv@^17.4.1, eslint@^8, eslint-config-next@14.2.3, express@^5.2.1, framer-motion@^11.2.10, geist@^1.3.0, hume@^0.8.10, jsonwebtoken@^9.0.3, lucide-react@^0.394.0, mongoose@^9.4.1, postcss@^8, react-virtualized@^9.22.5, remeda@^2.0.9, server-only@^0.0.1, tailwind-merge@^2.3.0, tailwindcss@^3.4.1, tailwindcss-animate@^1.0.7, ts-pattern@^5.1.2, typescript@^5, vite@^8.0.8

### Recent commits (newest first)

- fixed the log in page and set up mongodb backend
- got everything working
- Merge pull request #6 from armitakatarapu/revert-branch
- final DO NOT CHANGE
- Merge pull request #5 from armitakatarapu/revert-branch
- Merge branch 'main' into revert-branch
- email removed final version vetted
- Merge pull request #4 from armitakatarapu/revert-branch
- final finished
- images on home fixed
- Merge pull request #3 from armitakatarapu/revert-branch
- half done 2nd video
- color change
- Merge pull request #2 from armitakatarapu/revert-branch
- my connections formating + deeper video
- Merge pull request #1 from armitakatarapu/revert-branch
- merge temp
- Revert "login fixed"
- Revert "finished my connections ALL FRONT END DONE"
- f

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

### package.json

```
{
  "name": "hume-evi-next-js-starter",
  "version": "0.1.0",
  "private": true,
  "homepage": "https://github.com/humeai/hume-evi-next-js-starter",
  "scripts": {
    "dev": "vite dev",
    "build": "vite build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@humeai/voice-react": "^0.1.15",
    "@radix-ui/react-slot": "^1.0.2",
    "@radix-ui/react-switch": "^1.0.3",
    "@radix-ui/react-toggle": "^1.0.3",
    "@types/react-virtualized": "^9.21.30",
    "bcryptjs": "^3.0.3",
    "class-variance-authority": "^0.7.0",
    "clsx": "^2.1.1",
    "cors": "^2.8.6",
    "dotenv": "^17.4.1",
    "express": "^5.2.1",
    "framer-motion": "^11.2.10",
    "geist": "^1.3.0",
    "hume": "^0.8.10",
    "jsonwebtoken": "^9.0.3",
    "lucide-react": "^0.394.0",
    "mongoose": "^9.4.1",
    "react-virtualized": "^9.22.5",
    "remeda": "^2.0.9",
    "server-only": "^0.0.1",
    "tailwind-merge": "^2.3.0",
    "tailwindcss-animate": "^1.0.7",
    "ts-pattern": "^5.1.2"
  },
  "devDependencies": {
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "eslint": "^8",
    "eslint-config-next": "14.2.3",
    "postcss": "^8",
    "tailwindcss": "^3.4.1",
    "typescript": "^5",
    "vite": "^8.0.8"
  }
}

```

### deeper-connections/package.json

```
{
  "name": "deeper-connections",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "typescript": "~6.0.2",
    "vite": "^8.0.4"
  },
  "dependencies": {
    "hume": "^0.15.16"
  }
}

```

### server.js

```javascript
const express = require('express');
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const cors = require('cors');
const path = require('path');
require('dotenv').config();

const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static(__dirname));

// ===== DATABASE CONNECTION =====
mongoose.connect(process.env.MONGO_URI)
    .then(() => console.log('MongoDB connected!'))
    .catch(err => console.log(err));

// ===== SCHEMAS =====
const userSchema = new mongoose.Schema({
    name: { type: String, required: true },
    phone: { type: String, required: true },
    username: { type: String, required: true, unique: true },
    password: { type: String, required: true },
    emergencyContacts: { type: [String], required: true },
    createdAt: { type: Date, default: Date.now }
});

const connectionSchema = new mongoose.Schema({
    userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
    connectedUserId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
    createdAt: { type: Date, default: Date.now }
});

const chatMessageSchema = new mongoose.Schema({
    role: { type: String, required: true },
    content: { type: String, required: true },
    topEmotions: { type: Array, default: [] },
    createdAt: { type: Date, default: Date.now }
});

const chatSessionSchema = new mongoose.Schema({
    userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
    humeChatGroupId: { type: String },
    messages: [chatMessageSchema],
    startedAt: { type: Date, default: Date.now },
    endedAt: { type: Date }
});

const User = mongoose.model('User', userSchema);
const Connection = mongoose.model('Connection', connectionSchema);
const ChatSession = mongoose.model('ChatSession', chatSessionSchema);

// ===== AUTH MIDDLEWARE =====
function authenticateToken(req, res, next) {
    const token = req.headers['authorization']?.split(' ')[1];
    if (!token) return res.status(401).json({ error: 'No token provided' });

    jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
        if (err) return res.status(403).json({ error: 'Invalid token' });
        req.user = user;
        next();
    });
}

// ===== AUTH ROUTES =====

// Signup
app.post('/api/signup', async (req, res) => {
    const { name, phone, username, password, emergencyContact1, emergencyContact2 } = req.body;

    try {
        const existing = await User.findOne({ username });
        if (existing) return res.status(400).json({ error: 'Username already exists' });

        const hashedPassword = await bcrypt.hash(password, 10);

        const newUser = await User.create({
            name,
            phone,
            username,
            password: hashedPassword,
            emergencyContacts: [emergencyContact1, emergencyContact2]
        });

        const token = jwt.sign(
            { id: newUser._id, username: newUser.username },
            process.env.JWT_SECRET,
            { expiresIn: '7d' }
        );

        res.json({ token, user: { id: newUser._id, username: newUser.username, name: newUser.name } });
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: 'Signup failed' });
    }
});

// Login
app.post('/api/login', async (req, res) => {
    const { username, password } = req.body;

    try {
        const user = await User.findOne({ username });
        if (!user) return res.status(401).json({ error: 'Invalid username or password' });

        const isMatch = await bcrypt.compare(password, user.password);
        if (!isMatch) return res.status(401).json({ error: 'Invalid username or password' });

        const token = jwt.sign(
            { id: user._id, username: user.username },
            process.env.JWT_SECRET,
            { expiresIn: '7d' }
        );

        res.json({ token, user: { id: user._id, username: user.username, name: user.name } });
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: 'Login failed' });
    }
});

// Get current user
app.get('/api/me', authenticateToken, async (req, res) => {
    try {
        const user = await User.findById(req.user.id).select('-password');
        res.json(user);
    } catch (err) {
        res.status(500).json({ error: 'Failed to fetch user' });
    }
});

// ===== CONNECTIONS ROUTES =====

// Get connections
app.get('/api/connections', authenticateToken, async (req, res) => {
    try {
        const connections = await Connection.find({ userId: req.user.id })
            .populate('connectedUserId', 'username name');
        res.json(connections.map(c => c.connectedUserId));
    } catch (err) {
        res.status(500).json({ error: 'Failed to fetch connections' });
    }
});

// Add connection
app.post('/api/connections', authenticateToken, async (req, res) => {
    const { connectedUsername } = req.body;
    try {
        const connectedUser = await User.findOne({ username: connectedUsername });
        if (!connectedUser) return res.status(404).json({ error: 'User not found' });

        await Connection.findOneAndUpdate(
            { userId: req.user.id, connectedUserId: connectedUser._id },
            { userId: req.user.id, connectedUserId: connectedUser._id },
            { upsert: true }
        );

        res.json({ success: true });
    } catch (err) {
        res.status(500).json({ error: 'Failed to add connection' });
    }
});

// ===== CHAT HISTORY ROUTES =====

// Start a new session
app.post('/api/chat/session', authenticateToken, async (req, res) => {
    const { humeChatGroupId } = req.body;
    try {
        const session = await ChatSession.create({
            userId: req.user.id,
            humeChatGroupId
        });
        res.json({ sessionId: session._id });
    } catch (err) {
        res.status(500).json({ error: 'Failed to start session' });
    }
});

// Save 
[truncated — 1252 more characters]
```

### deeper-connections/src/main.ts

```typescript
import './style.css'
import typescriptLogo from './assets/typescript.svg'
import viteLogo from './assets/vite.svg'
import heroImg from './assets/hero.png'
import { setupCounter } from './counter.ts'

document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
<section id="center">
  <div class="hero">
    <img src="${heroImg}" class="base" width="170" height="179">
    <img src="${typescriptLogo}" class="framework" alt="TypeScript logo"/>
    <img src=${viteLogo} class="vite" alt="Vite logo" />
  </div>
  <div>
    <h1>Get started</h1>
    <p>Edit <code>src/main.ts</code> and save to test <code>HMR</code></p>
  </div>
  <button id="counter" type="button" class="counter"></button>
</section>

<div class="ticks"></div>

<section id="next-steps">
  <div id="docs">
    <svg class="icon" role="presentation" aria-hidden="true"><use href="/icons.svg#documentation-icon"></use></svg>
    <h2>Documentation</h2>
    <p>Your questions, answered</p>
    <ul>
      <li>
        <a href="https://vite.dev/" target="_blank">
          <img class="logo" src=${viteLogo} alt="" />
          Explore Vite
        </a>
      </li>
      <li>
        <a href="https://www.typescriptlang.org" target="_blank">
          <img class="button-icon" src="${typescriptLogo}" alt="">
          Learn more
        </a>
      </li>
    </ul>
  </div>
  <div id="social">
    <svg class="icon" role="presentation" aria-hidden="true"><use href="/icons.svg#social-icon"></use></svg>
    <h2>Connect with us</h2>
    <p>Join the Vite community</p>
    <ul>
      <li><a href="https://github.com/vitejs/vite" target="_blank"><svg class="button-icon" role="presentation" aria-hidden="true"><use href="/icons.svg#github-icon"></use></svg>GitHub</a></li>
      <li><a href="https://chat.vite.dev/" target="_blank"><svg class="button-icon" role="presentation" aria-hidden="true"><use href="/icons.svg#discord-icon"></use></svg>Discord</a></li>
      <li><a href="https://x.com/vite_js" target="_blank"><svg class="button-icon" role="presentation" aria-hidden="true"><use href="/icons.svg#x-icon"></use></svg>X.com</a></li>
      <li><a href="https://bsky.app/profile/vite.dev" target="_blank"><svg class="button-icon" role="presentation" aria-hidden="true"><use href="/icons.svg#bluesky-icon"></use></svg>Bluesky</a></li>
    </ul>
  </div>
</section>

<div class="ticks"></div>
<section id="spacer"></section>
`

setupCounter(document.querySelector<HTMLButtonElement>('#counter')!)

```

### styles1.css

```css


```

### next-env.d.ts

```typescript
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

```

### vite.config.js

```javascript
import { defineConfig } from 'vite'

export default defineConfig({
  build: {
    rollupOptions: {
      input: {
        main: 'index.html',
        home: 'home.html',
        evi: 'evi.html',
        about: 'about.html',
      }
    }
  }
})
```

### index.html

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Deeper Connections</title>
</head>
<body>
    <script>
        window.location.href = '/home.html';
    </script>
</body>
</html>
```

### interaction.html

```html
<div class = "embedded-app-container">
  <iframe src = "https://calhacks-october2024.vercel.app" width = "800" height = "600" frameborder = "0"></iframe>
    </div>

    <style>

      embedded-app-container {
        border: ipx solid #ccc;
        margin 20px auto;
      }
    </style>

```

### sign.css

```css
.container {
  width: 100%;
  max-width: 400px;
  margin: auto;
  border: 1px solid #ccc;
  padding: 16px;
  background-color: white;
}


input[type=text], input[type=password] {
  width: 100%;
  padding: 12px;
  margin: 8px 0 16px 0;
  display: inline-block;
  border: 1px solid #ccc;
  box-sizing: border-box;
}


.signupbtn, .cancelbtn {
  width: 100%;
  padding: 14px;
  background-color: dodgerblue;
  color: white;
  border: none;
  cursor: pointer;
  font-size: 16px;
}

.cancelbtn {
  background-color: #f44336;
}

.signupbtn:hover, .cancelbtn:hover {
  opacity: 0.8;
}


input[type=checkbox] {
  margin-bottom: 16px;
}

.clearfix::after {
  content: "";
  clear: both;
  display: table;
}

a {
  color: dodgerblue;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}
```

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