- designland
The project is an online directory of useful design resources for web developers and designers.
Users can register to submit resources to the directory, and upvote and bookmark resources they find useful.
The project was built keeping the Agile management principles in mind, and I utilised many of GitHub's features such as Issue and Projects to implement Scrum methodology.
Closed Issues on GitHub for the project
I used GitHub issues for the product backlog containing the user stories. Issues were also used for bug reports so I could keep track of tricky bugs over time.
CRUD functionality
- Users can read all approved resources, and create, update and delete resources they contributed.
- Users can create, update, read and delete their accounts/profiles.
- Admins can create, read, update and delete all resources.
I used the tags feature in GitHub Issues for assigning story points, prioritising features based on the MoSCoW method, and categorising the user stories.
I used the Milestones feature to plan sprints and set deadlines.
I took the Agile Foundations course on LinkedIn Learning to better understand the difference between Agile and Scrum.
User stories were prepared using GitHub Issues and assigned story points based on estimated completion time.
User Stories can been seen below under User Story Testing, and in the GitHub Issues for full details including screenshots, story points and associated sprints.
As the project is a directory of design resources, I wanted to try something fun and bold with the design and was inspired by the trend for neubrutalism web design, and websites such as Gumroad and Google I/O 2022.
- Qode Magazine - 60 Best Examples of Brutalism in Web Design
- Elementor Blog - What Is Brutalism in Web Design?
-
A display font called Bebas Neue was used for the logo as it fitted the neubrutalist theme of the site.
-
Baloo 2 contrasts the harsh lines of the display font with friendlier rounded letters that made it suitable for the headings and navbar.
I ensured that despite bold use of color, every element still met AAA level in the Web Content Accessibility Guidelines (WCAG).
Buttons featuring icons have appropriate aria-labels
, and notification messages have aria-live
tags and are read by screen readers.
I tested navigating the project with VoiceOver on macOS.
I used inline SVGs for icons in the project.
I recently watched Seren Davies' talk Death to Icon Fonts where I learned of the issues that icon fonts can cause for accessibility. I researched the best way to use inline SVG icons, including descriptions where appropriate for screen readers. By using SVGs the icons don't break if a user chooses to use a custom font such as Dyslexie.
See also:
- Inline SVG vs Icon Fonts - CSS Tricks
- SVG, Icon Fonts, and Accessibility: A Case Study - 24 Accessibility
I used the desktop version of diagrams.net to design the models. I created a Profile model to associate extra information with users not included in the default Django user model.
After creating the Profile model I used this script in the terminal to create a profile for existing users in the database that didn't have one yet:
>>> from django.contrib.auth.models import User
>>> from directory.models import Profile
>>> users = User.objects.filter(profile=None)
>>> for user in users:
... Profile.objects.create(user=user)
A simple landing page explains the project and features a call to action button to lead the user to the main content.
The Navbar is responsive and collapses to a hamburger menu on smaller devices. On larger screen it sticks to the top when the page is scrolled.
When a user is logged in, their username is displayed in the navbar, and a dropdown menu includes:
- My Profile (link to the user's own profile)
- My Bookmarks (list of the resources the user has bookmarked)
- My Submissions (list of approved resources the user has submitted)
- Submit New Resource (form to submit a new resource)
- Logout
When a staff member is logged in, an extra Manage dropdown option is shown which includes:
- Unapproved Resources (submissions not yet visible on the site ready for screening)
- User List (a list of all registered users on the site)
- Django Admin Panel (a link to the Django Administration Panel)
The list of design resources. Directory lists all resources, while Categories lets users sort by tag.
Users can sort the list by newest, oldest or most up-voted.
The list page is also used for seeing all the resources a user has added via their profile.
Users can either sign up using their Google or Github account, or directly on the site.
Users signing up with GitHub or Google just need to pick a username, and don't need to create a password.
GitHub was chosen as the site is aimed at developers and designers, and Google as is has 1.8 billion active monthly users.
Users who have previously registered with GitHub or Google can easily sign in again with one click.
Register / Login Screenshots
Register a new Account - pick username (after authorising Google account)
Users can upvote the resources they like, other users will see the total number of uploads and can view the most popular resources on the site.
Users can add tags their submissions which are used to categorise the entries. Suggested tags are show on the submission page.
Users can bookmark resources they find useful in list that only they can see.
Users can display links to their Personal Website, GitHub profile and Twitter profile
A list of all the resources the user has contributed is shown on their page.
When a logged in user views their own profile, they can click a button to edit it. The user can delete their account from this page too if they choose.
Users can submit a resource to the directory by providing a Title, URL, Description, and Tags describing the resource.
A placeholder thumbnail is added to the Resource on submitting.
When a user submits a resource to the directory, they can see a preview of it which they can edit again, and a badge telling them it is awaiting approval by a staff member.
Submissions will be manually approved by staff members to prevent unwanted material being posts, and to ensure a high standard of resources in the directory.
The Footer includes:
- A link back to the homepage
- Copyright information
- A link to the Privacy Policy
- A link to the GitHub repository for the project.
As the project can collect data from users, I included a Privacy Policy link in the Footer which explains how data may be used. I used GDPR.eu for help writing the policy.
See: Writing a GDPR-compliant privacy notice (template included)
Django Messages and Bootstrap's Toast elements were combined to make elegant notification messages when the user performs actions such as signing in/out and bookmarking or upvoting a resource. Staff also see notifications for things like approving/hiding/deleting resources. The notifications appear on the bottom right so as not to cover the navigation bar.
Animated screenshot showing notifications
Notifications for upvoting / removing upvote / logging out in action
The Manage dropdown menu in the nav bar appears only for logged in staff members and features additional pages.
All unapproved resources that have been submitted by registered users. Staff members can approve, edit, or delete them.
A list of all registered users of the site along with the date they joined, number of contributions, and total upvotes received.
The Manage menu also features a link to the Django admin panel should it be needed for features not yet implemented directly in the project. (such as managing tags).
Custom error pages were added for 403, 404, and 500 errors.
- A favicon and icon for iOS/Android home screen bookmarks is included with the project's logo.
-
Currently the screenshot thumbnails for the site are manually uploaded to Cloudinary by an administrator, but I would love to add an API such as URL2PNG in future to automate the process, however it was difficult to find a free service for this project.
-
With Heroku ending free plans in November 2022, the project will be redeployed on a different cloud platform in future. This was only announced when nearing the final sprint and the project continued as planned for the submission deadline,.
- Python
- pip for installing Python packages.
- Git for version control.
- GitHub for storing the repository online during development.
- GitHub Projects was invaluable throughout the project and helped me keep track of things to do and bugs to fix - you can see the project's board here.
- GitPod as a cloud based IDE.
- Balsamiq for wireframing.
- Bootstrap 5 as a front end framework.
- Google Chrome, Mozilla Firefox and Safari for testing on macOS Monterey.
- Microsoft Edge for testing on Windows 11.
- Safari on iOS and iPadOS 15.
- Google Chrome on Android 12.
- diagrams.net for drawing database diagrams.
- favicon.io to make a favicon for site.
- Device Frames for the device mockups in this README.
- Meta Tags to prepare the Meta tags for social media share previews.
- django-taggit for tags on directory entries
- django-crispy-forms for help styling the forms
- crispy-bootstrap5 for Bootstrap 5 templates for django-crispy-forms
I performed manual testing continuously as the project was being developed, and filed bug reports on GitHub as issues were discovered to keep track of bugs. I kept track of how to recreate bugs, expected behaviour, screenshots of the issue and how it was resolved to help myself in future.
I asked friends to test registering accounts / submitting resources / deleting accounts in different ways (email registration, Google registration, GitHub registration, registration with no email, etc.) to try and catch any potential issues.
I tested the website on four different operating systems on four different types of hardware and didn't find any rendering bugs between the browsers tested.
Operating System | Chrome | Firefox | Edge | Safari |
---|---|---|---|---|
macOS 12.2 | ✅ | ✅ | ✅ | ✅ |
Windows 11 | ✅ | ✅ | ✅ | ✅ |
Android 10 | ✅ | ✅ | ✅ | ✅ |
iOS & iPadOS 15 | ✅ | ✅ | ✅ | ✅ |
I tested for responsiveness on many different sized viewports from 320px wide up to Ultrawide resolutions, and using different hardware (Monitors, Laptops, Phones).
I used Polypane during development to test many different viewport sizes at once.
Performed using Google Lighthouse in Google Chrome 105.0.5195.125 on macOS 12.5.1
Detailed Lighthouse Testing
Desktop
Page | Performance | Accessibility | Best Practices | SEO |
---|---|---|---|---|
Landing Page | 96 | 100 | 92 | 91 |
Directory | 90 | 98 | 100 | 91 |
Categories | 86 | 100 | 100 | 90 |
Privacy Policy | 99 | 98 | 100 | 90 |
User Profile Page | 90 | 98 | 100 | 90 |
Resource Page | 99 | 95 | 92 | 91 |
Mobile
Page | Performance | Accessibility | Best Practices | SEO |
---|---|---|---|---|
Landing Page | 95 | 100 | 100 | 92 |
Directory | 85 | 98 | 100 | 92 |
Categories | 82 | 100 | 100 | 89 |
Privacy Policy | 95 | 97 | 100 | 92 |
User Profile Page | 94 | 98 | 100 | 92 |
Resource Page | 94 | 95 | 100 | 92 |
No errors were detected using the WAVE Web Accessibility Evaluation Tool.
As a first time visitor I want to be greeted with a clear explanation of the site so that I know what it is about
- If I visit the homepage I am greeted with a eye catching slogan/hero image
- I should be able to tell the purpose of the site easily
Result: ✅ Pass
As a visitor to the site I want to read the Privacy Policy before I sign up so that I can know how my data will be used
- I can click a link to be taken to the Privacy Policy
- The policy is written in easy to understand language
Result: ✅ Pass
As a registered user I want to update my profile page so that people can find me on Twitter / GitHub
- I can add Twitter/GitHub links to my profile
- I can delete my account
Result: ✅ Pass
As a developer I want to register using my Github account so I can signup without filling in any forms
- I chose to sign up with Github
- An account is created automatically for me
Result: ✅ Pass
As I user I want to share the site on social media to help my designer friends find cool new stuff
- If I share the site on Facebook/Twitter etc.
- A thumbnail/logo and the right meta data describing the site should appear in the preview card
Result: ✅ Pass
As a user I want to see all the resources I have submitted so I can see all my submissions in once place
- I should be able to see all the resources I have submitted
- I can see the resources added by other users on the site too
Result: ✅ Pass
As a user I want to be able to see a list of tags on each resource so I know what category it belongs to
- Each resource page should list tags categorising the resource
Result: ✅ Pass
As a user I can view a paginated list of resources so that I can select one to read and not have too many displayed at once
- When there is many resources, they should be split onto separate paginated pages
Result: ✅ Pass
As a unregistered developer/designer I want to browse the directory so I can find useful resources for building my projects
- If I visit the site I should see a list of design resources
- I can click them to be taken to the resource
Result: ✅ Pass
As an administrator I want to manually approve or deny user submitted resources so I can moderate the directory and keep it free of spam or abusive messages
- If a user posts a Resource it appears in the admin panel for approval
- As an admin, I can approve or deny the Resource for publication
Result: ✅ Pass
As a user I want to be able to click other users names to see what other resources they have added to the directory
- I can click a username to be taken to their page
- On their page I can see all the resources they have added to the directory
Result: ✅ Pass
As a user I want to add links to my GitHub/Twitter/Portfolio website* so I can gain new followers
- I can add a link to my website/GitHub/Twitter to my profile
- It appears on my profile page
Result: ✅ Pass
As a user I can click on a thumbnail so that I can view a page with the full details of the resource
- If I click a resource in the lists, I am taken to a page with full details about it
Result: ✅ Pass
As an administrator I want to be able to add, edit and remove resources so I can curate the listings
- If a user submits a link, I can approve or deny
- If I approve it, it appears publicly on the site
- I should be able to delete previously approved resources too
Result: ✅ Pass
As a user I want to be able to see a thumbnail of the site so I can preview it before clicking
- I should see thumbnails of each resource
- When I click the thumbnail it takes me to the page of the resource
Result: ✅ Pass
As a user I want to be able to sort the resources by tag so I can find what I'm interested in
- I should be able so view the listed resources tag by tag
- When I select a tag, only resources with that tag are listed
Result: ✅ Pass
As a registered user I want to be able to add useful resources I've discovered to the site so I can share them with the community
- I should be able to add resources to the site
Result: ✅ Pass
As a user I want to be able to upvote resources so I can participate and recommend resources to others
- I can click a button to upvote resources
- The number of upvotes should increase
- Resources are listed by number of upvotes
Result: ✅ Pass
As a user I want to be able to bookmark resources so that I can view a list of my favourites in future
- I can click a bookmark icon next to each resources
- The resource should be added to my list of bookmarked resources
- I can visit a page where I can see all my bookmarked resources
Result: ✅ Pass
As a user, I want to be able to register for an account so I can interact with the site
- I should be able to browse without logging in.
- I should be able to register for an account using Google OAuth
Result: ✅ Pass
django-taggit
was the source of a few bugs encountered in development. In a future project I may just model my own tags in the database.
While Bootstrap was good for getting a responsive design up and running quickly, I found using Bootstrap classes for things like layout very frustrating when combined with Django templating. In future I would consider not using Bootstrap at all, or writing more custom classes instead of using Bootstrap layout classes that need to be changed in many places.
Pages were validating using the W3 HTML Validator, and pages with content that varies based on guest/logged in user/admin status were validated in each state.
W3 HTML Validation
Page | URL | Logged In Status | Result |
---|---|---|---|
Landing Page | / | Guest | ✅ No errors or warnings |
Landing Page | / | User | ✅ No errors or warnings |
Landing Page | / | Admin | ✅ No errors or warnings |
Directory | /list/ | Guest | ✅ No errors or warnings |
Directory | /list/ | User | ✅ No errors or warnings |
Directory | /list/ | Admin | ✅ No errors or warnings |
Categories | /alltags/ | Guest | ✅ No errors or warnings |
Categories | /alltags/ | User | ✅ No errors or warnings |
Categories | /alltags/ | Admin | ✅ No errors or warnings |
User Profile | /user/admin/ | Guest | ✅ No errors or warnings |
User Profile | /user/admin/ | User | ✅ No errors or warnings |
User Profile | /user/admin/ | Admin | ✅ No errors or warnings |
Add New Resource | /add/ | User | ✅ No errors or warnings |
Add New Resource | /add/ | Admin | ✅ No errors or warnings |
Login | /accounts/login/ | Guest | ✅ No errors or warnings |
Log Out | /accounts/logout/ | User | ✅ No errors or warnings |
Register | /accounts/signup/ | Guest | ✅ No errors or warnings |
Privacy Policy | /privacy/ | User | ✅ No errors or warnings |
User List | /manage/users/ | Admin | ✅ No errors or warnings |
Update User Profile | /user/admin/update | Admin | ✅ No errors or warnings |
The custom CSS was validated using the W3C CSS Validation Service as CSS level 3 + SVG.
All the custom Python files pass PEP8 Validation, which I checked both in the development environment and on PEP8 online.
# noqa
was used in settings.py
where line breaks would have broken Django functionality.
Very little custom JavaScript was used with most of the functionality coming from Bootstrap. The two JS files I wrote were validated using JSHint.
In order to make a local copy of this project, you can clone it. In your IDE Terminal, type the following command to clone my repository:
git clone https://github.com/davidindub/designland.git
Alternatively, if using Gitpod, you can click below to create your own workspace using this repository.
After cloning or opening the repository in Gitpod, you will need to:
- Create your own
env.py
files in the root level of the project:
os.environ["DATABASE_URL"] = "postgres://"
os.environ["SECRET_KEY"] = "YOUR_DJANGO_SECRET_KEY"
os.environ["CLOUDINARY_URL"] = "cloudinary://YOUR_CLOUDINARY_URL"
os.environ["HEROKU_HOSTNAME"] = "URL_OF_PROJECT_DEPLOYED_ON_HEROKU"
os.environ["DEVELOPMENT"] = "True"
**Ensure the env.py
file is added to your .gitignore
file so it doesn't get pushed to a public repository.
If you don't have a Cloudinary account already, you will need to Sign Up for Free to host the static files in the project.
-
Run
pip3 install -r requirements.txt
to install required Python packages. -
Migrate the database models using:
python3 manage.py migrate
-
Create a superuser with your own credentials:
python3 manage.py migrate
-
Run the Django sever:
python manage.py runserver
The address of the server will appear in the terminal window. Add /admin to the address to access the Django admin panel using your superuser credentials.
Full Instructions on deploying to Heroku
Sign up to Heroku for free if you don't already have an account.
-
Create a new app in Heroku.
-
In the Resources tab of your app in the Heroku dashboard, click Add-Ons and select Heroku Postgres. Select Hobby Dev - Free as your plan.
-
When Heroku Postgres is installed, click the Settings tab in the Heroku Dashboard. Click Reveal Config Vars, and add the same variables from your
env.py
file here, except forDEBUG
, as you don't want debug mode on the deployed project. -
Copy the value of
DATABASE_URL
from the Config Vars. In yoursettings.py
file, comment out the default database configuration, and add a new one with the Postgres url.
DATABASES = {
'default': dj_database_url.parse('your DATABASE_URL here'))
}
-
Migrate the database models using:
python3 manage.py migrate
-
Create a superuser with your own credentials:
python3 manage.py migrate
-
Create a file called
Procfile
(no extension) containing the following:
web: gunicorn designland.wsgi
-
Run
pip3 install -r requirements.txt
to install required Python packages. -
Add the url of your Heroku app (for example 'designland.herokuapp.com') to your
env.py
file in the local deployment, and to the Config Vars in your Heroku deployment. -
Disable collect static so that Heroku doesn't try to collect static files when you deploy by typing the following command in the terminal
heroku config:set DISABLE_COLLECTSTATIC=1
- Stage and commit your files to GitHub
git add .
git commit -m "Commit message"
git push
-
In the Heroku dashboard for your App, select Deploy. Under Deployment Method, choose GitHub and search for your repository and click Connect.
-
Select Enable Automatic Deployments, and then Deploy Branch. Heroku will build the App from the branch you selected.
-
Now whenever you push your commits to GitHub, Heroku will rebuild the application.
You need to use your own Google Cloud and GitHub Developer credentials to set up django-allauth
.
The django-allauth documentation provides instructions for how to complete setup in your Google Cloud Console / GitHub settings.
- Writing a GDPR-compliant privacy notice (template included)
- OrdinaryCoders - Django custom user profile was really helpful for the script to create profiles for existing users.
- Bootstrap Icons were used extensively in the project.
- Zuzana on Unsplash for the paintbrush hero image.
- Thank you to my CI Mentor Tim Nelson for his help and suggestions.
- Thanks to my partner David for his constant support on my journey to a new career.