rowlandcoping / hopes-and-dreams

0 stars 2 forks source link

Hopes and Dreams

image

Hopes and Dreams is a social platform designed to help users collaborate, share and plan their hopes, aspirations, dreams and goals. The site is designed as a collaborative space through which, with a little luck and a little help, those dreams might come true.

Contents:

UX Design

UX Design - Strategy\ UX Design - Scope\ UX Design - Structure\ UX Design - Skeleton\ UX Design - Surface

The MVP

Specification Changes\ MVP Data Structure\ Feature List

Testing and Deployment

Testing Documentation\ Deployment

Credits and Technical

Credits\ Technical Information

UX - Strategy

(back to top)

1) Research

My research ahead of this project has involved looking at existing social platforms and analyzing what makes them work (or otherwise) and interviewing friends, colleagues and family to understand what they do and don't like about them. I am also lucky to be able to draw on 20 years of experience working in online advertising and marketing. On reviewing the information I have been able to gather, I have settled on a number of key points which, through the establishment of developer goals and user stories, will be important in a social platform as intimate as this.

2) Project Goal

Hopes and Dreams intends to be a place to realise positive aspirations. In spite of this, I intend to avoid the sort of language that exists around setting goals. Whilst planning tools can be part of the process (either as part of the MVP or part of the evolution of the project) this platform is about encouraging blue skies thinking. The intention is that a community will develop to support people in pursuit of their dreams, at which point they might even become goals, rather than interaction with the site be a goal-setting exercise in itself. The aspiration is almost as important as the realisation, as such creating and sharing a dream with the community will be intended as a journey of discovery rather than a chore. Dreams are meant to be shared and celebrated almost as much as they are meant to be realised.

The main goal of the project then, is to develop this community and bring people together, through a UI which makes the site a pleasure to use. It's about having people put their dreams and ideas in writing and find like-minded people. On an MVP level this will simply be about matching dreams to users, creating a 'feed of dreams' containing a variety of fascinating hopes and aspirations, hopefully some of which will motivate the user to positively engage - whether this engagement means offering advice, the benefit of experience or even practical assistance. The site will also act as a more conventional social platform, where you can actively search for and follow individuals or their aspirations and receive updates about how things are going for them.

3) Developer Goals

4) Site Owner - User Stories

Based on my project research I have identified the following key areas.

5) Site Visitor - User Stories

This site should be for everyone, from any walk of life. As such the user stories focus on UI, engagement and provision of compelling content.

UX - Scope

(back to top)

It is important to make clear at that the below is the scope envisaged at the beginning of the project, and that there was always anticipated to be an evolutionary process in producing an MVP. For a full overview of specification changes in the finished MVP, please click HERE.

Technology

The technology used will be HTML/CSS and JavaScript/JQuery, using Python with the Flask framework as a templating language and MongoDB to store data.

I have chosen to use MongoDB over PostgreSQL for a number of reasons (in order of importance):

Core Elements (MVP)

Structure

Features

NB This MVP feature list represents this site as I currently envisage it, and will be subject to change (probably quite a lot of it!)

Optional Features

UX - Structure

(back to top)

As with the Scope, it is important to make clear at that the below is the structure envisaged at the beginning of the project, and that there was always anticipated to be an evolutionary process in producing an MVP. For a full overview of specification changes in the finished MVP, please click HERE.

The data structure for the submitted MPV can be found HERE.

Site pages and elements

Header and Site Navigation

The homepage navigation will simply be a sign up/sign in button prominently placed, which leads either to the sign-up user journey or the Dreamscape feed by default on signing in.

Once logged in the main navigation will be in the form of bold icons indicating the function of each page, and a logo will appear either alongside or above the navigation.

Furthermore search functionality will also be included on all pages. This will take either the form of a search bar with a radial offering the option to search for people or dreams, or an additional icon which would open a more detailed search page. The choice of concept here will likely evolve along with the site design.

My philosophy is to simplify navigation and avoid the need for additional pop-up/drop-down menus on mobile which impair site feel and are largely un-necessary if navigation is well designed.

Footer

If I view any social site there is no main footer as such, and indeed Facebook does not include one either - this seems to be for two reasons; one is infinite scroll, the other is space being limited on a mobile screen. Any important information (copyright, terms of service) can be located elsewhere; with this in mind I'm not sure what a footer would add so I won't be including one.

