βKnowledge grows when it is shared.β An open, student-driven platform to map, preserve, and amplify the collective learning resources of the Undergraduate Program in Molecular Sciences (CiΓͺncias Moleculares) at USP.
The Molecular Sciences Library is a fully open-source initiative created by students, for students of the CiΓͺncias Moleculres USP community.
It started from a simple pain: books existed, but discovery was hard, circulation was messy, and collective memory was fragile.
We decided to fix that by building an extensible, transparent and collaborative system that:
- π Catalogs every physical item with structured codes & metadata.
- π Makes searching intuitive (area, subarea, language, status, availability, lending state).
- ποΈ Models the physical arrangement through a Virtual Bookshelf (digital β real shelves).
- π Automates loans, renewals, extensions, overdue flows & didactic reservations.
- βοΈ Sends meaningful notifications (borrow, return, renewal, extension, nudges, custom).
- π Encourages engagement (badges, donor registry, contribution recognition).
- π Stays totally open: your pull requests shape the next iteration.
Created and initially maintained by Luca Marinho and Helena Reis (Turma 33). Now, youβstudents, alumni, contributorsβare invited to help grow this into a living academic commons.
git clone https://github.com/lucaanasser/MolecularSciencesLibrary.git
cd MolecularSciencesLibrary
cp backend/.env.example backend/.env # edit as needed
# Setup aliases (optional but recommended)
bash scripts/setup-aliases.sh
source ~/.bash_aliases
# Run with interactive menu
npm run dev- Frontend β http://localhost:8080
- API β http://localhost:3001/api
Pro tip: After setup, just type dev from anywhere to start! π―
- π Molecular Sciences Library (Biblioteca do curso de CiΓͺncias Moleculares da USP)
- π Quick Start (for the impatient)
- π Table of Contents
- 1. Vision & Philosophy
- 2. Feature Overview
- 3. Architecture & Technology Stack
- 4. Directory Structure (Condensed)
- 5. Data & Domain Model (High-Level)
- 6. Logging & Conventions
- 7. Environments (Development vs Production)
- 8. Environment Variables (Backend Example)
- 9. Running the Project
- 10. Developer Scripts & Automation
- 11. Core Workflows
- 12. API Surface (Snapshot)
- 13. Background Tasks
- 14. Contribution Guide (Pull Requests)
- 15. Code Quality, Style & Testing
- 16. Roadmap
- 17. Security & Hardening
- 18. License (Public Domain β The Unlicense)
- 19. Acknowledgements
We believe an academic library is infrastructure for imagination.
This project:
- π― Treats operational clarity (statuses, rules, due windows) as UX.
- ποΈ Sees physical arrangement (shelves) as a navigable data model.
- π Embraces openness: everything auditable, extensible, remixable.
- β‘ Prefers pragmatic simplicity over premature abstraction.
- π§ͺ Welcomes experimentation: modular and replaceable features.
Fork it, extend it, adapt itβthatβs the point.
| Domain | Highlights |
|---|---|
| π Books | Structured codes AREA-SUBAREA.SEQ v.X, EAN-13 ID, filtering, didactic reservation flag. |
| ποΈ Virtual Bookshelf | Logical ordering of shelves & rows with start/end code ranges. |
| π Loans | Authenticated by NUSP, renewals, due windows, extension blocks. |
| β³ Extensions & Nudges | Policy-driven logic for eligibility & shortened due dates. |
| βοΈ Rules Engine | Admin-editable runtime parameters (limits, cooldowns, multipliers). |
| βοΈ Notifications | Internal + email (borrow, return, renewal, extension, nudge, custom). |
| π€ Users | Roles (admin, aluno, proaluno kiosk), password reset, profile image. |
| π Badges | Unlockable achievements. |
| π Donors | Registry & filters (internal vs external). |
| π¬ Forms | βHelp the Libraryβ contribution form with confirmation email. |
| π€ Automation | Daily cron for overdues, Google Drive backups, Certbot renewal. |
Backend: Cloudflare Workers (Hono), D1 (SQLite), JWT, Resend (email HTTP API). Frontend: React + TypeScript + Vite, React Query, TailwindCSS + shadcn/ui. Infra: Docker, Nginx, Certbot, sidecar cron/backup. Observability: Semantic console logging with emoji stages.
Client (React) ββ> REST API (Express) ββ> Services ββ> Models ββ> SQLite
β
βββ> Email Service
βββ> Notifications
βββ> Cron / Backup / Certbot
backend/
src/{routes,controllers,services,models,middlewares,database}
scripts/ (overdue, seeding, imports)
frontend/
src/features/{books,loans,users,notifications,rules,donators}
src/{components,services,hooks,utils}
certbot/ (ACME challenges)
database/ (SQLite persistent files)
ssl/ (prod certs)
ssl-dev/ (dev certs)
scripts/ (backup, automation)
- books: id (EAN13), area, subarea, title, edition, volume, language, reserved.
- loans: book_id, student_id, due_date, returned_at, renewals, is_extended.
- rules: runtime policy (singleton).
- users: id, NUSP, role, password_hash, email, class, profile_image.
- notifications: user_id, type, message, metadata, read state.
- badges & user_badges.
- donators: name, type, linked user (optional).
Emoji stages keep logs scannable:
- π΅ Start
- π’ Success
- π‘ Warning/alternate
- π΄ Error
| Aspect | Dev | Prod |
|---|---|---|
| Frontend | http://localhost:3000 |
Public domain (TLS) |
| Backend | 3001 (http/https) |
Behind Nginx TLS |
| Reload | Hot-reload | Static build |
| Sidecars | Skipped | Enabled (cron/backup/certbot) |
| Certs | ssl-dev/ self-signed |
ssl/ auto-renew |
Set with npx wrangler secret put <NAME> (non-secret vars live in wrangler.toml [vars]):
JWT_SECRET=change_me
RESEND_API_KEY=re_xxx # sending via Resend (domain verified: bibliotecamoleculares.com)
INBOX_NOTIFY_TO=you@example.com # personal Gmail that gets "new message" alerts from the contact inbox
KIOSK_ALLOWED_IP=143.107.90.22,143.107.79.0/24,2804:14d:5cd2:8000::/64KIOSK_ALLOWED_IP gates proaluno logins to the kiosk. It takes a comma-separated
list of addresses and/or CIDR prefixes, IPv4 and IPv6, matched against cf-connecting-ip
(worker/src/ipAllowList.ts). Prefixes matter: the kiosk's public IPv4 is not static, and
since the zone has AAAA records the browser may arrive over IPv6, whose address rotates
within the /64. To read the address Cloudflare actually sees, open
https://bibliotecamoleculares.com/cdn-cgi/trace on the kiosk and look at ip=.
Unset, it falls back to the single address 143.107.90.22.
Email addresses: all automatic mail is sent from avisos@bibliotecamoleculares.com
(outbound-only β no mailbox, accidental replies bounce). The human address is
contato@bibliotecamoleculares.com: Cloudflare Email Routing delivers it to the Worker's
email handler (worker/src/services/emailInbox.ts), which stores it in D1 and notifies
INBOX_NOTIFY_TO. Admins read and reply from the panel ("Emails" tab), replies go out
from contato@ via Resend. Routing rule required: contato@ β Send to a Worker β
biblioteca-api. Do not create a rule or catch-all for avisos@.
After running bash scripts/setup-aliases.sh once:
# Development
dev # Interactive development menu
save # Git add + commit + push (prompts for message)
# Production (VPS)
deploy # Git pull + restart with SSL & prune
restart # Restart containers with cleanup
rebuild # Full rebuild from scratch
# Monitoring
logs # Live container logs
status # Container status
stop # Stop all containers
# Database
db # Open SQLite CLI
seed # Populate database with sample data
backup # Manual backup to Google Drive
scrape # Update USP disciplines
# Utilities
aliases # Show all available commands
biblioteca # Navigate to project directoryOption 1: Interactive Menu (Recommended)
npm run dev
# or just: dev (if aliases are set up)Choose from 6 development modes:
- Full Docker Compose (frontend + backend)
- Frontend only (Vite dev server)
- Backend in Docker + Frontend local (hot-reload)
- Backend only (nodemon)
- Backend Docker only
- Both frontend + backend local (best DX!)
Option 2: Manual Docker Compose
docker compose -f docker-compose.dev.yml up --buildOn VPS:
cd MolecularSciencesLibrary
git pull
npm run start
# or just: deploy (if aliases are set up)The production script automatically:
- Stops existing containers
- Cleans old images (
docker system prune) - Copies SSL certificates
- Starts fresh containers
- Shows status
| Script | Command | Purpose |
|---|---|---|
| Development | ||
start-dev.sh |
npm run dev / dev |
Interactive development menu with 6 modes |
save.sh |
save "message" |
Quick git add + commit + push |
| Production | ||
start-production.sh |
npm run start / restart |
Deploy with SSL + cleanup |
setup-aliases.sh |
Run once | Configure global shortcuts |
show-aliases.sh |
aliases |
Display all available commands |
| Database | ||
seed_database.js |
npm run seed / seed |
Populate with sample data |
importCsv.js |
npm run import:csv file.csv |
Import books from CSV |
clean_test_scenarios.js |
npm run clean:test |
Remove test data |
| Maintenance | ||
backup_db_to_gdrive.sh |
npm run backup / backup |
Upload DB to Google Drive |
scrapeUSPDisciplines.js |
npm run scrape:disciplines / scrape |
Update USP course catalog |
checkOverdues.js |
Cron daily | Check overdue loans + send emails |
troubleshoot.sh |
npm run troubleshoot |
System diagnostics |
Background Services (Production only):
cronβ Daily overdue checks & notificationsbackupβ Daily Google Drive backupscertbotβ Automatic SSL renewal
- π Add Book β generate code + EAN13.
- π’ Borrow β validate policy, send email.
- π Renew β enforce max, update due_date.
- β³ Extension β post max renewals only.
- π¬ Nudge β email + optional due_date shorten.
- β©οΈ Return β mark loan + email.
- ποΈ Virtual Shelf β admin sets ranges, UI highlights.
/books (GET filter, POST add, DELETE, POST borrow|return)
/loans (GET, POST create, PUT renew, PUT extend)
/rules (GET, PUT)
/notifications (GET, POST, PATCH read)
/users (POST create, POST login, GET /me)
/virtual-bookshelf (GET, PUT config)
/forms/submit (help form)π Auth β Bearer JWT.
| Service | Purpose | Frequency |
|---|---|---|
cron |
Overdues, reminders, nudges | Daily |
backup |
Upload DB to Google Drive | Daily |
certbot |
TLS renew & reload Nginx | Daily |
We welcome all contributionsβcode, docs, design, or even book donations.
- Fork β clone.
- Branch:
feat/<desc>,fix/<desc>... - Commit:
git commit -m "feat(books): add language filter". - Push β PR with rationale + screenshots/tests.
Quick commit: Use save "your message" for instant add + commit + push! π
- No secrets in commits.
- Clear, minimal scope.
- Follow emoji logging.
- Keep API stable.
- βοΈ Small, pure functions.
- β Controllers thin, Services clean.
- π§© Expand TS types (no
any). - π§ͺ Planned: Vitest/Jest, Supertest, Playwright.
- π Avoid N+1 DB queries.
- Virtual bookshelf editing.
- Developer automation scripts.
- Interactive development menu.
- Global command aliases.
- Automated deployment workflow.
- Stronger type safety.
- Automated test suite.
- CSV import/export UI.
- i18n framework.
- PWA offline mode.
- Postgres adapter.
- Analytics & dashboards.
- π Rotate JWT secrets.
- πͺ Consider httpOnly cookies for tokens.
- π§Ή Input sanitization (future: schema validation).
- π§ Use app passwords for SMTP.
- π Regular
npm audit+docker scan.
Released into the public domain. Do whatever you wantβuse, remix, fork.
Attribution is optional, but deeply appreciated.
π To the CM-USP communityβstudents, alumni, staff, donorsβwho believe shared knowledge compounds. π‘ Special thanks to early collaborators & testers.
Build something. Improve something. Share it back. PRs are openβso is the library.
Made with curiosity & care by students of CiΓͺncias Moleculares