GRANTSHARK
DOCS
Complete technical and business documentation for building, launching, and scaling GrantShark from zero to revenue.
๐ Start here if you're new: This doc covers everything from day 1 setup to launch. Read it top to bottom once, then use the sidebar to jump to specific sections.
What Is GrantShark?
GrantShark is an AI-powered scholarship hunting and application platform. Unlike scholarship databases (Fastweb, Scholly), GrantShark is agentic โ it doesn't just find scholarships, it applies to them. The platform:
- Scrapes 1,000+ scholarship sources nightly using Firecrawl
- Matches students to scholarships they qualify for
- Generates personalized essays using GPT-4o trained on the student's voice
- Auto-fills and submits application forms using Playwright browser automation
- Monitors decision emails and tracks winnings
- Charges a 5% success fee only when students win
Quick Start Guide
Step 1: Set Up Your Accounts (Day 1)
Before writing a single line of code, create accounts on these services:
Supabase โ supabase.com (Free tier to start)
OpenAI โ platform.openai.com (~$50/mo at scale)
Stripe โ stripe.com (2.9% + 30ยข per charge)
Vercel โ vercel.com (Free โ $20/mo Pro)
Firecrawl โ firecrawl.dev (~$50/mo)
Browserbase โ browserbase.com (~$100/mo)
Redis โ upstash.com (Free tier available)
2Captcha โ 2captcha.com ($2 per 1000 solves)
Step 2: Initialize the Project
npx create-next-app@latest grantshark --typescript --tailwind --app
cd grantshark
npm install @supabase/supabase-js stripe @stripe/stripe-js
npm install lucide-react framer-motion
npm install zod react-hook-form
python -m venv venv
source venv/bin/activate
pip install fastapi uvicorn playwright firecrawl-py openai redis
playwright install chromium
Step 3: Environment Variables
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_service_key
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
OPENAI_API_KEY=sk-...
FIRECRAWL_API_KEY=fc-...
BROWSERBASE_API_KEY=bb-...
TWOCAPTCHA_API_KEY=2c-...
REDIS_URL=redis://localhost:6379
Student Onboarding Flow
The onboarding form is the most critical part of the product. Every data point collected here improves essay quality and scholarship matching. Build it as a multi-step form with the following structure:
Step 1: Account Creation
- Email + password (Supabase Auth)
- Role selection: Student or Parent
- If Parent: link to student account or create student profile
Step 2: Academic Profile
- GPA (weighted and unweighted)
- Class rank (if available)
- SAT/ACT scores
- Current high school + graduation year
- Intended major and career goals
Step 3: Demographics (Optional but Powerful)
- Ethnicity (for ethnicity-specific scholarships)
- Gender identity
- Family income bracket
- First-generation college student status
- Geographic location (zip code)
Step 4: Activities & Achievements
- Upload activities list or fill structured form
- Top 3 extracurriculars with descriptions
- Community service hours and organizations
- Awards, honors, competitions
Step 5: Document Upload
- Official transcript (PDF)
- Resume (optional)
- 2โ3 existing essays (for voice training)
โ ๏ธ Critical: Use OpenAI to immediately parse uploaded PDFs into structured JSON. Store in the documents table with vectorized content for RAG retrieval during essay generation.
Scholarship Matching Engine
The matching engine runs as a cron job (nightly at 2am). It has two components:
Part A: Scholarship Ingestion
from firecrawl import FirecrawlApp
import json
SOURCES = [
"https://www.fastweb.com/college-scholarships",
"https://www.scholarships.com/financial-aid/college-scholarships",
"https://www.bold.org/scholarships",
"https://www.goingmerry.com/scholarships",
]
def ingest_scholarships():
app = FirecrawlApp(api_key=FIRECRAWL_API_KEY)
for url in SOURCES:
result = app.scrape_url(url, params={
'formats': ['json'],
'jsonOptions': {
'schema': scholarship_schema
}
})
Part B: Student Matching Query
SELECT s.* FROM scholarships s
WHERE
(s.requirements->>'gpa_min')::float <= $student_gpa
AND (s.requirements->>'deadline')::date > NOW()
AND (
s.requirements->>'ethnicity' IS NULL
OR $student_ethnicity = ANY(
ARRAY(SELECT jsonb_array_elements_text(s.requirements->'ethnicity'))
)
)
AND s.is_active = true
ORDER BY s.amount DESC;
Essay Generation Pipeline
This is the secret sauce. Essays must sound like the student, not like AI. The pipeline:
- Retrieve the scholarship's essay prompt
- Pull student's top 3 most similar past essays from pgvector (semantic similarity)
- Extract relevant activities and experiences from student profile
- Generate with GPT-4o using a carefully tuned prompt
- Run through GPTZero โ if flagged, regenerate with higher temperature
- Present to student for approval via SMS/dashboard
prompt = f"""
You are ghostwriting a scholarship essay for {student_name}, a high school senior.
SCHOLARSHIP PROMPT: {essay_prompt}
WORD LIMIT: {word_limit}
STUDENT'S VOICE (their actual writing samples โ match this style exactly):
{voice_samples}
KEY EXPERIENCES TO HIGHLIGHT (pick the most relevant 1-2):
{activities_json}
INSTRUCTIONS:
- Match the casual-but-earnest voice in their samples
- Include 1 specific anecdote, not vague generalities
- Avoid: "passionate about", "from a young age", "pursue my dreams"
- End with a forward-looking sentence about college goals
- Do NOT mention AI, college consultants, or that this was assisted
"""
Auto-Submission Agent
The submission agent uses Playwright via Browserbase (cloud browser hosting). This avoids managing Chrome instances on your server.
Supported Platforms (MVP)
- Bold.org โ Largest scholarship platform, most structured
- GoingMerry.com โ Strong for merit + niche scholarships
- ScholarshipOwl.com โ High volume, good for automation
- Individual school websites โ Adapter-based approach
- Submittable.com โ Used by many local foundations
async def submit_application(student, scholarship, essay):
browser = await browserbase.create_session()
page = await browser.new_page()
await page.goto(scholarship.url)
await login_or_register(page, student)
form_mapping = await claude_map_form(page.content(), student)
for field, value in form_mapping.items():
await page.fill(field, value)
if await has_captcha(page):
solution = await solve_captcha_2captcha(page)
await enter_captcha(page, solution)
screenshot = await page.screenshot()
await page.click('button[type="submit"]')
return save_proof(screenshot, application.id)
Decision Monitoring
Connect to the student's Gmail using Google OAuth. Monitor incoming emails for decision keywords. Update application status automatically.
Email Classification Prompt
"Classify this email as one of: [WON, FINALIST, REJECTED, MORE_INFO_NEEDED, UNKNOWN].
Email from: {sender}
Subject: {subject}
Body excerpt: {body[:500]}
Respond with JSON: {'status': '...', 'award_amount': null or number}"
System Architecture
Frontend (Next.js + Vercel)
โโโ /app/dashboard โ Student pipeline view
โโโ /app/onboard โ Multi-step profile form
โโโ /app/review/[id] โ Essay approval page
โโโ /api/ โ Next.js API routes (auth, webhooks)
Backend (FastAPI + Railway/Render)
โโโ /agents/
โ โโโ discovery.py โ Nightly scholarship scraper
โ โโโ writer.py โ Essay generation + GPTZero check
โ โโโ submitter.py โ Playwright form automation
โ โโโ monitor.py โ Email decision classifier
โโโ /queue/
โ โโโ worker.py โ BullMQ job processor (Redis)
โโโ /api/
โโโ routes.py โ Internal API for Next.js
Database (Supabase Postgres)
โโโ profiles โ User accounts
โโโ students โ Academic/demographic data
โโโ scholarships โ Scraped scholarship database
โโโ applications โ Pipeline tracking
โโโ documents โ Vectorized files (pgvector)
Database Schema
CREATE TABLE students (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES auth.users(id),
gpa DECIMAL(3,2),
gpa_weighted DECIMAL(3,2),
sat_score INTEGER,
act_score INTEGER,
graduation_year INTEGER,
major_interest TEXT,
ethnicity TEXT[],
income_bracket TEXT,
activities JSONB DEFAULT '[]',
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE scholarships (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
url TEXT UNIQUE NOT NULL,
amount INTEGER,
deadline DATE,
requirements JSONB,
essay_prompt TEXT,
is_active BOOLEAN DEFAULT true,
last_scraped TIMESTAMPTZ
);
CREATE TABLE applications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
student_id UUID REFERENCES students(id),
scholarship_id UUID REFERENCES scholarships(id),
status TEXT CHECK (status IN (
'matched','drafting','pending_approval',
'submitted','won','finalist','rejected'
)),
draft_essay TEXT,
final_essay TEXT,
award_amount INTEGER,
submitted_at TIMESTAMPTZ,
proof_url TEXT
);
CREATE TABLE documents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
student_id UUID REFERENCES students(id),
file_name TEXT,
file_url TEXT,
content_text TEXT,
embedding VECTOR(1536),
doc_type TEXT
);
Deployment Guide
Frontend (Vercel โ Free to start)
npm install -g vercel
vercel login
vercel --prod
Backend (Railway โ $5/mo to start)
git init && git add . && git commit -m "init"
git remote add origin https://github.com/yourusername/grantshark-api
Domain Setup
grantshark.app โ Vercel (main site)
api.grantshark.app โ Railway (FastAPI backend)
Launch Checklist
โ
Complete these in order before accepting your first real student.
Week 1: Infrastructure
- โ Supabase project created with schema deployed
- โ Stripe account verified (important: need KYC for payouts)
- โ OpenAI account with GPT-4o access
- โ Firecrawl API key and first test scrape working
- โ Browserbase account and first Playwright test running
- โ Redis queue set up (Upstash free tier)
Week 2: MVP Features
- โ Student onboarding form (4 steps) live
- โ Document upload + PDF parsing working
- โ Scholarship scraper running for 5 platforms
- โ Essay generation + student approval flow
- โ At least one scholarship platform submission working end-to-end
Week 3: Business Layer
- โ Stripe subscription + success fee invoicing live
- โ Gmail OAuth email monitoring connected
- โ Dashboard showing pipeline status
- โ SMS approval notifications (Twilio)
- โ Privacy Policy + Terms of Service published
Week 4: Soft Launch
- โ 10 beta students onboarded (friends/family first)
- โ First real submission made
- โ Monitoring + error alerting (Sentry) live
- โ Post in 3 Facebook parent groups
- โ Reach out to 5 high school counselors
Monetization Deep Dive
Revenue Model 1: Success Fee
5% of scholarship amount won. Use Stripe's deferred payment feature: store card on file, charge only on win confirmation.
stripe.InvoiceItem.create(
customer=student.stripe_customer_id,
amount=int(award_amount * 0.05 * 100),
currency="usd",
description=f"GrantShark 5% fee โ {scholarship_name} award"
)
stripe.Invoice.create(
customer=student.stripe_customer_id,
auto_advance=True
)
Revenue Model 2: Subscription
$99/month Hunter plan (reduced to 3% success fee). Best for students who expect high volumes. Target parents of ambitious students.
Revenue Model 3: School Licensing
Charge $5,000โ$10,000/year per school for a counselor dashboard. One sales call closes the deal if you can show "our students won $X last year."
Legal & Compliance Notes
โ ๏ธ Important: This is general guidance, not legal advice. Consult a lawyer before launch, especially for FERPA and state-specific education laws.
Key Legal Considerations
- FERPA: Get explicit written consent before accessing transcripts. Your onboarding form should include a FERPA release authorization.
- COPPA: For students under 13, require verifiable parental consent. Consider blocking under-13 registration entirely for simplicity.
- Scholarship Terms: Some scholarships prohibit application assistance. Build a flagging system to avoid auto-submitting to these.
- Unauthorized Computer Access: Only submit to platforms where the student has an account. Never "create" fake accounts.
- Success Fee Disclosure: State clearly in your Terms that you charge a % of winnings. Have parents acknowledge this explicitly.
- Business Entity: Form an LLC ($100โ500) in your state before processing any payments. Separates personal liability.
Recommended Legal Budget
- LLC formation: $100โ500
- Attorney review of ToS + Privacy Policy: $500โ1,500
- FERPA compliance review: $500โ1,000
- Total first-year legal budget: ~$2,000โ3,000