DEV Community

Cover image for Study Partner: An AI Study Companion Built for My Wife
Emibrown
Emibrown

Posted on

Study Partner: An AI Study Companion Built for My Wife

Hacktoberfest Weekend Challenge: Build for a Friend Submission 🤝

This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend

What I Built

I built Study Partner for my wife, to give her a more interactive way to study using her own notes and PDFs.
She can upload her materials, ask questions, get explanations, and test her understanding through practice quizzes. An “Explain It Back” mode lets her describe a concept in her own words and receive feedback grounded in her material.
I also built voice role-play with Classmate and Mock Examiner modes for practising aloud, though that integration is still being refined. Saved conversations and practice results let her return to previous sessions.
The goal is simple: help her move beyond rereading notes and actively check what she understands, with a study partner available when she needs one.

Demo

Code

GitHub logo Emibrown / study-partner

Hacktoberfest Weekend Challenge: Build for a Friend

Study Partner

A private study-material library with Google-only authentication, PostgreSQL-backed notes and preferences, and private Cloudflare R2 PDF storage. Built with Next.js, TypeScript, Tailwind CSS, Radix UI, and Lucide.

Run

npm install
npm run db:check
npm run db:migrate
npm run dev
Enter fullscreen mode Exit fullscreen mode

Run commands from the project root. Configure root .env or .env.local using the placeholders in .env.example. Authentication setup is documented in AUTHENTICATION.md. The default origin is http://localhost:3000; changes to the port must also update Better Auth and Google's callback configuration.

