Skip to content

About

A full-stack Flask bookstore with user accounts, persistent cart, order history, and a simulated checkout that validates card details without a real payment gateway. Features a 9-book curated catalog, CSS-gradient covers, hashed passwords, and Flask-Login session auth.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

15 Commits

Folders and files

Repository files navigation

📚 Marginalia

Slower reading, on purpose.

Marginalia is a full-stack online bookstore built with Flask. Nine curated books, chosen rather than algorithmically recommended, across genres like Memoir, Fiction, Essays, and Nature. It features real user accounts, a persistent cart, order history, and a simulated checkout flow that validates payment details like a real gateway would, without ever contacting one.


✨ Features

  • 📖 Browse a curated catalog, filterable by genre
  • 🎨 CSS-gradient book covers — no image assets needed, each book's cover is generated from a two-color gradient stored in the database
  • 🔐 User accounts — registration and login with hashed passwords (Werkzeug) and session management via Flask-Login
  • 🛒 Persistent cart — add, increase/decrease quantity, or remove items, synced to your account
  • 💳 Simulated checkout — validates card number (Luhn algorithm), expiry, and CVC like a real payment form, without ever contacting a real payment processor
  • 🧾 Order history — past orders are saved with item snapshots (title, author, price at time of purchase), so catalog edits never affect historical orders
  • 🚦 Flash messaging for errors, confirmations, and info across the app
  • ⚠️ Custom error pages for 404 and 403

🛠️ Tech Stack

  • Python 3 + Flask — routing and server-side logic
  • Flask-SQLAlchemy — ORM and database models
  • Flask-Login — session-based authentication
  • Werkzeug Security — password hashing
  • SQLite — database (marginalia.db)
  • Jinja2 — server-side templating, with a reusable cover() macro
  • HTML5 / CSS3 — custom-styled frontend, no CSS framework
  • Google Fonts — Fraunces (headings) & Work Sans (body)

📁 Project Structure

marginalia/
├── app.py                       # Routes and application setup
├── extensions.py                # Shared Flask extension instances (db, login_manager)
├── models.py                    # SQLAlchemy models: User, Book, CartItem, Order, OrderItem
├── seed_data.py                 # Fixed catalog of 9 books, seeded on first run
├── templates/
│   ├── base.html                # Shared layout, nav, and flash messages
│   ├── index.html               # Catalog with genre filtering
│   ├── book_detail.html         # Single book page
│   ├── cart.html                # Cart contents and totals
│   ├── checkout.html            # Simulated payment form
│   ├── success.html             # Order confirmation
│   ├── orders.html              # Order history
│   ├── login.html               # Login form
│   ├── register.html            # Registration form
│   ├── error.html               # Shared 404 / 403 page
│   └── _macros.html             # Reusable `cover()` gradient macro
├── static/
│   └── css/
│       └── style.css            # Stylesheet
└── README.md

🗄️ Data Model

Model Key Fields
User name, email (unique), password_hash, created_at
Book title, author, genre, price_cents, description, stock, cover_from, cover_to
CartItem user_id, book_id, quantity (unique per user/book pair)
Order user_id, total_cents, status, card_last4, created_at
OrderItem order_id, book_id, title, author, quantity, price_cents (snapshotted at purchase time)

The catalog is seeded automatically from seed_data.py the first time the app runs, so marginalia.db doesn't need to exist beforehand.


▶️ Getting Started

Prerequisites

pip install flask flask-sqlalchemy flask-login

Running the App

git clone https://github.com/rhitamcoder/marginalia.git
cd marginalia
python app.py

The app will start in debug mode at http://127.0.0.1:5000/. On first run, the database and catalog are created automatically.


🔐 Security Note

This project is a coursework / portfolio demonstration, not a production application. app.py uses os.environ.get("SECRET_KEY", "dev-secret-change-me"), a placeholder fallback intended only for local development, and no SECRET_KEY environment variable is configured for this repo.

Real user accounts should not be created on any public instance of this app, and it is not intended to be deployed for real-world use. The Flask-Login authentication and the checkout flow exist to demonstrate full-stack skills (auth, sessions, ORM relationships, server + client-side validation), not to handle real credentials or real payments.


💳 About the Simulated Checkout

This project doesn't integrate a real payment gateway. The checkout form validates card number (via the Luhn algorithm), expiry format, and CVC exactly like a real one would, but no card network is ever contacted and no money moves. On successful validation, it writes a real Order and OrderItem record, the same way a webhook from an actual processor would, so the cart, auth, and order history logic are all fully functional and wouldn't need to change if a real gateway were added later.


📝 License

This project is licensed under the MIT License — see the LICENSE file for details.

About

A full-stack Flask bookstore with user accounts, persistent cart, order history, and a simulated checkout that validates card details without a real payment gateway. Features a 9-book curated catalog, CSS-gradient covers, hashed passwords, and Flask-Login session auth.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages