Skip to content

Latest commit

Β 

History

198 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🧠 PaperMind

AI-assisted discovery for scientific papers.

πŸš€ Live Demo

Next.js 16 MongoDB Atlas Groq Status License


πŸ’‘ The Problem

Searching arXiv means knowing the right keywords. Ask it a real question β€” "how do transformers actually handle long context?" β€” and keyword matching gives you nothing useful. Researchers think in concepts; the search box wants terms.

πŸ›  The Solution

PaperMind puts a language model between your question and the search index. You ask in plain English, an LLM distils it into the terminology the archive expects, and you get papers back β€” no query-crafting required.


✨ Features

πŸ” Ask in plain English

Type a question, not keywords. A Groq-hosted model condenses it into a precise search phrase before the query reaches arXiv.

"What are the latest breakthroughs in quantum computing?" β†’ quantum computing breakthroughs

If the model is unavailable, the search falls back to your raw query rather than failing.

πŸ“š Two ways to read

  • Classic β€” a paginated grid of paper cards with expandable abstracts.
  • Swipe β€” one card at a time, drag to move through the deck. Reaching the end loads more.

Every card links to the PDF and the arXiv abstract page.

πŸ“„ A page per paper

Every result opens onto /article/<arXiv id> β€” the full abstract, authors, categories, DOI, author comments, and links to the PDF and the arXiv record. Old-style identifiers with a slash (cs/0701001) work as well as modern ones.

Papermind keeps its own copy of every paper it has seen, so these pages keep resolving when arXiv is rate limiting or down β€” which, in practice, is often.

πŸ”— Share cards

Any paper can be shared as a card image with a QR code that points back at its Papermind page. It is the same image social platforms show when the link is posted, so the preview and the downloaded PNG never drift apart.

πŸ‘₯ Groups

Shared folders of papers. Create one, add papers from anywhere in the app, and invite people with a link that expires after a week. Members add and remove their own papers; the owner can remove any of them, rename the group, hand it over, or delete it while they are still its only member.

πŸ” Accounts and saved papers

Sign up to bookmark papers to your profile. Auth is a hand-rolled JWT setup in HttpOnly cookies with bcrypt hashing, silent token refresh, distributed rate limiting, account lockout after repeated failures, and Postmark-delivered password resets. Accounts can be deleted outright: owned groups pass to their longest-standing member, and contributions stay behind without a name.


πŸ— Tech Stack

Component Technology Why
Framework Next.js 16 (App Router) Route handlers + React 19, deployed serverless
Database MongoDB Atlas Document store for users and saved papers
LLM Groq (openai/gpt-oss-120b) Sub-second keyword extraction
LLM plumbing Vercel AI SDK Thin, provider-agnostic wrapper
Papers arXiv API Live access to pre-prints
Auth jsonwebtoken + bcryptjs Cookie-based sessions, no third-party dependency
Email Postmark Password-reset delivery
Styling Tailwind CSS v4 + Motion Utility-first CSS, spring animations

πŸš€ Getting Started

1. Clone and install

This project uses Bun.

git clone https://github.com/alangnt/papermind.git
cd papermind
bun install

2. Configure the environment

Create .env.local:

# Required
MONGODB_URI=                    # MongoDB Atlas connection string
MONGODB_NAME=                   # database name, e.g. Astra
SECRET_KEY=                     # signing key for access tokens

# Recommended
GROQ_API_KEY=                   # without it, search uses your raw query verbatim
POSTMARK_SERVER_TOKEN=          # without it, password reset returns 500
WEBSITE_URL=                    # absolute URL used in reset emails (default: http://localhost:3000)
REFRESH_SECRET_KEY=             # separate key for refresh tokens (default: SECRET_KEY)

# Optional β€” sensible defaults exist
ALGORITHM=HS256
REFRESH_ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
REFRESH_TOKEN_EXPIRE_MINUTES=43200

Note: MONGODB_NAME has no default. A fallback would let a misconfigured deployment silently read and write the wrong database, so the app throws instead.

3. Create the database indexes

Unique indexes on users.username and users.email are what actually prevent duplicate accounts β€” without them, concurrent sign-ups race. Check first, then apply:

bun run db:indexes:check   # dry run, writes nothing
bun run db:indexes         # creates them; refuses if duplicates already exist

4. Run it

bun run dev

Open http://localhost:3000.


πŸ“œ Scripts

Script Purpose
bun run dev Dev server with Turbopack
bun run build Production build
bun run lint ESLint β€” fails on any warning
bun run lint:fix ESLint with autofix
bun run format Prettier across the repo
bun run knip Report unused files, exports and dependencies
bun run db:indexes Create the required MongoDB indexes (idempotent)
bun run test Vitest β€” the whole suite, needs MONGODB_URI
bun run test:unit Everything that does not touch the database
bun run test:watch Vitest in watch mode

A husky pre-commit hook runs lint and test:unit, and blocks the commit on any finding. The database-backed suites run against a scratch database on the same cluster, wiped before and after; they are skipped when no connection string is available, so a commit never depends on the network.


πŸ—Ί Roadmap

Semantic vector search is the headline goal and is not implemented yet. Finishing it needs an embedding model wired in β€” either @xenova/transformers in-process or a hosted embeddings API β€” and then the aggregation below over a documents collection carrying an embedding field.

[
  {
    $vectorSearch: {
      index: 'search_similar',
      path: 'embedding',
      queryVector: [], // the embedded query goes here
      numCandidates: 200,
      limit: 10,
    },
  },
  {
    $project: {
      _id: 0,
      id: 1,
      pdfLink: 1,
      title: 1,
      summary: 1,
      authors: 1,
      published: 1,
      score: { $meta: 'vectorSearchScore' },
    },
  },
];
  • 🧠 Vector search β€” embed abstracts, retrieve by concept similarity
  • πŸ’¬ RAG answers β€” synthesise a cited answer from retrieved abstracts
  • βœ‰οΈ Email verification β€” accounts are currently auto-verified on sign-up
  • πŸ”Ž Group discovery β€” public groups, browsable, alongside today's invite-only ones
  • πŸ”” Notifications β€” tell members when a paper lands in a group they are in
  • ⚑ Query caching β€” arXiv responses are cached for a day
  • πŸ“Š Distributed rate limiting β€” limits live in MongoDB, shared across instances
  • πŸ§ͺ Test suite β€” Vitest, with the database-backed rules covered against a real server

πŸ“š Resources

Thank you to arXiv for use of its open access interoperability.


πŸ“„ License

MIT

About

An AI-powered arXiv search engine.

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages