6 Checkpoints on the Software Developer Journey
6.1 Looks anf Feels by HTML
This tutorial provides an introduction to essential HTML elements and styling techniques. For more detailed information, visit the MDN Web Docs.
6.1.1 Section Heading
HTML headings are defined with the <h1> to <h6> tags. Here’s an example of a section heading:
<h2>Section Heading Example</h2>Render:
Section Heading Example
6.1.2 Paragraphs, Divs, and Spans
- Paragraphs are defined with the
<p>tag. - Divs are used as block-level containers with the
<div>tag. - Spans are used for inline styling with the
<span>tag.
Example:
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
<div>This is a div</div>
<div>This is another div</div>
<span>This text is inside a span.</span>
<span>This another text is inside a span.</span>Render:
This is a paragraph.
This is another paragraph.
The HTML code provided consists of two paragraph elements (<p>), two division elements (<div>), and two span elements (<span>). Each of these elements serves a different purpose in the structure and styling of a webpage:
- Paragraph (
<p>) Elements: Define paragraphs, typically resulting in a visual break with a new line and space before and after the text. - Division (
<div>) Elements: Serve as containers to segment the page vertically. They do not inherently cause any visual break or create space unless styled with CSS. - Span (
<span>) Elements: Inline elements used to group or apply styles to parts of a text within other elements. They do not cause any line breaks or add extra space.
This comparison shows how HTML tags dictate the structure and flow of content on a webpage, affecting how text and containers appear in the browser.
6.1.3 Simple Text Styling
HTML provides several tags for styling text:
- Bold:
<strong>bold text</strong>or<b>bold text</b> - Italic:
<em>italic text</em>or<i>italic text</i> - Underline:
<u>underlined text</u>
Example:
<p>This is <strong>bold</strong>, <em>italic</em>, and <u>underlined</u> text.</p>This is bold, italic, and underlined text.
6.1.4 Lists
6.1.4.1 Ordered List
An ordered list is defined with the <ol> tag.
<ol>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</ol>- First item
- Second item
- Third item
6.1.4.2 Unordered List
An unordered list is defined with the <ul> tag.
<ul>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</ul>- First item
- Second item
- Third item
6.1.5 Images
Images are inserted using the <img> tag, which requires the src, alt, width, and height attributes.
<img src="https://loremflickr.com/640/480/abstract" alt="Description of image" width="300" height="200">6.1.6 Tables
Tables are defined with the <table> tag, and include rows (<tr>) and cells (<td> for data, <th> for headers).
<table>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
<tr>
<td>Data 1</td>
<td>Data 2</td>
</tr>
</table>| Header 1 | Header 2 |
| Data 1 | Data 2 |
6.1.7 Further Information
For more detailed information on HTML elements, visit the HTML Elements Reference on MDN.
6.2 Deploy Django Server on DigitalOcean
6.2.1 Infrastructure as a Service
Since we are deploying our Django application on DigitalOcean, we don’t need to worry about physical hardware. Instead, we leverage DigitalOcean’s cloud infrastructure, which provides us with virtualised resources. These resources are part of what is known as Infrastructure as a Service (IaaS), where the provider (DigitalOcean) manages the physical servers, storage, and networking.
6.2.2 Key Components of DigitalOcean
Droplets: In DigitalOcean, the virtual servers are called Droplets. These Droplets are essentially virtual machines with dedicated CPU, memory, and storage resources. Depending on your application’s needs, you can choose a Droplet with the appropriate amount of resources. For example, you might start with a basic Droplet with 1 GB of RAM and 1 vCPU for a small application and scale up as needed.
Scalability: One of the key advantages of using cloud services like DigitalOcean is scalability. You can easily resize your Droplet or add more Droplets to your setup as your application grows, without needing to worry about purchasing or maintaining physical hardware.
Backup and Redundancy: DigitalOcean provides options for automated backups and snapshots, which are critical for maintaining data integrity and ensuring that you can recover your application in case of failure.
6.2.3 Software of Choice
In deploying your Django application on DigitalOcean, several key software components are required to ensure a stable, secure, and efficient production environment. Below are the specific versions of the software used in this deployment setup:
Operating System: The Droplet runs Ubuntu 24.04 LTS (GNU/Linux 6.8.0-40-generic x86_64). Ubuntu is a popular Linux distribution known for its stability, security, and extensive support in server environments, making it an ideal choice for hosting web applications.
Python: Python 3.12.3 is used to run Django. Python is the core language for Django, and ensuring compatibility with the version used in development is crucial for avoiding runtime issues.
Django: The application is built with Django 5.1, a high-level Python web framework that encourages rapid development and clean, pragmatic design. Django handles everything from database queries to rendering HTML.
Gunicorn: Gunicorn 23.0.0 serves as the WSGI HTTP server. Gunicorn is a robust, scalable server that handles the communication between the web server (Nginx) and your Django application.
Nginx: Nginx 1.24.0 is used as the web server. Nginx is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption. It acts as a reverse proxy, handling client requests, serving static files, and passing requests to Gunicorn for dynamic content.
SQLite: SQLite 3.45.1 is the database used for this deployment. While SQLite is often used for development and testing due to its simplicity, it can also be used in production environments where a lightweight, file-based database is sufficient.
HTTP/HTTPS: Currently, the setup uses HTTP 1.1. However, it is crucial to upgrade to HTTPS to ensure secure communication between the client and server. This upgrade involves obtaining an SSL/TLS certificate and configuring Nginx to handle HTTPS traffic.
This software stack ensures that your Django application is running on a solid foundation, with each component playing a critical role in delivering a secure, scalable, and efficient web service.
Diagram:
6.2.4 Clone Django Project and Activate Python
- Clone the Repository: This command clones the Django project from the GitHub repository to your local machine.
- Navigate to the Project Directory: After cloning, navigate into the project directory.
- Create a Virtual Environment: This command creates a virtual environment named .venv inside your project directory.
- Activate the Virtual Environment: This command activates the virtual environment, allowing you to install packages specific to your project without affecting the global Python environment.
- Create a new secret key for Django production server.
git clone https://github.com/jeremy886/mvp24.git
cd mvp24
python -m venv .venv
source .venv/bin/activate
echo "export SECRET_KEY='$(openssl rand -hex 40)'" > .DJANGO_SECRET_KEY
source .DJANGO_SECRET_KEY6.2.5 Install Django and Gunicorn
Install Django and Gunicorn:
python -m pip django
python -m pip install gunicornRun server:
- test django server
- test gunicorn
- run gunicorn and keep alive after logout using
nohup and &
# test django server
python manage.py runserver '0.0.0.0:8888'
# test gunicorn
source .DJANGO_SECRET_KEY
export DJANGO_SETTINGS_MODULE='mvp24.settings.production'
gunicorn --workers 1 --bind 0.0.0.0:8888 mvp24.wsgi:application
nohup gunicorn --workers 1 --bind 0.0.0.0:8888 mvp24.wsgi:application & You also need to set up your domain name so you can visit http://cyber.mrchen.store:8888.
Kill gunicorn after testing.
pgrep gunicorn # view jobs
pkill -f gunicorn # kill jobs6.2.6 Django Settings for Production and Development
mvp24/settings/base.pyproduction.pydevelopment.py
mvp24/settings/base.py
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent.parent # add .parent due to base.py
import os
try:
SECRET_KEY = os.environ["SECRET_KEY"]
except KeyError as e:
raise RuntimeError("Could not find a SECRET_KEY in environment") from e
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'crm.apps.CrmConfig',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'mvp24.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates']
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'mvp24.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/
LANGUAGE_CODE = 'en-au'
TIME_ZONE = 'Australia/Melbourne'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/
# URL to use when referring to static files
STATIC_URL = '/static/'
# Additional locations to search for static files
STATICFILES_DIRS = [
BASE_DIR / 'static', # Include additional directories here
]
# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Redirect to home URL after login (Default redirects to /accounts/profile/)
LOGIN_REDIRECT_URL = '/'
# Also redirect to home after logout
LOGOUT_REDIRECT_URL = '/'mvp24/settings/development.py
from .base import *
DEBUG = True
# The directory where static files will be collected
STATIC_ROOT = BASE_DIR / 'staticfiles'
ALLOWED_HOSTS = []mvp24/settings/production.py
# production.py
from .base import *
DEBUG = False
# The directory where static files will be collected
STATIC_ROOT = '/var/www/cyber.mrchen.store/static'
ALLOWED_HOSTS = ['localhost', 'cyber.mrchen.store']Create the directory for static files:
(.venv) $ sudo mkdir -pv /var/www/cyber.mrchen.store/static/
(.venv) $ sudo chown -cR jeremy:jeremy /var/www/cyber.mrchen.store/static6.2.7 Setup Gunicorn
Create config/gunicorn/prod.py
conf/gunicorn/prod.py
"""Gunicorn *production* config file"""
# Django WSGI application path in pattern MODULE_NAME:VARIABLE_NAME
wsgi_app = "mvp24.wsgi:application"
# The granularity of Error log outputs
loglevel = "info"
# The number of worker processes for handling requests
workers = 1
# The socket to bind
bind = "0.0.0.0:8888" # Use standard HTTP port
# Reload is disabled in production
reload = False
# Write access and error info to /var/log
accesslog = errorlog = "/var/log/gunicorn/prod.log"
# Redirect stdout/stderr to log file
capture_output = True
# PID file so you can easily fetch process ID
pidfile = "/var/run/gunicorn/prod.pid"
# Daemonize the Gunicorn process (detach & enter background)
daemon = TrueSudo commands to set up log files
sudo mkdir -pv /var/{log,run}/gunicorn/
sudo chown -cR jeremy:jeremy /var/{log,run}/gunicorn/ # jeremy:jeremyTest gunicorn settings
gunicorn -c config/gunicorn/prod.py
tail -f /var/log/gunicorn/prod.logRemember to kill gunicorn jobs after testing.
6.2.8 Set up HTTP Server Nginx
Install Nginx
apt-get install -y nginx
nginx -v
systemctl start nginx
systemctl status nginxNginx config file
/etc/nginx/sites-available/cyber
server_tokens off;
access_log /var/log/nginx/supersecure.access.log;
error_log /var/log/nginx/supersecure.error.log;
# This configuration will be changed to redirect to HTTPS later
server {
server_name .cyber.mrchen.store;
listen 80;
location / {
proxy_pass http://localhost:8888;
proxy_set_header Host $host;
}
location /static {
autoindex on;
alias /var/www/cyber.mrchen.store/static/;
}
}
Test Nginx Config File
service nginx configtest /etc/nginx/sites-available/cyberEnable Site Configuration
cd /etc/nginx/sites-enabled
ln -s ../sites-available/cyber .Restart Ngnix
systemctl reload nginx6.2.9 Turning on HTTPS
An SSL/TLS certificate is like a digital ID card for websites, confirming their identity and enabling secure, encrypted connections between the site and its users. This encryption protects sensitive information, like passwords and credit card numbers, ensuring it can’t be intercepted or altered during transmission.
Let’s Encrypt is a free service that provides these SSL/TLS certificates. It automates the process of getting and renewing certificates, making it easy for anyone to secure their website with HTTPS, which is the secure version of HTTP. This ensures that data shared on the site stays private and protected.
sudo apt-get update -y
sudo apt-get install certbot python3-certbot-nginx -y
sudo certbot --nginx -d cyber.mrchen.storeResult:
Requesting a certificate for cyber.mrchen.store
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/cyber.mrchen.store/fullchain.pem
Key is saved at: /etc/letsencrypt/live/cyber.mrchen.store/privkey.pem
This certificate expires on 2024-11-15.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Deploying certificate
Successfully deployed certificate for cyber.mrchen.store to /etc/nginx/sites-enabled/cyber
Congratulations! You have successfully enabled HTTPS on https://cyber.mrchen.store
Certbot will be run twice a day.
$ sudo systemctl status certbot
○ certbot.service - Certbot
Loaded: loaded (/usr/lib/systemd/system/certbot.service; static)
Active: inactive (dead)
TriggeredBy: ● certbot.timer
Docs: file:///usr/share/doc/python-certbot-doc/html/index.html
https://certbot.eff.org/docs
$ sudo systemctl status certbot.timer
● certbot.timer - Run certbot twice daily
Loaded: loaded (/usr/lib/systemd/system/certbot.timer; enabled; preset: enabled)
Active: active (waiting) since Sat 2024-08-17 11:02:25 UTC; 13min ago
Trigger: Sat 2024-08-17 17:34:49 UTC; 6h left
Triggers: ● certbot.serviceThis is the updated Nginx configuration file:
/etc/nginx/sites-available/cyber
server_tokens off;
access_log /var/log/nginx/supersecure.access.log;
error_log /var/log/nginx/supersecure.error.log;
# This configuration will be changed to redirect to HTTPS later
server {
server_name .cyber.mrchen.store;
location / {
proxy_pass http://localhost:8888;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /static {
autoindex on;
alias /var/www/cyber.mrchen.store/static/;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/cyber.mrchen.store/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/cyber.mrchen.store/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = cyber.mrchen.store) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name .cyber.mrchen.store;
listen 80;
return 404; # managed by Certbot
}Test Nginx Configuration file:
sudo nginx -tIf okay, then restart Nginx:
sudo systemctl reload nginxEasier Way to Run the Server
Remembering all the necessary commands can be challenging, so let’s simplify the process by putting them into a script that you can run with a single command.
source ./run_server.sh productionrun_server.sh
#!/bin/bash
# Check for the correct number of arguments
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <environment>"
echo "Where <environment> is 'development' or 'production'."
exit 1
fi
# Set the DJANGO_SETTINGS_MODULE based on the argument
if [ "$1" == "development" ]; then
export DJANGO_SETTINGS_MODULE='mvp24.settings.development'
elif [ "$1" == "production" ]; then
export DJANGO_SETTINGS_MODULE='mvp24.settings.production'
else
echo "Invalid environment: $1"
echo "Please choose 'development' or 'production'."
exit 1
fi
# Generate a new secret key
# echo "export SECRET_KEY='$(openssl rand -hex 40)'" > .DJANGO_SECRET_KEY
source .DJANGO_SECRET_KEY
# Print the settings being used
echo "Starting Django server with settings: $DJANGO_SETTINGS_MODULE"
echo "Using SECRET_KEY: $SECRET_KEY"
# Collect static files in production
if [ "$1" == "production" ]; then
echo "Collecting static files..."
python manage.py collectstatic --noinput
fi
# Start the server
# For development:
if [ "$1" == "development" ]; then
python manage.py runserver
# For production, assuming you use gunicorn:
elif [ "$1" == "production" ]; then
gunicorn -c config/gunicorn/prod.py
fi6.2.10 Firewall
6.2.11 Introduction to UFW
UFW (Uncomplicated Firewall) is a user-friendly tool designed to help configure and manage iptables firewall rules on Linux systems. It simplifies the process of setting up basic firewall policies, allowing you to easily control incoming and outgoing traffic to your server. UFW is particularly useful for securing applications like Django, providing a straightforward way to enforce security measures and protect your server from unauthorized access.
To showcase networking functionalities, the firewall is inactive currently. Remember to activate UFW or another firewall solution after the demonstration to secure your server.
6.2.12 UFW Configuration for a Django Application
1. Install UFW:
sudo apt-get update
sudo apt-get install ufw2. Allow SSH Access:
sudo ufw allow 22/tcp3. Allow HTTP and HTTPS Traffic:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp4. Restrict MySQL/PostgreSQL Access (if applicable):
sudo ufw allow from 127.0.0.1 to any port 3306 # MySQL
sudo ufw allow from 127.0.0.1 to any port 5432 # PostgreSQL5. Enable UFW:
sudo ufw enable6. Check UFW Status:
sudo ufw status verbose7. Deny All Other Incoming Traffic:
sudo ufw default deny incoming
sudo ufw default allow outgoing8. Allow Other Necessary Services:
sudo ufw allow 2222/tcp # Example for a custom SSH port9. Advanced: Rate Limiting:
sudo ufw limit ssh/tcp10. Disabling or Resetting UFW:
sudo ufw disable
sudo ufw reset6.2.13 Commands to Run the Server:
cd DjangoProjects/mvp24 && source .venv/bin/activate
source run_server.sh production6.2.14 Credit
Adapted from:
6.3 How To Upgrade Your Server
6.3.1 Ongoing Development
(.venv) $ git log --oneline --decorate --graph --all
* 85f2d19 (HEAD -> production, origin/production) Merge branch 'feature/event' into production
|\
| * bdf660c (origin/feature/event, feature/event) add quiz app, change home page
| * 8ffde36 start a new branch and add event
* | 4c29357 update gitignore
|/
* 32641b3 make home page responsive with bootstrap
| * ad081d9 (origin/main, main) Merge branch 'production'
| |\
| |/
|/|
* | a534d23 udpate gitignore
* | 2071b38 update manage.py for development settings
* | 72808e9 add run_server.sh
* | 44bbc47 add gunicorn config
* | 7d4db21 add image to home page
| * 39987bb add gunicorn config
| * 264c408 add image to home page
|/
* 8359617 (tag: v1.0.0) new updates from production
* 9b3afa2 Merge production into main: Kept development.py and production.py, deleted settings.py
|\
| * b530716 modify settings files for development (PyCharm)
* | 8b650f7 Upgrade Django to 5.1 (Security fix)(.venv) $ git branch -a
feature/event
main
* production
remotes/origin/feature/event
remotes/origin/main
remotes/origin/production- main: to show the simplest product (MVP)
- production: to run on the server
- feature/event: additional event app, quiz app
6.3.2 Run The New Code
Merge the feature/event branch into the production branch.
git checkout production
git pull origin production
git merge feature/event
# Resolve conflicts if necessary
git push origin production6.3.3 Update Django Server
# check if gunicorn is running; if so, stop it
pgrep gunicorn
pkill -f gunicorn
# restart gunicorn
source .venv/bin/activate
source .DJANGO_SECRET_KEY
# make sure you have this if you want to run manage.py
export DJANGO_SETTINGS_MODULE='mvp24.settings.production'
# run makemigrations and migrate if there is any model change.
python manage.py makemigrations
python manage.py migrate
source run_server.sh productionGunicorn Issue
We might need to create a systemd config for gunicorn because /var/run dictories will disappear after reboot.
gunicorn -c config/gunicorn/prod.py
tail -f /var/log/gunicorn/prod.logError: /var/run/gunicorn doesn't exist. Can't create pidfile.
[2024-08-25 10:00:39 +0000] [1400] [INFO] Starting gunicorn 23.0.0
Error: /var/run/gunicorn doesn't exist. Can't create pidfile.
This will be fixed by:
sudo mkdir -pv /var/{log,run}/gunicorn/
sudo chown -cR jeremy:jeremy /var/{log,run}/gunicorn/Make Migrations
If you have change your models, make sure:
python manage.py makemigrations quiz
python manage.py migrate quizSend files
python manage.py dumpdata quiz > quiz_data.json
scp -i ~/.ssh/id_rsa quiz_data.json jeremy@cyber.mrchen.store:/tmp/
python manage.py loaddata /tmp/quiz_data.json6.4 What is Responsive Web Development?
Responsive web development is an approach to building websites that ensures a seamless and optimal user experience across a wide range of devices, from desktops and laptops to tablets and smartphones. The key idea is that the website layout and content should adapt to the screen size, resolution, and orientation of the device being used.
6.4.1 Key Features of Responsive Web Development:
- Flexible Layouts: The use of fluid grids and flexible images that automatically resize and rearrange based on the screen size.
- Media Queries: CSS techniques that apply different styles based on the characteristics of the device, such as screen width or resolution.
- Viewport Meta Tag: A tag that controls the layout on mobile browsers by setting the viewport size and scale.
- Optimized Performance: Ensuring that the website loads quickly and efficiently on all devices, often by serving different content or images based on device capabilities.
Responsive design is essential in modern web development because it provides a consistent and user-friendly experience, regardless of the device being used, which is crucial in an era where mobile and tablet usage is prevalent.
6.4.2 How Bootstrap Enables Responsive Web Design
Bootstrap is a popular front-end framework that makes it easier to create responsive websites. It comes with a set of pre-designed components, CSS classes, and JavaScript plugins that help developers quickly build responsive, mobile-first web pages. Here’s how Bootstrap achieves responsiveness:
6.4.2.1 1. Fluid Grid System
Bootstrap uses a 12-column fluid grid system that automatically adjusts the layout of your website based on the screen size. The grid is responsive, meaning it resizes and repositions content depending on the device’s viewport size. By applying classes like .col-md-6 or .col-sm-12, you can control how much space a content block occupies on different devices.
6.4.2.2 2. Responsive Breakpoints
Bootstrap includes predefined breakpoints that allow you to apply different styles at different screen widths. These breakpoints correspond to common device sizes (e.g., mobile phones, tablets, desktops). For instance, .d-none d-md-block hides an element on small screens and shows it on medium and larger screens.
6.4.2.3 3. Flexible Media
Bootstrap provides utility classes for making media elements, like images and videos, responsive. For example, the .img-fluid class ensures that images scale to fit the width of their container, preventing them from overflowing or distorting.
6.4.2.4 4. Responsive Components
Many of Bootstrap’s built-in components, such as the navbar, modals, and carousels, are designed to be responsive out of the box. For example, the navigation bar automatically collapses into a mobile-friendly menu on smaller screens.
6.4.2.5 5. Mobile-First Design
Bootstrap is designed with a mobile-first approach, meaning that it prioritizes the mobile experience and then scales up to larger devices. This ensures that your website is optimized for the smallest screen first and progressively enhanced for larger screens.
By leveraging Bootstrap’s grid system, breakpoints, flexible media, and responsive components, developers can create websites that look great and function well across a variety of devices without needing to write extensive custom CSS.
6.4.3 Case Study: Making a Non-Responsive Home Page Responsive
The current home page is not fully responsive. Specifically, the image and text do not adapt well to different screen sizes, making the page difficult to use on mobile devices. Let’s explore how to improve this page’s responsiveness using Bootstrap.
6.4.3.1 Current Home Page Code:
{% extends 'base.html' %}
{% load static %}
{% block content %}
<h1>Welcome to Cool Code Coach Membership Management</h1>
<img src="{% static 'crm/images/crm_home.webp' %}" width="500" alt="Hi!"/>
<br/>
Developer: {{ records.developer }}
{% endblock %}6.4.3.2 Issues:
- Fixed Width Image: The image has a fixed width of
500px, which may cause it to overflow or not display correctly on smaller screens. - Text and Image Layout: The text and image layout does not adjust based on screen size, making it hard to read on small devices.
6.4.3.3 Making the Home Page Responsive:
- Use Bootstrap’s Responsive Classes:
- Replace the fixed width of the image with Bootstrap’s
.img-fluidclass to make it responsive. - Wrap the content in a Bootstrap container and grid system to ensure proper alignment and spacing across devices.
- Replace the fixed width of the image with Bootstrap’s
- Improving Layout with Bootstrap Grid:
- Utilize Bootstrap’s grid system to create a layout that stacks the content vertically on smaller screens.
6.4.3.4 Updated Home Page Code:
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-12 text-center">
<h1>Welcome to Cool Code Coach Membership Management</h1>
</div>
<div class="col-12 text-center">
<img src="{% static 'crm/images/crm_home.webp' %}" class="img-fluid" alt="Hi!"/>
</div>
<div class="col-12 text-center mt-3">
Developer: {{ records.developer }}
</div>
</div>
</div>
{% endblock %}6.4.3.5 Explanation:
container: This class centers the content and adds padding on the sides for better presentation across different screen sizes.rowandcol-12: Bootstrap’s grid system is used to organise the content into rows and columns. Thecol-12class ensures that each piece of content takes up the full width of the container on smaller screens, while adjusting automatically on larger screens.img-fluid: This class makes the image responsive, allowing it to scale appropriately depending on the screen size.text-center: This class centers the text and image, improving the visual alignment on all devices.
By applying these changes, the home page will become more user-friendly and responsive, providing a better experience across different screen sizes.
6.4.3.6 Responsive Homepage On a Mobile Phone
