Submission at ConUHacks X (2026)
GhostWriter turns messy handwritten notes into neat, customizable documents with full
As students ourselves, we understand the struggle of keeping up in class. We wanted a tool that lets us give 100% attention to the professor while ensuring we still walk away with high-quality, study-ready notes. Why compromise when you can have both?
- Real-Time Sync: Uses a QR code to instantly link your phone to your desktop. No cables, no emailing files to yourself.
- AI-Powered OCR: Converts handwritten text into clean Markdown.
-
Math Wizardry: Automatically detects equations and converts them into proper
$\LaTeX$ formatting. -
Notion-Style Editing: Integrated
BlockNotefor a distraction-free, polished editing experience.
GhostSync/
βββ backend/
β βββ app.py # Flask server with SocketIO
β βββ requirements.txt # Python dependencies
β βββ .gitignore
βββ frontend/
β βββ src/
β β βββ components/
β β β βββ DesktopView.jsx # Main Desktop Dashboard
β β β βββ MobileView.jsx # Mobile Camera Interface
β β βββ App.jsx # Routing Logic
β β βββ main.jsx # Entry point
β β βββ index.css # Global styles (Tailwind/Cyberpunk theme)
β βββ package.json # Node dependencies
β βββ vite.config.js # Vite configuration
β βββ .env # Environment variables (API Keys & URLs)
βββ README.md
## Setup Instructions
### Prerequisites
- Python 3.8+ (for backend)
- Node.js 16+ and npm (for frontend)
### Backend Setup
1. Navigate to the backend directory and install Python packages
```bash
cd backend
pip install Flask==3.0.0 flask-socketio==5.3.6 python-socketio==5.11.0 python-engineio==4.9.0-
Create a virtual environment (recommended):
python3 -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install Python dependencies:
pip install -r requirements.txt
-
Run the Flask server:
python app.py
The backend will run on
http://localhost:5001
-
Open a new terminal and navigate to the frontend directory:
cd frontend -
Install Node dependencies:
npm install
-
Install required libraries/dependencies:
npm install -D vite @vitejs/plugin-react npm install react react-dom react-router-dom socket.io-client qrcode.react npm install react-easy-crop npm install react-icons/ri npm install katex npm install lucide-react npm install @blocknote/core @blocknote/react @blocknote/mantine npm install @mantine/core @mantine/hooks @mantine/utils npm install framer-motion
-
Open two separate terminals and create cloudflare tunnels for backend(5001) and frontend port(3000):
cloudflared tunnel --url http://localhost:5001/
cloudflared tunnel --url http://localhost:3000/
-
Take note of the generated URLs for each tunnel(example: https://random-generated-tunnel.trycloudflare.com)
-
Create a .env file and paste the following:
# Backend (Port 5001) -> VITE_BACKEND_URL=PASTE_BACKEND_URL_HERE # Frontend (Port 3000) -> VITE_FRONTEND_URL=PASTE_FRONTEND_URL_HERE VITE_AI_PROMPT="You are a precise OCR and document analysis system. Your sole task is to extract and convert all text content from images into properly formatted markdown and/or LaTeX. CORE INSTRUCTIONS: Extract ALL visible text with complete accuracy. Output ONLY the extracted text in markdown/LaTeX format. Use markdown for standard text, tables, lists, and headers. Use LaTeX for mathematical equations, formulas, and scientific notation. Preserve document structure (headings, paragraphs, lists, tables). Maintain original formatting hierarchy and spacing where meaningful. CRITICAL RULES: NO explanations, descriptions, or commentary. NO preambles like 'Here is the extracted text:'. NO post-ambles or summaries. If image is blank or contains no readable text: output exactly 'No text found in the image.' OUTPUT FORMAT: Tables: Use markdown table syntax. Math: Use LaTeX wrapped in $$. Code blocks: Use markdown code fences with language tags. Lists: Use markdown list syntax (-, *, 1., etc.). Emphasis: Use italic and bold as appropriate. Begin extraction immediately upon receiving an image. Output the formatted text directly with no additional text." VITE_AI_PROMPT_2="You are a precise text reformatter and document analysis system. Your sole task is to reformat a markdown text with LaTex into a JSON list. CORE INSTRUCTIONS: - Extract the ALL text within the markdown file. - Output ONLY the extracted text in markdown/LaTeX format - The JSON objects MUST have two keys, format and content (ie. {"format" : "", "content" : ""}). - The ONLY possible values for the format key are "markdown" for text and "latex" for math - The JSON list must plaintext NOT be in a code block. - Identify LaTeX by text wrapped in $$ - Preserve document structure (headings, paragraphs, lists, tables) - Structure must be preserved by separating sections () into different JSON objects - Reconnect phrases in the markdown text which were broken up by line breaks (\n). CRITICAL RULES: 1. NO explanations, descriptions, or commentary 2. NO preambles like "Here is the extracted text:" 3. NO post-ambles or summaries 4. If text is blank: output exactly "No text found." 5. For mixed content, alternate between objects of different formats. 6. Do NOT give the JSON array in a code block, it must be in plaintext OUTPUT FORMAT: - The JSON objects MUST have two keys, format and content (ie. {"format" : "", "content" : ""}) - Tables: Use markdown table syntax, different objects will act as line breaks - Code blocks: Use markdown code fences with language tags - Lists: Use markdown list syntax (-, *, 1., etc.) - Emphasis: Use *italic* and **bold** as appropriate - Math: Preserve LaTeX wrapped in $$. - The JSON array must be in plaintext Begin extraction immediately upon receiving a markdown text. Output the formatted text directly with no additional text." VITE_AI_SUMMARY_PROMPT="You are a helpful study assistant. Read the following text and provide a concise, short summary of the key concepts in 3-5 bullet points." VITE_AI_REFINE_PROMPT="You are an expert technical writer. Rewrite the notes to be Concise, Structured, and Error-Free. formatting Rules: NO Inline LaTeX: Never use single dollar signs ($). Variables are Bold: If you mention a variable like 'x' or 'f(t)', make it bold (e.g., **x**, **f(t)**). Equations are Blocks: For any mathematical formula, use double dollar signs ($$) on their own lines. Definitions: For definitions (like 'Def:'), use a bold header followed by a bullet point. Concise Bullets: Keep text explanations extremely short and bulleted. Strict Output: Return raw Markdown only. No code fences." VITE_AI_MODEL=gemini-2.5-pro
-
Run the Vite dev server:
npm run dev
The frontend will run on
http://0.0.0.0:3000(accessible from your local network)
- Start the Backend: Run
python app.pyin thebackenddirectory - Start the Frontend: Run
npm run devin thefrontenddirectory - Open Desktop View: Navigate to
http://localhost:3000on your desktop browser - Connect Mobile:
- A QR code will appear on the desktop view
- Scan the QR code with your mobile device's camera or QR code scanner
- The mobile browser will open and connect automatically
- Upload Photo:
- On the mobile view, tap "Take Photo" to open your phone's camera
- Adjust photo zoom and press Upload
- The image will instantly appear on the desktop view
- Ensure your mobile device is on the same network as your computer
- Verify the local IP address in
DesktopView.jsxis correct - Make sure the frontend server is running on
0.0.0.0(not justlocalhost)
- Check that both backend and frontend servers are running
- Verify the SocketIO connection URL matches your backend (default:
http://localhost:5000) - Check browser console for errors
- Check browser console for errors
- Verify the socket connection is established (look for connection status)
- Ensure the mobile device has successfully joined the session
- The backend uses Flask-SocketIO with CORS enabled for all origins (change in production)
- Images are transmitted as base64 encoded strings
- Session IDs are UUIDs generated server-side
- The frontend uses React Router for navigation between desktop and mobile views
MIT License - See LICENSE file for details