Skip to content

Repository files navigation

πŸ“š Molecular Sciences Library (Biblioteca do curso de CiΓͺncias Moleculares da USP)

License: Unlicense PRs Welcome Made with ❀️ by Students.

β€œ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.


πŸš€ Quick Start (for the impatient)

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

Pro tip: After setup, just type dev from anywhere to start! 🎯


πŸ“‘ Table of Contents


1. Vision & Philosophy

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.


2. Feature Overview

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.

3. Architecture & Technology Stack

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

4. Directory Structure (Condensed)

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)

5. Data & Domain Model (High-Level)

  • 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).

6. Logging & Conventions

Emoji stages keep logs scannable:

  • πŸ”΅ Start
  • 🟒 Success
  • 🟑 Warning/alternate
  • πŸ”΄ Error

7. Environments (Development vs Production)

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

8. Environment Variables (Worker Secrets)

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::/64

KIOSK_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@.


9. Running the Project

Quick Commands (with aliases)

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 directory

Development

Option 1: Interactive Menu (Recommended)

npm run dev
# or just: dev (if aliases are set up)

Choose from 6 development modes:

  1. Full Docker Compose (frontend + backend)
  2. Frontend only (Vite dev server)
  3. Backend in Docker + Frontend local (hot-reload)
  4. Backend only (nodemon)
  5. Backend Docker only
  6. Both frontend + backend local (best DX!)

Option 2: Manual Docker Compose

docker compose -f docker-compose.dev.yml up --build

Production

On 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

10. Developer Scripts & Automation

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 & notifications
  • backup β†’ Daily Google Drive backups
  • certbot β†’ Automatic SSL renewal

11. Core Workflows

  • πŸ“– 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.

12. API Surface (Snapshot)

/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.


13. Background Tasks

Service Purpose Frequency
cron Overdues, reminders, nudges Daily
backup Upload DB to Google Drive Daily
certbot TLS renew & reload Nginx Daily

14. Contribution Guide (Pull Requests)

We welcome all contributionsβ€”code, docs, design, or even book donations.

Steps

  1. Fork β†’ clone.
  2. Branch: feat/<desc>, fix/<desc>...
  3. Commit: git commit -m "feat(books): add language filter".
  4. Push β†’ PR with rationale + screenshots/tests.

Quick commit: Use save "your message" for instant add + commit + push! πŸš€

Guidelines

  • No secrets in commits.
  • Clear, minimal scope.
  • Follow emoji logging.
  • Keep API stable.

15. Code Quality, Style & Testing

  • ✍️ Small, pure functions.
  • βœ… Controllers thin, Services clean.
  • 🧩 Expand TS types (no any).
  • πŸ§ͺ Planned: Vitest/Jest, Supertest, Playwright.
  • πŸ“Š Avoid N+1 DB queries.

16. Roadmap

  • 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.

17. Security & Hardening

  • πŸ”‘ Rotate JWT secrets.
  • πŸͺ Consider httpOnly cookies for tokens.
  • 🧹 Input sanitization (future: schema validation).
  • πŸ“§ Use app passwords for SMTP.
  • πŸ” Regular npm audit + docker scan.

18. License (Public Domain – The Unlicense)

Released into the public domain. Do whatever you wantβ€”use, remix, fork.

Attribution is optional, but deeply appreciated.


19. Acknowledgements

πŸ™ 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

Releases

Packages

Used by

Contributors

Languages