Sign-up user journey

This will consist of a series of pages requesting use information to complete the sign-up process. The intention is not only to gather the information required for the site to be functional, but to introduce the user to key site concepts, build anticipation about site content and encourage exploration once signed up.

Feed pages

The feed pages will consist of a scrollable list of items in the feed, along with options to interact at the bottom of each item. This will include like buttons, and the ability to follow, unfollow, expand the comments section or leave a new comment. Where dreams are concerned users will also be able to access full details about the dream and the user who created it from the feed.

The feed will take two forms - one is a personal feed which will show the latest from all the content and people the user is following. the other is the Dreamscape feed where the user can browse the dreams that others have created.

Dreams page

The dreams page will list Dreams and descriptions of them, with latest comments. You can also expand them to view various modules and comments therein, or open them in the Dream Editor page. At the top of the page will also be the Dream Builder button which initiates the user journey for building a dream.

Dream Editor

Large icons will represent the various dream modules if present, otherwise there is an icon to create them. Here you can also enter various modules to edit and update them.

Dream Builder

The Dream Builder icon initiates the user journey to create a dream, walking the user through each stage of the process. Not all modules are compulsary but each dream will require a name, description and some category tags so people can discover it.

Profile Page

The user will be faced with two options - it defaults to personal which allows them to update skills, interests, projects and experience to tailor what they see in their Dreamscape feed. The user can also access Account Settings from this page to update their personal info and privacy/notification settings.

Core Data Structure

Please note that this section represents the initial design phase for the database schema, and as I outlined below it was always going to be subject to change. The data structure for the completed MVP can be found HERE.

Using Mongo DB and a modular approach to building key elements of the site means I have opted for an extremely flat structure, creating new collections where possible to make data easily accessible and speeding up the process of removing data. This data structure has been put together with two major provisos - one is that this is my first MongoDB project and I do not yet know how this structure will evolve in practice. It may well be that I need to merge, nest or separate various collections as the requirements of the platform become clearer.

Users Collection

This will include basic user data, key settings for discovery of dreams and notification/privacy settings.

image

Dream Collection

This is the collection for base dream data. It includes all the data to be included in feeds and discovery, and is linked to a user by the user's ID. Comments will be enabled on dreams.

image

Modular Components Data Structure

The below represent modular components of dreams. The key concept among these components is the Diary Module, which will form part of the MVP - the rest may not all be included in the MVP depending on timescales and viability, however it is intended that they should be.

Diary Collection

The diary is a modular component of a dream, and is linked to a dream by the dream's ID. Comments will be enabled for diary entries.

image

Goals Collection

Goals are a modular component of a dream, and are linked to a dream by the dream ID. Comments will be enabled for goals.

image

Planner Collection

The Planner collection will be created on the same basis as other dream modules and will have comments enabled. Each plan within the planner will have an associated task, which can include any number of steps.

image

Requests Collection

The requests module of a dream allows a user to request any number of specific skills or assistance within the skills required section. This can then be associated with users offering their services.

image

UX - Skeleton

(back to top)

As with the Scope and Structure, it is important to make clear at that the below is the Skeleton envisaged at the beginning of the project, and that there was always anticipated to be an evolutionary process in producing an MVP. This said the guiding principles set out here for the design of the platform have been adhered to throughout, if not the specifics. For a full overview of specification changes in the finished MVP, please click HERE.

Design Choices

Wireframes

Please find the wireframes HERE.

UX - Surface

(back to top)

Color Palate

Color Names

black - background for all pages.\ red - warning, delete and fail messages. Also used as activated/mousover color for buttons which cancel, abandon or unfollow. Used to indicate user has liked something already.\ green - success messages. Also used as activated/mousover color for buttons which submit or follow. Used to indicate user has liked something already. Green background indicates a category is selected.\ orange - user for edit confirmation messages, or non-critical alerts.\ grey - initial background for category buttons.\ white - color for text and borders (except in situations where higher contrast was required).

RGB

rgb(34, 34, 34) - secondary background for Dreamscape.\ rgb(0, 145, 255) - main color theme for dreams icon, all dreams, view dream and dream creation pages. Also used for highlighting icons and form fields.\ rgb(6, 28, 46) - secondary color theme for dreams.\ rgb(255, 221, 71) - main color theme for the Dreamscape feed and icons. Also used for highlighting icons and form fields.\ rgb(59, 49, 0) - secondary color theme for the Dreamscape.\ rgb(248, 72, 69) - main color theme for profile icon and all profile related activities including signup and the profile page. Also used for highlighting icons and form fields.\ rgb(77, 28, 27) - secondary color theme for the profile pages.\ rgb(49, 7, 7) - follow, unfollow, cancel and abandon buttons background color.\ rgb(58, 73, 69) - submit and confirm buttons.\ rgb(139, 247, 139) - mouseover color for like button.\ rgb(250, 144, 144) - mouseover color for unlike button.\ rgb(0, 80, 0) - mouseover color for unlike button.\ rgb(133, 0, 0) - mouseover color for undislike button.

Fonts

All fonts found on fontspace or google. The title font has been chosen because I feel it is evocative or the theme. The main font is chosen to marry with this but also for its clarity and versatility. I originally wanted to use a font called ClearSans by Intel but this was throwing errors in the console so I had to abandon it for the purposes of a graded project.

Titles/some buttons

CfDavesDreamPersonalRegular-WyAGn.ttf

Main font

OpenSans-Regular.ttf

Images

Site Theme

I deided at the start of the project that any assets would have to be simple to product, yet also very striking in design. The plan was to use simple line drawings of cute animals throughout the project. In the end I had very limited time for asset creation so I have used the themes and assets from the landing page and navigation throughout.

User Avatars

The user avatars came about because I wanted to simplify signup (nobody wants to upload an image right away), provide users with a really simple customisation option and because it fits the site theme. I also wanted every user to have an image they could use alongside comments, as such users are randomly allocated an avatar on signup.

The idea stems, interestingly, from a football forum I use where users rarely change their avatars. Users on Hopes and Dreams can have fun randomising their avatar to see what is out there, whilst they are still able to upload their own image to use if they want. As an admin I can continue adding more avatars to add interest and variety.

User Avatars were all created using Bing Image creator.

Navigation

Navigation was always intended to be a site feature rather than simply be functional, with very bold and memorable icons. The choices are intended to be evocative of the destination but also include a text prompt which I know from experience is key with a new site.

Elsewhere on the site I have used clear, recognisable icons for edit and delete processes, as well as viewing dreams. The show/hide comments carat also includes a text prompt.

Where key actions can be performed I have provided outsize buttons in the site theme with the intention that the user should never be hunting for anything. Where users return no results from a search they are prompted to take action to get better results next time, or in the case of the dreams page create a dream. These large, clear buttons throughout are a theme which helps the site be extremely accessible on mobile.

In the feed the user is always routed back to the content they were viewing when they take an action (adding/editing/deleting comments, following/unfollowing users or dreams, like/disliking comments). Everything is designed to be in the flow of the user's interaction.

The objective is a site which should be a pleasure to use.

Alerts

Customised alerts are provided as a user safety net if they take any delete actions, whether that be a comment or a dream. All other user CRUD operations receive a clear confirmation, either via a flash message or (on signup or dream creation) a seperate page. The custom alerts are designed to retain the site theme and avoid users feeling like they are being railroaded - I have kept such pop-ups to a bare minimum.

Responsiveness

The site is very simple in terms of navigation and design, and this is with mobile in mind. Although designed on a 1920px screen width, mobile was at the forefront of my thoughts throughout. Anything below 1920px uses a 'max-size' media query, anything above a 'min-size' From wireframe onwards the CSS flexbox page structure was designed to be easily adjusted to other screen widths.

Most of the difficulties were in scaling textboxes to work effectively on different screen sizes without overflowing the page, and in ensuring that users never have to scroll when entering data. The was ultimately achieved using Javascript.

I worked to specific break points in order to keep the development overhead to a minimum. I've been strict with myself to avoid any custom break-points for specific cases - for such a complex site this could easily get out of hand! The break-points are as follows:

max-width: 359px (for very very small phones)\ max width: 450px (the main break point for converting to smaller mobile format)\ max-width: 650px (the main break point for converting to a mobile format)\ max width: 920px (for large tablets or people viewing in smaller windows)\ max width: 1200px (to accommodate smaller laptop screens)\ max width: 1400px (to accommodate laptop screens)

The MVP

Specification Changes

(back to top)

As Donald Rumsfeld memorably said:

