# Project export: SnackHack

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 12.0
- Tagline: Automated consented phishing tests
- Devpost: https://devpost.com/software/snackhack-3flm5b
- GitHub: https://github.com/SAHAJ-BHADJA/Wordware_Wachy_admin
- Video: https://www.youtube.com/embed/NWRSyGsucn8?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Sahaj Bhadja (3 commits)

## Devpost submission (written by the team)

### Inspiration

Phishing and email spoofing remain the most common entry points for cyberattacks. We wanted to explore how easily users can fall for realistic but harmless emails—and how data-driven insights can strengthen awareness training and detection models.

### What it does

Our project simulates controlled, lab-safe phishing campaigns using Wordware automation. It tracks delivery, opens, and clicks in a sanitized dashboard to measure human risk and gateway effectiveness. We also began developing a machine-learning and deep-learning pipeline to detect and classify malicious URLs, complementing the simulation with proactive defense research. How I built it We used Wordware for automation and telemetry visualization, Python + Flask for backend logging, and a mock SMTP setup to ensure all emails were contained within a sandboxed environment. Challenges I ran into Ensuring full ethical isolation—no real recipients or payloads. Managing asynchronous message tracking and accurate analytics visualization. Balancing detection accuracy and false-positive rates in URL classification. Time-boxing training runs on limited hardware during the hackathon. Accomplishments that I'm proud of End-to-end phishing simulation dashboard built safely within 24 hours. Actionable analytics showing how awareness and filters impact outcomes. Integration of an initial malicious-URL detection model for future defense modules. Clear demonstration of how offensive simulation data can inform defensive systems. What I learned Hands-on simulation, when done responsibly, provides the best understanding of real-world attack behavior. We learned to combine offensive-security insights with defensive ML research to build safer email ecosystems and better user education.

### What's next

Integrate the ML URL detector into the simulation pipeline for real-time classification. Expand datasets and benchmark models for precision and recall. Open-source a training-mode simulator for organizations to test awareness safely. Develop an admin dashboard with real-time defense recommendations.

## README (from the GitHub repository)

No README available.

## Detected evidence (automated analysis)

Indexed codebase: 10 recognized source files, 23 KB.
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Python (language) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (13 of 13)

```
.gitignore
api/wordware/run.ts
index.html
package.json
postcss.config.js
src/index.css
src/main.ts
src/main.tsx
src/WordwareEmailUI.tsx
styles.css
tailwind.config.js
tsconfig.json
vite.config.ts
```

### Dependencies

- package.json: @types/react@^18.2.70, @types/react-dom@18.2.22, @vitejs/plugin-react@4.2.0, autoprefixer@10.4.20, postcss@8.4.38, react@^18.2.0, react-dom@^18.2.0, tailwindcss@3.4.10, typescript@^5.4.0, vite@5.0.0

### Recent commits (newest first)

- fix of 404 error
- necessary changes
- hacker admin ready

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

### package.json

```
{
  "name": "ts-landing-page",
  "version": "0.2.0",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.70",
    "@types/react-dom": "18.2.22",
    "typescript": "^5.4.0",
    "vite": "5.0.0",
    "@vitejs/plugin-react": "4.2.0",
    "tailwindcss": "3.4.10",
    "postcss": "8.4.38",
    "autoprefixer": "10.4.20"
  }
}

```

### src/main.tsx

```typescript
import React from "react";
import { createRoot } from "react-dom/client";
import WordwareEmailUI from "./WordwareEmailUI";
import "./index.css";

const rootEl = document.getElementById("root");
if (!rootEl) throw new Error("Root element #root not found");

createRoot(rootEl).render(
  <React.StrictMode>
    <WordwareEmailUI />
  </React.StrictMode>
);

```

### src/main.ts

```typescript
const btn = document.getElementById('cta-button') as HTMLButtonElement | null;
const year = document.getElementById('year');

if (year) {
  year.textContent = String(new Date().getFullYear());
}

btn?.addEventListener('click', () => {
  const target = document.getElementById('features');
  if (!target) return;
  target.scrollIntoView({ behavior: 'smooth', block: 'start' });
});

```

### postcss.config.js

```javascript
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

```

### index.html

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Wordware Email Sender UI" />
    <title>Wordware Email Sender</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
  </html>

```

### vite.config.ts

```typescript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// Proxy /api/wordware/* to https://app.wordware.ai/api/*
export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      '/api/wordware': {
        target: 'https://app.wordware.ai/api/released-app/be71501b-0e7e-421f-8653-1a39237221c0',
        changeOrigin: true,
        secure: true,
        rewrite: (path) => path.replace(/^\/api\/wordware/, '/api'),
      },
    },
  },
})

```

### tailwind.config.js

```javascript
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{ts,tsx}"
  ],
  theme: {
    extend: {
      colors: {
        brand: {
          50: "#eef3ff",
          100: "#dbe7ff",
          200: "#b8d0ff",
          300: "#94b8ff",
          400: "#6fa1ff",
          500: "#4b89ff",
          600: "#3c6ed6",
          700: "#2d54ad",
          800: "#1e3a84",
          900: "#10215b",
        }
      },
      boxShadow: {
        soft: "0 1px 2px 0 rgb(0 0 0 / 0.05), 0 10px 25px -5px rgb(0 0 0 / 0.08)",
      },
      fontFamily: {
        sans: [
          "ui-sans-serif", "system-ui", "-apple-system", "Segoe UI", "Roboto", "Helvetica", "Arial",
          "Apple Color Emoji", "Segoe UI Emoji"
        ]
      }
    },
  },
  plugins: [],
}

```

### styles.css

```css
:root{
  --bg: #0b1020;
  --panel: #111833;
  --text: #e6e9f2;
  --muted: #a4adbf;
  --primary: #5b8cff;
  --primary-600: #4b78e2;
  --border: #1e2747;
}
*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0;
  font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
  color:var(--text);
  background:linear-gradient(180deg, #0b1020 0%, #0b1226 100%);
}
.container{width:min(1100px, 92%); margin:0 auto}
.header{padding:28px 0 64px}
.nav{display:flex; align-items:center; justify-content:space-between}
.logo{font-weight:700; letter-spacing:.3px}
.btn{display:inline-flex; align-items:center; gap:8px; padding:10px 14px; border-radius:10px; border:1px solid var(--border); cursor:pointer; text-decoration:none; color:var(--text)}
.btn.primary{background:var(--primary); border-color:transparent; color:white}
.btn.primary:hover{background:var(--primary-600)}
.btn.ghost{background:transparent}
.btn.link{border-color:transparent; padding:10px 6px; color:var(--muted)}
.hero{padding:56px 0 24px; text-align:center}
.hero h1{margin:0 0 12px; font-size:44px; line-height:1.1}
.hero .sub{margin:0 auto 20px; color:var(--muted); max-width:700px}
.cta{display:flex; gap:12px; justify-content:center}
.features{display:grid; grid-template-columns:repeat(3, 1fr); gap:18px; padding:24px 0 52px}
.feature{background:var(--panel); border:1px solid var(--border); border-radius:14px; padding:18px}
.feature h3{margin:0 0 6px}
.feature p{margin:0; color:var(--muted)}
.footer{padding:24px 0 56px; border-top:1px solid var(--border); color:var(--muted); text-align:center}
@media (max-width: 860px){
  .features{grid-template-columns:1fr}
  .hero h1{font-size:34px}
}

```

### src/index.css

```css
@tailwind base;
@tailwind components;
@tailwind utilities;

/* App shell polish */
:root { color-scheme: light; }
html, body, #root { height: 100%; }
body { @apply bg-gray-50 text-gray-900; }

/* Cards */
.card { @apply rounded-2xl bg-white shadow-soft border border-gray-200; }

/* Inputs */
.input { @apply w-full rounded-lg border border-gray-300 px-3 py-2 focus:outline-none focus:ring focus:ring-blue-200; }
.button { @apply rounded-xl bg-blue-600 px-5 py-2.5 font-semibold text-white shadow-sm transition hover:bg-blue-700 disabled:opacity-60; }

```

### src/WordwareEmailUI.tsx

```typescript
import React, { useEffect, useMemo, useState } from "react";

const API_URL = "/api/wordware/run";

const API_KEY = "ww-6ka2SyX65Uaz0dfFOO0B4yeBM3p1MYSHDqA1f5ha43YRDjaqZGUqdC";

function normalizeReceivers(input: string): string {
  return input
    .split(/\n|,|;|\s+/)
    .map((s) => s.trim())
    .filter(Boolean)
    .join(", ");
}