Project Structure

  • src/: application routes, shared components, and server modules; @/* resolves here.
  • public/: static assets and the generated PDF.js worker.
  • tests/, scripts/, and migrations/: automated checks, maintenance commands, and versioned database migrations.
  • Root configuration files define Next.js, TypeScript, Tailwind/PostCSS, ESLint, and Playwright behavior. Application type checking covers src/, Next.js configuration, and generated route types.
  • submission-review/: historical review evidence…

How I Built It

Study Partner uses Qwen3-30B-A3B-Instruct-2507, an open-weight language model, accessed through OpenRouter via Backboard. It powers explanations, conversational quizzes, “Explain It Back” feedback, and practice question generation. Inference is hosted rather than run locally.
After my wife explicitly enables AI for a material, the app sends it to Backboard for indexing. Each material has its own assistant context, separate conversation threads, and material scoped memory. Responses are instructed to stay grounded in her notes and acknowledge missing information. Every generation request specifies the same Qwen model, with no fallback.
I built the app with Next.js, TypeScript, and Tailwind CSS, using Better Auth for Google sign-in and private Cloudflare R2 storage for PDFs. Render hosts both the Next.js web service and the PostgreSQL database, which stores accounts, preferences, notes, conversations, and practice results.
Practice questions are validated server side, answer keys remain hidden until submission, and scores are calculated deterministically.

For voice role play, ElevenLabs Agents handles speech and turn-taking while a custom backend connects learner turns to the same Backboard/Qwen pipeline. That integration is still being refined.

Qwen is the open-weight AI at the centre of the experience; Backboard, OpenRouter, and ElevenLabs provide hosted services around it.
I used Codex to help implement, debug, and test the project, including automated checks for authentication, user-data isolation, accessibility, and mocked AI-provider workflows.

Why Does Open Innovation Matter?

Building Study Partner for my wife made flexibility important. I wanted the learning experience to grow around her needs, rather than depend entirely on one provider’s model.
Using Qwen’s open weights creates options that a closed-model API alone would not: I can inspect the model’s architecture and published research, evaluate it independently, and potentially self host or fine tune it for specific learning needs. Those possibilities matter for future control over privacy, cost, and availability.
The current app uses hosted inference through Backboard and OpenRouter, so I haven’t implemented local inference or eliminated provider dependencies. The value of open weights is having a path toward greater control, not claiming that the app is already fully independent.
Open-source frameworks also made it practical to build authentication, accessible interfaces, and persistent study tools without starting from scratch. Open innovation helped me turn an idea for someone I love into something she can use, while leaving room to improve it.

My Agent Session

This curated session documents Study Partner’s implementation,
key decisions, debugging, and verification.

Building Study Partner for My Wife: From Prototype to Private AI Study Tools
Agent

01 | The person behind the project
[Curator-written retrospective summary]
Study Partner was built for the developer's wife. The aim was to help her study from her own notes and PDFs, ask for explanations, practise recall, and explain concepts in her own words. This selection records implementation, decisions, debugging and verification. It is an edited build record, not a raw transcript. No claims about her personal study habits, educational history or measured learning outcomes are added.

You

02 | Begin with the experience
[Verbatim excerpt from the user's approved frontend plan; remaining plan omitted]
Build a complete, clickable UI prototype with Next.js App Router, TypeScript, and Tailwind CSS. Use a calm, focused design with light neutral surfaces, green and coral accents, and readable study content.

Agent

03 | Build and test the prototype
[Curator-written retrospective summary]
The first milestone was deliberately UI-only: overview, library, study workspace, practice, voice, history, recap and settings. Shared components and accessible Radix primitives provided consistent navigation, dialogs, tabs and controls. Temporary fixtures let the journey be tested before backend integration.
Browser checks found low-contrast secondary text, missing tab-to-panel associations and a dialog that did not restore focus. Those were corrected. Screenshot review also caught long notes pushing the composer out of view, leading to bounded study panels and a composer-containment check. Later milestones replaced the sample content and simulated study responses rather than presenting them as real learning activity.

Agent

04 | Simplify identity and protect the workspace
[Curator-written retrospective summary]
Authentication initially included passwords and email delivery, then changed to Google-only at the user's request. Password and recovery endpoints, obsolete screens, and the email service integration were removed. Better Auth and PostgreSQL provide database-backed sessions; protected pages and APIs independently verify identity. Preferences belong to the authenticated account, not a client-supplied owner.
A one-time, explicitly approved transition reset only the application schema after a private backup; the backup is excluded from this selection. Normal migrations are versioned and additive. A hosted-database TLS error led to verified TLS defaults while retaining loopback test support. No credentials or database connection strings are reproduced here.

Agent

05 | Make onboarding direct
[Curator-written retrospective summary]
Incomplete users could navigate toward Overview only to encounter onboarding again. A Next.js proxy now checks the database-backed session and onboarding status before rendering study routes. Page and API checks remain in place as defense in depth. Incomplete onboarding hides home navigation, while completed users can revisit their preferences. Return destinations are validated locally.
The proxy reader was configured to avoid session renewal and expired-session cleanup during its read-only check. Regression tests covered direct visits, refresh, navigation, browser Back, expiry, revocation and unsafe return paths.

You

06 | Let the learner bring the material
[Verbatim excerpt from the user's approved materials plan; remaining plan omitted]
Change onboarding to study goal → preferred mode → Library. New users start with an empty workspace and add their own PDFs or pasted notes. Materials persist across sessions using PostgreSQL and a private Cloudflare R2 bucket.

Agent

07 | Replace samples with private persistence
[Curator-written retrospective summary]
Seeded biology materials and fabricated progress were removed. Notes are stored in PostgreSQL; PDFs use random object keys in a private R2 bucket. Material APIs check ownership independently and return not-found responses for inaccessible IDs. Upload validation covers PDF signatures, streamed byte limits and quotas. Failed storage deletion is queued for retry.
PDF.js renders the actual owned PDF with a download fallback. Debugging addressed its installed API, a stale Library-fetch race and delayed cleanup for uncertain uploads. Tests use generated PDFs and mocked storage; canvas-pixel checks verify that the preview is not blank. Private learner documents are not included in this record.

Agent

08 | Connect the open-weight model
[Curator-written retrospective summary]
The AI workspace uses qwen/qwen3-30b-a3b-instruct-2507 through OpenRouter via Backboard. Each generation pins that provider and model; no direct OpenRouter client or fallback model is added. This is hosted inference, not local inference or a fine-tuned model.
A material is sent for AI processing only after explicit consent. Backboard provides a separate assistant per material and separate threads for sessions. Tutoring uses automatic material-scoped memory; practice generation disables memory writes. Web search and external tools are disabled. Responses are instructed to treat uploaded text as source data and acknowledge gaps, not to invent citations. PDF grounding relies on provider retrieval, not an independent fact-checking guarantee.

Agent

09 | Make study state durable and practice checkable
[Curator-written retrospective summary]
Explain, conversational Quiz and Explain It Back share a persistent conversation with streaming, stop controls and recoverable errors. Practice validates five generated multiple-choice questions on the server, withholds answer keys until submission, calculates scores deterministically and saves progress. History shows actual sessions and results.
Database-backed operation records, idempotency keys and material-level reservations guard against duplicate or concurrent generation. Uncertain provider outcomes are reconciled rather than blindly replayed. Reset and material deletion queue remote cleanup. Debugging addressed consent-dialog focus, retry-key lifecycle, paginated provider cleanup and hiding raw practice JSON during reconnects.

Agent

10 | Add hands-free role-play
[Curator-written retrospective summary]
ElevenLabs Agents supplies WebRTC audio, speech and turn-taking for Classmate and Mock Examiner roles. A custom OpenAI-compatible streaming endpoint connects learner turns to the same Backboard/Qwen pipeline. Material preparation and voice consent are separate, and microphone access begins only after Start.
The app includes mic/speaker mute, End, a ten-minute deadline, transcript visibility and History. Provider-verified session binding and signed final webhooks separate authoritative transcripts from temporary browser captions. Audio is not archived by the app; agent configuration is checked for disabled audio saving. The initial daily start cap was later removed at the user's request, while generation limits, concurrency guards and the deadline remain.

Agent

11 | Investigate voice failures instead of hiding them
[Curator-written retrospective summary]
Live calls exposed disconnects, repeated listening filler and cancellation races that mocked tests alone had not established. Optional sanitized tracing records stages, timings and opaque references without prompts, transcripts or credentials. A disabled-by-default deterministic mode isolates ElevenLabs transport from generation for one explicitly selected, authenticated fictional session.
Fixes tied finalization and cancellation to exact generation-operation IDs, distinguished revised utterances from exact retries, waited for cancellation acknowledgement before the next turn and retained uncertain operations instead of replaying them. Provider completion statuses were normalized at the adapter boundary. An unresolved material generation now produces a distinct error rather than claiming a call is still active.
Limited live evidence included a fictional Backboard/Qwen probe with roughly 2.1-second first-token latency and 2.5-second completion. A later probe failed before preparation completed. A provider first-content timeout was also investigated, and the configured timeout was increased without enabling a fallback model. These observations are not proof that the combined voice pipeline is stable: the user's later disconnect reports remained unresolved when voice debugging was paused.

Agent

12 | Polish the application and simplify its structure
[Curator-written retrospective summary]
UI follow-ups placed the voice transcript beside the controls on desktop and used Google's multicolour sign-in logo. The project was flattened from a nested frontend directory to a standard root-level Next.js app with application code under src. Environment loading, scripts, imports, PDF-worker paths and the isolated mock SDK alias were updated. All 89 moved files passed content and permission checks before edits; credentials remained private and unchanged.
A subsequent cleanup removed the unreferenced pre-integration study placeholder, obsolete styles, the unused biology image and stale generated caches. Tests, migrations, private backups and historical review evidence were preserved. Eight retrospective feature-grouped Git commits were then created; they were explicitly labelled as a reconstruction from current files, not the original development chronology or a guarantee of runnable intermediate revisions.

Agent

13 | Verification, with its limits visible
[Curator-written retrospective summary of previously observed runs]
The root-structure verification passed lint, TypeScript and a production build, plus 8 authentication/database tests, 8 materials tests, 11 AI tests and 31 voice/configuration tests. One voice cleanup test failed on the first run; the complete 31-test voice suite passed on a separate rerun without a code change. The record does not establish the cause of that transient failure.
All 21 browser tests passed. Coverage included Google sign-in, protected routes, onboarding, account isolation, persisted materials, PDF previews, AI practice and the synthetic voice journey. Responsive checks covered desktop and narrow mobile widths, screenshots, overflow and automated accessibility checks. The sign-in page, Google logo and PDF worker also returned successful local responses.
Backend and browser provider tests used isolated PostgreSQL, fictional fixtures, mocked Google/R2/Backboard/ElevenLabs responses and synthetic microphone input. They do not prove live provider access, production reliability or a complete assistive-technology audit. The later unused-file cleanup passed lint, TypeScript and build; full backend/browser suites were not rerun for that cleanup. No tests were rerun merely to prepare this transcript.

Agent

14 | Deployment and remaining acceptance
[Curator-written retrospective summary]
The submission describes Render as the host for both the Next.js web service and PostgreSQL. Deployment guidance covered server-only environment variables, migrations, the public authentication origin, Google callbacks, ElevenLabs custom-model/webhook URLs and scheduled cleanup. Production deployment health was not independently verified during this curation, and no production URL or account details are included.
Before describing voice as production-ready, the combined live pipeline still needs successful multi-turn and interruption testing, silence/resume, mute/unmute, explicit End and saved-transcript refresh. Operational cleanup also needs to be scheduled and checked. Deploying to a public host does not by itself resolve the previously observed voice failures.

Agent

15 | What this build demonstrates
[Curator-written retrospective summary]
The project grew from a clickable prototype into private, user-owned study workflows around an open-weight model. The important decisions were explicit consent before AI processing, material-scoped context, server-enforced ownership, deterministic scoring and honest recovery for uncertain requests. Open weights leave future options for independent evaluation, self-hosting or adaptation; none of those future options is presented as already implemented.
The useful lesson from voice work was that passing mocks is not the same as passing live acceptance. This record includes that limitation alongside the implemented features rather than presenting an unfinished integration as a completed success.

Agent

16 | Privacy and review boundary
[Curator-written editorial note]
This selected record contains no secret values, private notes, uploaded documents, audio, raw learning conversations, account emails, personal names, machine paths, deployment/tunnel hostnames, provider identifiers or diagnostic references. The relationship 'wife' is retained because the developer explicitly chose it for the public submission; no further personal details are added. Public technology names and the model identifier are intentional.
Original local drafts are preserved. This candidate and its matching readable review copy remain local, excluded from Git and awaiting the user's review. No DevRelay upload, public session ID, article embed or publication has been created by this curation. Automated scanning reduces risk but is not a guarantee that all sensitive information has been detected.

Prize Categories

I’m entering the partner categories for:

  • Render: Hosts the Next.js web service and PostgreSQL database.
  • Backboard: Provides material indexing, conversation context, and memory for Qwen-powered study sessions.
  • ElevenLabs: Powers speech and turn-taking for voice role-play with Classmate and Mock Examiner modes.

Hand it over

My wife was excited to try Study Partner. She told me it made studying feel easier, and that the role-play helped her understand a topic better and feel more confident discussing it. Hearing that was the most rewarding part of building it.

Top comments (0)