An educational full-stack portfolio project built to practise application structure, backend development, databases, authentication, security concepts, and deployment.
This Library Management System is a personal educational and portfolio project. It is not a commercial product or production-ready library management service.
The application was built to help me develop my understanding of full-stack web development by working on a larger project with multiple connected features and components.
Please do not enter real personal information, passwords, email addresses, addresses, or other sensitive information into the application.
The data used within the application is demonstration data and may be changed, reset, or deleted during development.
Some images used for books and libraries are included as demonstration or placeholder content to help create a more realistic application.
The images and associated artwork remain the property of their respective copyright holders. No ownership of these images is claimed.
This is a full-stack library management application built using Python, Flask, SQLAlchemy, SQLite, HTML, and CSS.
The application allows customers to browse libraries and books, create accounts, manage loans, and leave reviews.
Staff members have access to a separate area where they can manage books, loans, library information and staff-related functionality. Managers have additional permissions for managing staff accounts and library information.
The main purpose of this project was to move beyond smaller applications and gain experience working with a larger codebase containing multiple connected systems.
While building the project, I practised working with:
- Relational databases and database relationships with SQLAlchemy.
- Authentication and authorisation.
- Server-side validation.
- CRUD operations.
- File uploads.
- Session management.
- Web security concepts.
- Application structure and organisation.
- Database migrations.
- Deployment.
This project is for educational and demonstration purposes and should not be considered a production-ready library management system.
This project represents an important stage in my development as I continue learning full-stack web development.
One of my main goals was to gain experience working with a larger application rather than repeatedly building small and isolated features.
I used the project to practise separating responsibilities into areas such as:
- Routes.
- Services.
- Validators.
- Database models.
- Configuration.
- Templates.
- Static assets.
This helped me better understand how different parts of an application can have separate responsibilities while working together to achieve a larger objective.
The project is not perfect, and there are areas that could be improved. I have encountered bugs, inconsistencies and development issues while building it, including occasional circular import problems.
However, I decided to publish the project because I believe it is important to continue building, deploying and learning from complete projects rather than waiting until every project feels perfect.
My aim is to build more applications, gain repetition through practice, identify mistakes, and gradually improve my development skills with each project.
Through this project, I have continued developing my understanding of:
- Python.
- Flask.
- SQLAlchemy 2.0.
- Relational databases.
- Backend architecture.
- Database relationships.
- Input validation.
- Authentication and authorisation.
- Web security concepts.
- File handling and uploads.
- Database migrations.
- Application deployment.
Customers can:
- Register and log in.
- Reset their password.
- Browse libraries.
- Browse books.
- Search for books and libraries.
- View library information.
- View book information.
- Leave reviews.
- View their active loans.
Staff members can:
- Log in to the staff area.
- View active loans.
- Manage books.
- Add books to their library.
- Manage library inventory.
- Update library information.
- Upload images.
Managers have additional permissions and can:
- Add staff accounts.
- Disable staff accounts.
- Reset staff passwords.
- Change staff roles.
- Manage additional library information.
The project uses role-based authorisation, allowing different users to access functionality depending on their role.
The following accounts are demonstration accounts only.
Email: customer1@email.com
Password: Library12345!
Email: staff1@email.com
Password: Library12345!
All demonstration accounts use the same password:
Library12345!
The demonstration data follows an incremental naming pattern.
For example:
customer1@email.com
customer2@email.com
customer3@email.com
staff1@email.com
staff2@email.com
staff3@email.com
These credentials are publicly available demonstration credentials and must never be reused for real accounts or services.
The application contains fictional demonstration data created for testing and portfolio purposes.
Please do not enter:
- Real personal information.
- Real passwords.
- Sensitive information.
- Private addresses.
- Payment information.
Demonstration data may be changed, reset or deleted during development.
The application is organised into separate areas for routes, services, database models, templates and static assets.
library-1/
│
├── app.py
├── config.py
├── extensions.py
├── security.py
├── requirements.txt
├── README.md
├── LICENCE
│
├── database/
│ └── models/
│ └── Database models
│
├── migrations/
│
├── routes/
│ └── Application routes
│
├── services/
│ └── Application logic and functions
│
├── static/
│ ├── css/
│ ├── js/
│ └── media/
│
└── templates/
├── customer_pages/
├── error_pages/
├── home_pages/
└── staff_pages/
The structure has evolved throughout development as I have learned more about organising larger applications.
Earlier in my development, I used traditional SQL queries directly within my functions.
For example:
SELECT * FROM Customer_Table;This was useful for learning because it helped me understand how SQL statements work and how information is retrieved from a database.
As the project developed, I moved towards SQLAlchemy 2.0 and its ORM approach.
This allowed me to work with database tables through Python models and constructs such as:
select()
insert()
update()For example:
query = select(Customer)
result = db.session.execute(query).scalars().all()Using SQLAlchemy has helped me understand the relationship between Python objects and database records while providing a more structured approach to database queries.
Learning traditional SQL before working more extensively with SQLAlchemy was valuable because it helped me understand the underlying concepts rather than only relying on the abstraction provided by an ORM.
This reflects the approach I am trying to follow throughout my development:
Learn the fundamentals first, then learn how established libraries and frameworks can build upon those fundamentals.
During the development of this project, I also learned how to use Flask-Migrate for managing changes to the database structure.
Database migrations allow changes to models and database schemas to be tracked and applied more safely than manually recreating the entire database.
This became particularly useful while developing and testing the project because the database structure changed several times as I learned more about data types, relationships and model design.
Security has been an important learning area throughout this project.
The application includes several security-related features and practices.
These features are part of my learning process and should not be interpreted as a guarantee that the application is completely secure or production-ready.
Passwords are hashed using Argon2 rather than being stored as plain text.
Flask-WTF CSRF protection is used to help protect forms against unauthorised cross-site requests.
Server-side validation is used for various types of information, including:
- Email addresses.
- Passwords.
- Telephone numbers.
- IDs and numeric values.
- Dates and times.
- Addresses.
- Roles.
- Text input.
The application uses server-side session management with security settings including:
- Secure cookies.
- SameSite restrictions.
- Session expiry.
Flask-Limiter is used to help restrict excessive requests to certain areas of the application.
A Content Security Policy (CSP) is implemented to help restrict where certain resources, such as scripts and images, can be loaded from.
The application restricts uploaded files to supported image types and applies request size limits before files are uploaded.
Images are stored using Cloudinary.
| Technology | Purpose |
|---|---|
| Python | Backend programming language. |
| Flask | Web framework and application structure. |
| SQLAlchemy 2.0 | Database ORM and query construction. |
| SQLite | Development database. |
| Jinja | Server-side HTML templating. |
| HTML5 | Website structure. |
| CSS3 | Styling and responsive layouts. |
| JavaScript | Client-side functionality. |
| Argon2 | Password hashing. |
| Flask-WTF | CSRF protection. |
| Flask-Limiter | Request rate limiting. |
| Flask-Migrate | Database migrations. |
| Flask-Session | Server-side session management. |
| Cloudinary | Image storage and delivery. |
git clone <repository-url>cd library-1python -m venv venvsource venv/bin/activatevenv\Scripts\activatepip install -r requirements.txtCreate a .env file containing the required environment variables.
SECRET_KEY=your_secret_key
DATABASE_URL=your_database_url
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret
Do not upload real secrets or environment variables to a public repository.
python app.pyThere are many areas that could be improved as I continue learning.
Some potential improvements include:
- Automated testing.
- Improved error handling and logging.
- Further database optimisation.
- Improved accessibility.
- Additional authorisation checks.
- More API functionality.
- Further code refactoring.
- PostgreSQL for a more production-style database environment.
- Improved user interface design.
- Improved responsive layouts.
- Additional pagination.
- Improved login and password reset processes.
- Better timezone handling.
- More efficient code in certain areas.
- Increased client-side interactivity.
- Improved image dimension validation.
- Further security improvements.
There are undoubtedly other improvements and bugs that I have not yet identified.
However, I have chosen to publish the project at this stage because the purpose of my portfolio is to demonstrate my learning and development over time.
I do not want to spend an unlimited amount of time attempting to perfect one educational project before moving forward.
Instead, I want to continue building projects, deploying them, learning from mistakes and applying what I learn to future applications.
This project represents my development at this particular stage of my learning journey rather than a finished example of production-quality software.
This project is licensed under the MIT Licence.
See the LICENCE file for the full licence.
MIT Licence
Copyright (c) 2026 Sheikh Hussain
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.