const SAMPLE_HTML = `<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Snacks at the Counter 🍪</title>
  <meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body style="margin:0; padding:0; background-color:#f4f6f8;">
  <center style="width:100%; background:#f4f6f8;">
    <div style="display:none; font-size:1px; color:#f4f6f8; line-height:1px; max-height:0; max-width:0; opacity:0; overflow:hidden;">
      Fresh snacks just arrived at the office counter—check ingredients before you grab!
    </div>

    <table role="presentation" cellpadding="0" cellspacing="0" width="100%" style="max-width:640px; margin:0 auto; background:#ffffff;">
      <tr>
        <td style="padding:20px 24px; background:#0b5fff; color:#ffffff; font-family:Arial,Helvetica,sans-serif;">
          <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
            <tr>
              <td style="font-size:20px; font-weight:700;">Snacks Are In! 🎉</td>
              <td align="right" style="font-size:12px; opacity:0.9;">Today • Office Counter</td>
            </tr>
          </table>
        </td>
      </tr>

      <tr>
        <td style="padding:20px 24px; font-family:Arial,Helvetica,sans-serif; color:#111827;">
          <p style="margin:0 0 10px; font-size:18px; font-weight:700;">Grab a bite, check ingredients first</p>
          <p style="margin:0; font-size:14px; line-height:1.6;">
            We’ve stocked the counter with fresh snacks. Browse the list below and tap
            <span style="font-weight:700;">Ingredients</span> to see what's inside—helpful for allergens and dietary preferences.
          </p>
        </td>
      </tr>

      <tr>
        <td style="padding:0 24px;">
          <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="border-collapse:collapse; border:1px solid #e5e7eb;">
            <tr>
              <th align="left" style="padding:12px 14px; background:#f9fafb; font-family:Arial,Helvetica,sans-serif; font-size:12px; color:#374151; border-bottom:1px solid #e5e7eb;">Snack</th>
              <th align="left" style="padding:12px 14px; background:#f9fafb; font-family:Arial,Helvetica,sans-serif; font-size:12px; color:#374151; border-bottom:1px solid #e5e7eb;">Dietary</th>
              <th align="left" style="padding:12px 14px; background:#f9fafb; font-family:Arial,Helvetica,sans-serif; font-size:12px; color:#374151; border-bottom:1px solid #e5e7eb;">Details</th>
            </tr>

            <tr>
              <td style="padding:12px 14px; font-family:Arial,Helvetica,sans-serif; font-size:14px; color:#111827; border-bottom:1px solid #f0f2f5;">
                Bhavnagari Gathiya
              </td>
              <td style="padding:12px 14px; font-family:Arial,Helvetica,sans-serif; font-size:12px; color:#065f46;">
                <span style="display:inline-block; padding:2px 8px; border-radius:999px; background:#ecfdf5;">Vegetarian</span>
              </td>
              <td style="padding:12px 14px; font-family:Arial,Helvetica,sans-serif; font-size:14px;">
                <a href="https://example.com/ingredients/bhavnagari-gathiya" style="color:#0b5fff; text-decoration:none;">Ingredients</a>
              </td>
            </tr>

            <tr>
              <td style="padding:12px 14px; font-family:Arial,Helvetica,sans-serif; font-size:14px; color:#111827; border-bottom:1px solid #f0f2f5;">
                Star Gathiya
              </td>
              <td style="padding:12px 14px; font-family:Arial,Helvetica,sans-serif; font-size:12px; color:#92400e;">
                <span style="display:inline-block; padding:2px 8px; border-radius:999px; background:#fffbeb;">Contains Gluten</span>
              </td>
              <td style="padding:12px 14px; font-family:Arial,Helvetica,sans-serif; font-size:14px;">
                <a href="https://example.com/ingredients/star-gathiya" style="color:#0b5fff; text-decoration:none;">Ingredients</a>
              </td>
            </tr>

            <tr>
              <td style="padding:12px 14px; font-family:Arial,Helvetica,sans-serif; font-size:14px; color:#111827; border-bottom:1px solid #f0f2f5;">
                Papdi Plain
              </td>
              <td style="padding:12px 14px; font-family:Arial,Helvetica,sans-serif; font-size:12px; color:#86198f;">
                <span style="display:inline-block; padding:2px 8px; border-radius:999px; background:#fdf4ff;">May contain nuts</span>
              </td>
              <td style="padding:12px 14px; font-family:Arial,Helvetica,sans-serif; font-size:14px;">
                <a href="https://example.com/ingredients/papdi-plain" style="color:#0b5fff; text-decoration:none;">Ingredients</a>
              </td>
            </tr>

            <tr>
              <td style="padding:12px 14px; font-family:Arial,Helvetica,sans-serif; font-size:14px; color:#111827; border-bottom:1px solid #f0f2f5;">
                Chocolate Burfi
              </td>
              <td style="padding:12px 14px; font-family:Arial,Helvetica,sans-serif; font-size:12px; color:#991b1b;">
                <span style="display:inline-block; padding:2px 8px; border-radius:999px; background:#fef2f2;">Contains Dairy</span>
              </td>
              <td style="padding:12px 14px; font-family:Arial,Helvetica,sans-serif; font-size:14px;">
                <a href="https://example.com/ingredients/chocolate-burfi" style="color:#0b5fff; text-decoration:none;">Ingredients</a>
              </td>
            </tr>

            <tr>
              <td style="padding:12px 14px; font-family:Arial,Helvetica,sans-serif; fo
[truncated — 11305 more characters]
```

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