"There are known knowns. These are things we know that we know. There are known unknowns. That is to say, there are things that we know we don't know. But there are also unknown unknowns. There are things we don't know we don't know."

The majority of work required for this project definitely fell into the 'unknown unknowns' category. As such although the MVP is true to the core concepts of the original design there have been significant modifications to the feature list and schema and some elements of the initial design as laid out in the UX Design section.

Developer Goals

"I would like to make use of JQuery on this occasion to simplify the Javascript"\ My own reading and research has led me to believe that JQuery is identical in functionality to Javascript. As such I decided against using it for multiple reasons:

Structure

"Base Elements: Once signed in each page will have title/logo and menu with four core elements, plus a search"\ The core elements were almost immediately reduced to three, and eventually the search integrated into the Dreamscape feed filter. Because the site is so freeform in its current iteration, it is more of a browsing experience than searching for specifics. And in any case users can use categories to customise their personalised feed or the followed filter to view specific dreams they have interest in. Time was also a factor in creating a full search facility.

"Feed (default page): The main site feed is divided into two elements, Dreamscape (default) and Personal"\ The various elements of the original were integrated into one feed and accessible via the filter at the top of the page - for example the followed filter contains all the content intented for the personal feed that is avilable in the MVP iteration.

"Profile: Consists of an overview of your profile and options to update info divided into 2 sections, account or personal settings."\ After a meeting to review the prototype of the site with my mentor before Christmas, it was agreed it would be for the best to simplify this into one page.

Features

"Detailed step-by-step user journey planner..."\ The original plan was for the signup process to be staged and broken down into sections - a bit like a tutorial on a video game. In the prototype meeting my mentor demostrated that this was far too complicated for what the site is. It was not just unviable to produce in the timescale, it was unwieldy for a user, especially on mobile. People simply would have been put off by it. The MVP sign-up process is now one page and four fields of basic information, and adding custom images and interests is something the user is prompted to do as they go.

"Personal feed will consist of actions from people or dreams you follow"\ This section is now the 'follwed' filter option on the main feed page.

"Step-by-step Dreambuilder wizard"\ This is now also a single page, with only two compulsary fields and a category selector. The user is prompted to upload an image but they don't have to. The absence of any 'Dream modules' makes an extended process completely unnecessary for now, and in any case should never detract from how easy the core site ought to be to use.

"Optional modular elements for your dream..."\ None of these have been included in the MVP due to time constraints. Leaving modules out for now has also made my design choices a lot easier!

"Opportunities to update skills and interests... Account and personal settings which allow the user to customize their experience"\ The original suite of options has been reduced to a single pre-defined interests list which is also shared with dreams. Interests etc were originally free-form and manually entered, but even as the site creator I was struggling to enter appropriate interests. The chances of anything matching with a dream were slim. Also users do not want all these steps. Following the prototype meeting all this was stripped down (along with 500+ lines of Javascript) and the current categories system instigated. Account settings are a roadmap feature, but not essential at present.

"Users may rate comments, and have the option to filter users with very low scores"\ All the data regadring likes and dislikes exists and could be used to build a user filter which could be integrated into the profile. Unfortunately time constraints mean this will not be part of the MVP. Users are protected by the opportunity to delete any comments on their own dreams they do not think are acceptable or in extreme cases disable comments altogether.

"Search facility to find friends or chase specific dreams"\ This has been abandoned in favour of the Dreamscape filters which do much the same thing, due to time constraints and necessity. It is possible to follow users and see all thier content in your 'followed' feed, and to share dreams with others whether they are registered site members or not.

"Basic themes - dreams and indeed profiles can be tailored with basic color themes"\ It would be relatively straightforward to implement, but it would require a major reworking of the CSS as well as designing other site themes, which would require a lot more time than I have left for this project.

Site Pages and Elements

Dreams page: This has been simplified to allow immediate access to key CRUD features and reduce the number of user clicks. As there are no modules in the MVP there is no need to provide access to them. If modules were added they would instead need to be integrated into the current site structure, probably part of each dream section on the 'view dreams' page rather than as a seperate page (which is mooted both here and in the wireframes) in order to limit the number of clicks to reach a destination.

Data Structure

The data structure has evolved significantly as the project has developed, particularly as my experience of using both MongoDB and the FLask framework has grown. I have outlined below significant changes to the structure originally mooted:

DREAM MODULES:

There are no dream modules in the MVP, so none of these schemas have been implemented.

COMMENTS:

Comments have been split into their own collection.

CATEGORIES:

There is a new categories collection, which is common to users and to dreams.

AVATARS:

This is now a collection of avatars that can be allocated to users.

DUPLICATING DATA:

In light of the limitations of Jinja2 as a templating language and to limit as much as possible the number of data queries, and in light of the fact that MongoDB stores data in a freeform way with no foreign keys, I have opted to store some data in multiple locations. For example comments all contain the user's full name and a link to their profile picture and alt to make it easier to render than information on the page, even though it is also stored in the 'users' collection. Rather than force the template to count data (eg total number of times a category has been selected) I have included a separate count as a document in the categories collection. It's not clear to be what best practice is as to be honest not too many examples exist of projects with Flask and PyMongo, but the principle behind my approach is to simplify data queries made in the browser and do as much of the work as possible in the back end.

Design Choices

Most of this has been covered above, and the principles underlying the initial design have not deviated. The wireframes, however, show significant deviation from the finished design.

MVP Data Structure

(back to top)

Although the core functionality of the project has not changed, the schema has evolved as I have learned more about working with MongoDB and Jinja2. Most notably I have done my best to restrict data operations to the back end as much as possible, and try to reduce database calls and simplify my code. This has means duplicating some data across multiple collections to limit the necessity of cross-referencing data. As the site has evolved I have also added two new collections, and removed anything pertaining to modules, as well as separating comments from the collections they relate to.

users

The users data collection contains key user data and tracks details of what the user is following and the comments they have liked.

image

dreams

The dreams collection contains details relating to a dream, including the user who created it. It also tracks who has followed the dream.

image

comments

The comments collection has been seperated from its related modules to ensure user interaction and reactions are tracked more easily.

image

categories

Pre-defined categories have been added to simplify the dream creation experience and shorten the user journey. It will also make drema discovery a lot less hit and miss. There is potential for user-added categories at a future date but not in this MVP. Categories also tacks users and dreams selecting them, as well as a count of that data to simplify the front end.

image

avatars

The final collection is a repository of details for pre-defined user avatars, which are randomly assigned to users on sign-up. It consists solely of the filename to link to the image in cloudinary and the image alt.

image

Feature List

(back to top)

Landing Page and Sign-up

image

image

image

image

Site Theme and navigation

image

image

image

image

Dreams

image

image

image

image

image

image

image

image

image

Dreamscape Feed

image

image

image

image

image

image

image

Personal Profile

image

image

Testing Documentation

(back to top)

Please find all testing documentation HERE.

Deployment

(back to top)

Initial Deployment

Hopes and Dreams has been deployed HERE via Heroku, taking the following steps:

Preparing for Deployment:

Creating the App and connecting to Github:

Setting up the deployment:

For the site to function I also needed to add the correct environment variables.

Deploying this Project

If you wish to deploy this website yourself, here is how to go about it.

Create a Version of the repository:

Creating your own Heroku Account:

Creating the database:

This project uses MongoDB to store all data, therefore you will need a copy of the database to deploy it for yourself.

Creating a Cloudinary Account:

This project hosts all images on Cloudinary. In order to do the same you will need a Cloudinary account.

For this project I used gmail to set up an account through which all password reset e-mails are sent.

Deploy to Heroku

Continuing the Project

Once the deployment steps have been completed, as above, you will be in a great position to continue the project. All you will need to do is set up the environment variables in your chosen development environment.

Using VS Code on Linux:

Using VS Code to continue the project is actually a simple matter because you already have the requirements.txt. I have used it throughout and I have found it straightforward to set it up on a second machine using a venv and the requirements.txt file.

Setting up:

Making it work:

Hopes and Dreams Environment Variables

FLASK:

os.environ.setdefault("IP", "0.0.0.0")\ os.environ.setdefault("PORT", "5000")\ os.environ.setdefault("DEBUG", "False")\ os.environ.setdefault("SECRET_KEY", "xxxxxxxxxxxxx")\ this key can be whatever you like\ os.environ.setdefault("SESSION_COOKIE_SAMESITE", "None")\ os.environ.setdefault("SESSION_COOKIE_SECURE", "True")

MONGO DB:

Please note you can set up this connection by logging into Mongo DB then doing as follows:

os.environ.setdefault("MONGO_URI", "mongodb+srv://xxxxxxxxxxxxxxxxxxxx.mongodb.net/xxxxxxxxxxxx")\ these are the details of the database connection\ os.environ.setdefault("MONGO_DBNAME", "xxx")\ this is the name of the database you wish to connect to

CLOUDINARY:

All the details for your Cloudinary account are provided on your Cloudinary Dashboard when you log in.

os.environ.setdefault("CLOUD_NAME", "xxxxxxx")\ as found on your Cloudinary dashboard\ os.environ.setdefault("API_KEY", "xxxxxxxxxx")\ as found on your Cloudinary dashboard\ os.environ.setdefault("API_SECRET", "xxxxxxxxxxxxxxx")\ as found on your Cloudinary dashboard\ os.environ.setdefault("CLOUDINARY_BASE", "https://res.cloudinary.com/xxxxxxxxxxxx/image/upload/yyyyyyyyyyyyy/")\ this is the base URL for cloudinary images - please note the 'xxxxxxx' portion is the same as your cloud name. If you view an image in the cloudinary explored and check the 'original url' you will be able to find the second part.

GMAIL:

os.environ.setdefault("MAIL_SERVER", "smtp.gmail.com")\ os.environ.setdefault("MAIL_PORT", "465")\ os.environ.setdefault("MAIL_USE_SSL", "True")\ os.environ.setdefault("MAIL_USERNAME", "xxxxxxxxxxxxx")\ the e-mail address you've set up with gmail\ os.environ.setdefault("MAIL_PASSWORD", "xxxxxxxxxxxxxxxx")\ the app password you've set up with gmail

CUSTOM:

os.environ.setdefault("BASE_URL", "xxxxxxxxxxxxx")\ this is the base URL for your site deployment. For example, for my deployment of Hopes and Dreams this is https://hopes-and-dreams-15b83f2d1383.herokuapp.com, for your localhost it will be something like http://127.0.0.1:5000/

Credits

(back to top)

Fonts

FONTSPACE:

CfDavesDreamPersonalRegular-WyAGn.ttf

GOOGLE FONTS:

OpenSans-Regular.ttf

Images and Icons

IMAGES:

All avatar images were created using Bing Image Creator.\ All other site assets were created myself using Inkscape.

As such all images belong to me.

ICONS:

Icons are from Font Awesome.

Content

© 2023 John Hall.

Code

IMAGE HANDLING:

My image handling process was put together using information from the following sources.

https://dev.to/feranmiodugbemi/image-conversion-web-app-with-python-1e18 \ https://stackoverflow.com/questions/33101935/convert-pil-image-to-byte-array \ https://gist.github.com/tomvon/ae288482869b495201a0

PASSWORD RESET:

I used the following blog, combined with a great deal of googling and guesswork, to put together the password reset functionality.

https://medium.com/@stevenrmonaghan/password-reset-with-flask-mail-protocol-ddcdfc190968

Acknowledgments

HELP AND ASSISTANCE:

Enormous credit goes to my mentor Mitko Bachvarov for his patience and assistance throughout this build. His feedback about the UI in particular resulted in major changes for the better to the sign-up and editing process and a significant re-build since Christmas - I'm not sure how I would have completed this project to any kind of standard without this. I feel certain he must be one of the best mentors working with Code Institue and very fortunate to have had access to his insight.

DESIGN INSPIRATION:

Strange as this may sound, since I came across it as part of my work I've always wanted to produce a project drawing influence from the design for the Luton Culture website c. 2012-2015. I always thought it was a great, clean, distinctive design. It has since been re-built in black and white (which I think is a shame), but here is a link from the web archive:

https://web.archive.org/web/20121002225637/http://www.lutonculture.com/wardown-park-museum/

Technical Information

(back to top)

Version Control: Git and Github.\ JavaScript validation: jshint.\ Python validation: CI Python Linter.\ Framework: Flask.\ Image Hosting: Cloudinary.\ DBMS: MongoDB Atlas.\ SMTP Mail Server: Gmail.\ Languages: HTML, CSS, JavaScript, Python, PyMongo, Jinja2.\ Development Environment: VS Code on Linux.\ Wireframes: Balsamiq.\ Database Modelling: Hackolade.\ Image Creation: Bing Image Creator & Inkscape.\ Image Editing: GIMP. Screen Capture: Kazam.

(back to top)