ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
Connect Canvas, StudentVue, or Schoology. IntelliPlan ranks assignments, builds a weekly study plan, exports to Google Calendar, and gives students a built-in AI tutor.
EducationPython · HTMLGitHub @UAnirudhOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
IntelliPlan is an AI study planner that connects to school platforms, pulls assignments, prioritizes tasks, and builds weekly schedules. It exports plans to Google Calendar, creates flashcards and quizzes, models grades, and includes an AI tutor across subjects—helping students stay organized, reduce stress, and learn more effectively.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
The AI-powered student planner built by a student, for students.
Connect your school platform, get a personalized study schedule, and actually stay on top of your work.
🌐 Live at: intelliplan.tech
💬 Community: discord.gg/34FYWhJQMU
📱 Installable as a PWA on Android & iOS · Chrome Extension available
Canvas and StudentVue show you what's due.
They don't tell you when to do it, what to prioritize, or how long it'll take.Read the full README ↗The AI-powered student planner built by a student, for students.
Connect your school platform, get a personalized study schedule, and actually stay on top of your work.
🌐 Live at: intelliplan.tech
💬 Community: discord.gg/34FYWhJQMU
📱 Installable as a PWA on Android & iOS · Chrome Extension available
Canvas and StudentVue show you what's due.
They don't tell you when to do it, what to prioritize, or how long it'll take.
Students are left manually juggling deadlines across apps, guessing what to work on first, and falling behind — not because they're lazy, but because no tool connects the dots for them.
IntelliPlan pulls your assignments directly from Canvas, Google Classroom, StudentVue, Schoology, Blackboard, or Moodle, scores them by priority, and uses AI to generate a full weekly study schedule tailored to your workload and available hours. It syncs to Google Calendar, integrates with Notion, and includes a built-in AI tutor — all free.
A Notion-style kanban board with three columns — Overdue, Today, and Upcoming. Assignments auto-import from your connected school platform and are sorted by AI priority scoring. You can also add manual tasks directly.
Input your available hours per day and preferred study time (morning, afternoon, evening). The AI generates a complete multi-day study plan — broken into focused work blocks with breaks — and exports it directly to Google Calendar with one click. Saved schedules persist across sessions.
Follow-Through Engine. Plans are optimised for work that actually gets done, not just work that fits:
How it works: docs/adaptive-scheduler/03-follow-through-engine.md.
Upload course notes (PDF, DOCX, TXT, MD, CSV) or paste text, and the AI generates:
Includes a full spaced repetition system (SRS) that tracks mastery level per question and schedules reviews automatically.
Smart priority scoring (High / Medium / Low) with estimated time per assignment based on points possible, due date proximity, and course weight. See everything ranked so you always know what to tackle first.
Browse and filter all assignments by course. Works across Canvas, Google Classroom, StudentVue, Schoology, Blackboard, and Moodle simultaneously if multiple accounts are linked.
GPA overview pulled live from your school platform. The Grade Modeler lets you simulate "what if I get X% on my next test?" and shows you exactly how it affects your course grade and GPA.
A dedicated AI tutor (separate from the assistant chatbot) that teaches subjects step by step — math, science, history, English, computer science, languages, economics, and test prep. It never just hands over answers; it builds understanding and checks comprehension with follow-up questions.
Plani runs on an adaptive student model rather than a plain chat wrapper. Every reply is shaped by a persistent profile of the student:
auto mode. Auditory learners get spoken-optimized phrasing; visual learners get more interactive artifacts.The layer lives in adaptive_tutor/ and degrades gracefully: if the analysis passes or the database are unavailable, the tutor falls back to its legacy heuristic memory rather than failing the reply.
Assignment deadline reminders sent as push notifications, even when the app is closed. Supports notification silencing for custom durations.
Full light/dark theme support with preference saved across sessions.
| Integration | What It Does |
|---|---|
| Canvas LMS | Auto-imports assignments, due dates, points, and course names via REST API |
| Google Classroom | Auto-imports active courses and coursework via Google OAuth |
| StudentVue | Auto-imports assignments and missing work via the StudentVue API |
| Schoology | Auto-imports assignments via API key + secret |
| Blackboard Learn | Connects to an institution's Learn URL with OAuth 2.0 (3LO) and imports gradebook due dates. Each school's Blackboard administrator must first register IntelliPlan's Application ID under System Admin → Integrations → REST API Integrations with End User Access enabled; until they do, /connect shows the student the exact steps instead of starting a sign-in that cannot finish |
| Moodle | Connects to a Moodle URL plus web-services token and imports assignments/events |
| Google Calendar | One-click export of AI-generated study schedules; OAuth 2.0 with PKCE |
| Notion | Two-way task sync with your Notion databases via integration token |
| Chrome Extension | Badge count showing pending assignments; injects into Canvas and StudentVue pages |
| PWA (Android) | Installable from Chrome's install prompt, or Menu → Add to Home screen |
| PWA (iOS) | Installable via Safari Add to Home Screen |
| Desktop app | Native Windows, macOS and Linux builds — tray, global shortcut, OS notifications, offline plan. See desktop/README.md |
| Layer | Technology |
|---|---|
| Backend | Python, Flask |
| Database | PostgreSQL (production via Railway), SQLite (local dev) |
| ORM | Flask-SQLAlchemy |
| Auth | Flask-Login, Flask-Bcrypt, Google OAuth 2.0 (PKCE), JWT tokens |
| Sessions | Flask-Session (SQLAlchemy-backed for persistence across Railway container restarts) |
| AI — Scheduling & Study | Google Gemini 2.5 Flash (Groq Llama fallback) |
| AI — Vision / Image Notes | Google Gemini 2.5 Flash (Groq Llama 4 Scout fallback) |
| AI — Tutor & Chatbot | Google Gemini 2.5 Flash (Groq Llama fallback) |
| School APIs | Canvas LMS REST API, Google Classroom API, StudentVue API, Schoology API, Blackboard Learn REST API, Moodle Web Services |
| Calendar | Google Calendar API v3 |
| Notes | Notion API |
| Push Notifications | Web Push / VAPID (pywebpush) |
| Error Tracking | Sentry |
| Rate Limiting | Flask-Limiter |
| Frontend | Vanilla HTML/CSS/JS, SVG animations, CSS custom properties |
| Hosting | Railway |
IntelliPlan/
│
├── App.py # Main Flask app — all routes, models, config
├── ai_provider.py # Unified AI layer — Gemini primary, Groq fallback
├── analytics.py # PostHog analytics wrapper (no-ops when unconfigured)
├── streak_engine.py # Pure streak logic — no Flask/DB dependencies
├── auth_api.py # Auth blueprint — JWT token endpoints
├── chatbot_api.py # Plani chatbot + tutor API blueprint
├── google_calendar_helper.py # Google OAuth + Calendar API helpers
├── notion_helper.py # Notion API integration helpers
├── studentvue_helper.py # StudentVue scraping/API helpers
├── canvas_routes.py # Canvas-specific route helpers
├── schoology_helper.py # Schoology API helpers
├── requirements.txt # Python dependencies
├── Procfile # Railway/Gunicorn process config
│
├── Main_Project/
│ └── templates/ # Jinja2 HTML templates
│ ├── base.html # Base layout with nav, Plani chatbot widget
│ ├── landing.html # Public landing page
│ ├── dashboard.html # Main task kanban board
│ ├── scheduler.html # AI schedule generator
│ ├── study.html # Study & Learn flashcard/quiz interface
│ ├── tutor.html # Plani AI tutor chat interface
│ ├── priority.html # Priority view
│ ├── classes.html # Classes/courses view
│ ├── grades.html # GPA overview
│ ├── grademodel.html # Grade modeler simulator
│ ├── settings.html # Integrations and account settings
│ └── ... # Login, register, connect, legal, blog pages
│
├── static/
│ ├── css/ # Stylesheets including mobile.css
│ ├── icons/ # PWA icons
│ ├── sw.js # Service worker for PWA/offline support
│ ├── manifest.json # PWA manifest
│ ├── robots.txt
│ ├── sitemap.xml
│ └── llms.txt # AI crawler instructions
│
├── extension/ # Chrome extension source
│ └── IntelliPlan-Extension-V.2.zip
│
└── uploads/
└── course_notes/ # Uploaded note files per user
# Clone the repo
git clone https://github.com/UAnirudh/IntelliPlan.git
cd IntelliPlan
# Install dependencies
pip install -r requirements.txt
# Create a .env file
cp .env.example .env
# Fill in your keys (see Environment Variables below)
# Run the app
python App.py
The app runs on http://localhost:3000 by default.
SECRET_KEY=your-flask-secret-key
GEMINI_API_KEY=your-gemini-api-key
GROQ_API_KEY=your-groq-api-key-optional-fallback
DATABASE_URL=sqlite:///intelliplan.db
# Google OAuth (optional — needed for Google Calendar)
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REDIRECT_URI=http://localhost:3000/oauth2callback
# Google Classroom OAuth (optional)
GOOGLE_CLASSROOM_CLIENT_ID=
GOOGLE_CLASSROOM_CLIENT_SECRET=
# Blackboard Learn OAuth (optional)
# The developer portal shows three values and they are NOT interchangeable.
# The application *key* goes here; putting the Application ID in this slot
# makes Blackboard reject the sign-in with "invalid client_id".
BLACKBOARD_APP_KEY=
BLACKBOARD_APP_SECRET=
# The Application ID each school's Blackboard admin registers under
# System Admin -> Integrations -> REST API Integrations (End User Access: Yes).
# This is the same value the portal calls the LTI "Client ID".
BLACKBOARD_APPLICATION_ID=
BLACKBOARD_SCOPE=read offline
# Check the configuration (prints no secrets):
# python scripts/blackboard_doctor.py [https://learn.myschool.edu]
# Moodle web services (optional; enabled by default)
MOODLE_ENABLED=1
# IndexNow (optional; defaults are already set for intelliplan.tech)
INDEXNOW_KEY=15d38c49db0d48efa4ec2ad2635b43c9
INDEXNOW_KEY_LOCATION=https://intelliplan.tech/15d38c49db0d48efa4ec2ad2635b43c9.txt
INDEXNOW_ENDPOINT=https://api.indexnow.org/indexnow
# Push Notifications (optional)
VAPID_PUBLIC_KEY=
VAPID_PRIVATE_KEY=
VAPID_EMAIL=
# Sentry (optional)
SENTRY_DSN=
# Lifecycle email (optional; required before the newsletter will send)
RESEND_API_KEY=
RESEND_FROM=IntelliPlan <[email protected]>
MARKETING_POSTAL_ADDRESS=
CRON_SECRET=
# App URL
APP_BASE_URL=http://localhost:3000
Three emails, in intelliplan/email/. Templates live in
Main_Project/templates/emails/, plain-text bodies beside the code in
intelliplan/email/text/.
| Key | Trigger | Consent | |
|---|---|---|---|
| Welcome | welcome | At signup; cron is a 36-hour backstop | Transactional — no marketing opt-in needed |
| Feedback request | feedback_v2 | Cron, accounts 7–8.5 days old with real activity | Requires dated weekly_v1 consent, eligible age, and no suppression |
| Weekly newsletter | newsletter_YYYY_wWW | Mondays, 08:00–09:00 Pacific, generated and sent unattended | Requires dated weekly_v1 consent, eligible age, and no suppression |
| One-off newsletter | newsletter_YYYY_MM | Admin only, hand-written payload | Requires dated weekly_v1 consent, eligible age, and no suppression |
Every send passes intelliplan.email.eligibility.is_marketing_eligible,
which refuses on unknown age, every under-13 account, undated or outdated
consent, a non-student role, or a suppressed address. Sends are deduplicated
on (user_id, email_key) in email_sends, so a double cron fire cannot
double-send.
Add one Railway cron entry, daily at 16:00 UTC (≈ 9am PT):
curl -X POST https://intelliplan.tech/cron/lifecycle-emails -H "X-Cron-Secret: $CRON_SECRET"
Railway schedule expression: 0 16 * * *. It is safe to run more often —
the ledger makes repeat runs no-ops.
A dedicated Railway cron service runs scripts/run_weekly_newsletter_cron.py
each Monday at 16:00 UTC (08:00 PST / 09:00 PDT):
The service reads the web service's CRON_SECRET by Railway variable
reference and calls the authenticated newsletter endpoint. No secret is
embedded in the start command.
Railway schedule expression: 0 16 * * 1. This sends to the eligible
weekly-consent list with nobody reviewing the content first. What protects it:
is_marketing_eligible.MARKETING_POSTAL_ADDRESS is still required.feat, fix only) and an allow-list of scopes. An unrecognised scope, an
unparseable subject, or anything matching the secret/internal/revert
pattern is dropped. A deny-list would leak the first thing nobody banned.Each issue leads with one rotating study idea and its suggested action, then lists at most three recent user-facing changes. The rotating study tips key off the ISO week number, so generation is deterministic — the preview is exactly what gets sent.
See what this week's issue will be before it goes:
curl -X POST https://intelliplan.tech/api/admin/newsletter/weekly-preview
The changelog needs a snapshot. .git is excluded from the Docker build
context, so the container cannot run git log. Refresh the committed
snapshot before deploying, or the "what changed" section goes stale:
python scripts/refresh_changelog.py
Reaches everyone who passes the consent gate, ignoring the 14-day window and the activity requirement — those two are quality heuristics. Consent, age and suppression still apply in full.
curl -X POST https://intelliplan.tech/api/admin/feedback-blast/preview
That returns the recipient count and sends nothing. To send, repeat against
/api/admin/feedback-blast/send with {"confirm": true}; without it the
endpoint returns 409 and the dry-run count. Deduplicated on feedback_v1,
so anyone the daily sweep already asked is not asked twice.
Admin-only, and never in one step. Dry run first:
curl -X POST https://intelliplan.tech/api/admin/newsletter/preview -H 'Content-Type: application/json' -d @newsletter.json
That returns the recipient count and sends nothing. Then test it on
yourself — test: true mails only ADMIN_EMAILS and does not write the
ledger, so it is repeatable. Only a payload with "confirm": true sends to
the full list; without it /api/admin/newsletter/send returns 409 and the
dry-run count instead.
MARKETING_POSTAL_ADDRESS must be set or the newsletter and feedback sends
refuse to run — CAN-SPAM requires a physical address in commercial email.
Run the preflight check first — it reports exactly what is missing:
curl -X POST https://intelliplan.tech/api/admin/email/preflight
Sending. intelliplan.tech has a CNAME at the apex pointing at Railway,
and DNS does not permit other records alongside a CNAME at the same name. So
rather than fighting the apex, send from a subdomain — this is Resend's own
recommendation anyway:
send.intelliplan.tech.RESEND_FROM=IntelliPlan <[email protected]>.Receiving. A send-only domain has no MX records, so anything addressed at it bounces. Every lifecycle email invites a reply, so point the reply addresses at a mailbox that already works:
[email protected]
[email protected]
Both are rendered into the email body as mailto: links and set as the
Reply-To header, so a student replying reaches a real inbox. Nothing in the
templates is hardcoded — switching to [email protected] later is an
environment-variable change, not a deploy.
To use @intelliplan.tech addresses for receiving, the apex needs MX
records, which means either moving DNS to a provider that flattens apex
CNAMEs (Cloudflare does, and its Email Routing is free) or replacing the apex
CNAME with an A record. Neither is required for any of this to work.
GET|POST /email/unsubscribe/<token> works logged-out, in one click, and
the token never expires. Unsubscribing sets marketing_emails_opt_in=False
and adds the address to email_suppressions — keyed on the address, not
the user, so deleting and recreating an account stays suppressed. Deadline
reminders are transactional and are deliberately unaffected.
An Expo app lives in mobile/. It authenticates with a bearer token from
/api/v1/auth/token and reads /api/today and /api/grade-predictions.
cd mobile
npm install
npm start # then press a for Android, i for iOS
It points at production by default. Under __DEV__ it uses the dev server
— 10.0.2.2:5000 on an Android emulator, localhost:5000 on iOS — and
EXPO_PUBLIC_API_BASE overrides both.
npx expo-doctor # 17/17 should pass
npx tsc --noEmit # typecheck
npx expo export --platform android # verify it bundles
Not on the app stores yet. eas.json has development, preview (APK) and
production (AAB) profiles ready for eas build.
| Endpoint | Method | Description |
|---|---|---|
/live | GET | Fetch live assignments from connected platform |
/tasks/unified | GET | All tasks merged (platform + manual + Notion) |
/courses | GET | List of courses |
/grades/data | GET | Grade data per course |
/missing/data | GET | Missing/overdue assignments |
| Endpoint | Method | Description |
|---|---|---|
/generate_schedule | POST | Generate AI study schedule from assignments |
/api/tutor | POST | Plani tutor — multi-turn academic tutoring |
/api/tutor/adaptive/profile | GET/POST | Learning profile (grade, subjects, goals, explanation preferences) |
/api/tutor/adaptive/dashboard | GET | Mastery scores, mistake patterns, learner memory, recommendations |
/api/tutor/adaptive/modality | POST | Set learning modality (auto/auditory/visual/reading/blended) |
/api/tutor/adaptive/summarize | POST | Close a conversation — summary, mistake extraction, mastery update |
/api/tutor/adaptive/memory-imports | GET/POST | Import learner context from another AI assistant |
/api/tutor/adaptive/mistakes/<id>/resolve | POST | Mark a recurring mistake resolved |
/api/chatbot | POST | Plani assistant — IntelliPlan feature help |
/study/generate | POST | Generate flashcards + quiz from notes |
/study/evaluate | POST | AI-evaluate a student's quiz answer |
/study/analyze-image | POST | Extract text/content from an uploaded image |
/notes/<id>/summarize | POST | AI summarize uploaded course notes |
| Endpoint | Method | Description |
|---|---|---|
/tasks/manual/create | POST | Create a manual task |
/tasks/manual/update | POST | Update a manual task |
/tasks/manual/delete | POST | Delete a manual task |
/dismiss | POST | Dismiss/complete an assignment |
/restore | POST | Restore a dismissed assignment |
| Endpoint | Method | Description |
|---|---|---|
/oauth/google | GET | Start Google OAuth flow |
/api/lms/connect/<provider> | POST | Start Google Classroom/Blackboard OAuth or return Moodle manual-connect metadata |
/api/lms/connect/moodle/manual | POST | Connect Moodle with site URL + web-services token |
/api/lms/status/google_classroom · /blackboard · /moodle | GET | Per-provider connection status (one route each, not a wildcard) |
/api/lms/disconnect/google_classroom · /blackboard · /moodle | POST | Disconnect that provider |
/api/lms/providers | GET | Every provider the registry knows about |
/api/lms/status | GET | Which providers this user is connected to |
/api/lms/<key>/sync | POST | Sync one provider through the registry |
/api/lms/<key>/disconnect | POST | Disconnect one provider through the registry |
/<INDEXNOW_KEY>.txt | GET | Host the IndexNow verification key at the site root |
/indexnow | GET | IndexNow protocol documentation and IntelliPlan setup |
/api/admin/indexnow/status | GET | Admin-only — show key, host, endpoint, sitemap count |
/api/admin/indexnow/submit | POST/GET | Admin-only — bulk POST {"urls":[...]}, GET ?url=..., or full sitemap |
/calendar/export | POST | Export schedule to Google Calendar |
/notion/connect | POST | Connect Notion integration |
/notion/tasks | GET | Fetch Notion tasks |
/schedule/save | POST | Save generated schedule |
| Endpoint | Method | Description |
|---|---|---|
/extension/login | POST | Authenticate extension with email/password |
/extension/tasks | GET | Get tasks for badge count |
/extension/schedule | GET | Get saved schedule |
/extension/grades | GET | Get grades |
/extension/dismiss | POST | Dismiss task from extension |
/extension/focus/current | GET | Focus Shield: current/next study block (device ?tz=), blocklist, break state |
/extension/focus/break | POST | Focus Shield: take one of this block's 5-minute breaks |
/extension/focus/done | POST | Focus Shield: "I'm done early" (stops blocking, checks the block off) |
The IntelliPlan Chrome Extension:
.zip in the repo — load via Chrome's chrome://extensions in Developer ModeIntelliPlan includes an optional Duolingo-style streak system behind the streak_v1 feature flag. It is off by default in production.
UPDATE feature_flags SET enabled = true, rollout_percentage = 100 WHERE key = 'streak_v1';
# .env
STREAK_V1_ENABLED=1
streak_v1:{user_id}.| Endpoint | Method | Description |
|---|---|---|
/api/streak/status | GET | Current streak, week dots, nudge eligibility |
/api/streak/plan-review | POST | Record a dashboard view as a qualifying action |
/api/streak/set-timezone | POST | Persist the user's IANA timezone |
/api/streak/nudge-shown | POST | Mark today's nudge as shown |
/api/streak/nudge-tapped | POST | Track nudge tap |
/api/streak/pill-tapped | POST | Track streak pill tap |
# Unit tests (pure logic, no DB)
pytest test_streak_engine.py -v
# E2E tests (Flask test client + SQLite in-memory)
pytest test_streak_e2e.py -v
When POSTHOG_API_KEY is set, the following events fire server-side: streak_started, streak_continued, streak_broken, streak_freeze_consumed, streak_freeze_earned, nudge_shown, nudge_tapped, streak_pill_tapped. The user property streak_v1_cohort (treatment or control) is set on each streak status fetch.
This project was built solo as a student project. Contributions, bug reports, and feature requests are welcome.
git checkout -b feature/your-feature)git commit -m 'Add your feature')git push origin feature/your-feature)For bugs or ideas, open an Issue or join the Discord.
Everything the previous roadmap listed has shipped and moved up into Features and Integrations. What is left is what has not been done yet — each item says what specifically is missing, so it is obvious when it can be ticked.
mobile/ builds and bundles
for Android and passes all 17 expo-doctor checks; eas.json is in
place. What remains is an Apple Developer and Google Play account,
store listings, and a first submission.electron-updater fits the existing
electron-builder config and the release feed already exists. It was
blocked on the installer bug, which is now fixed.MIT License — see LICENSE for details.
/schedule/saved |
| GET |
| Load saved schedule |