A recipe blog for autistic and other neurospicy folx. Utilitarian, customizable and to the point. No rambling, no unrelated stories, no word count fillers, no distracting design kitsch or vertigo-inducing moving backgrounds. Instead, the focus is on precise and searchable information to easily find recipes for specific needs.
Developer: Dr. Sylvia Blaho
See the development progress and further plans on GitHub Projects.
collection
appcommunity
appTable of contents generated with readme-toc
In a world designed for neurotypical people, the needs of neurodivergent people are often disregarded. When it comes to recipe blogs, the 3 main culprits I aim to tackle in this project are
Each issue and its implemented mitigation is described below.
An oft-parodied trend of many food blogs is their inflated word count by paraphrasing and unrelated personal stories, presumably in an effort to improve their SEO ranking.
While this is a mild annoyance to neurotypical people, it can be a serious accessibility issue for those who are neurodivergent and have executive functioning issues, such as problems focusing or front-end perfectionism.
Many autistic people are very particular about food (termed food selectivity in scientific literature; some examples). However, most recipe blogs do not offer easy ways to search for particular textures, tastes or temperatures.
Analogous to dopamine dressing, being able to surround themselves with colors that match or complement their mood and energy levels is a useful coping strategy for neurodivergent people.
To combat the problem of superfluous information, this recipe site is designed to clearly separate the different components of a recipe to provide a better overview for visitors, and a helpful template for recipe writers.
To address the problem of lack of specificity, this recipe blog has an emphasis on tagging, searching and filtering recipes, enabling visitors to find recipes matching their specific needs.
To facilitate users being able to customize the look of the site, the blog offers a selection of color themes that users can choose from.
Along with usual blog features like access management, post management and collaboration, the following Themes, Epics and User Stories were defined at the beginning of the project (click here for the original Sheet):
However, as the development time available for the project was only 1 month, and this was my first Django project, these User Stories were vetted based on whether they were to be part of the Minimum Viable Product (MVP) or not.
Based on the considerations specific to a neurodivergent audience (described above), clarity of presentation and customizability was rated more important than collaboration.
Accordingly, the User Stories in the MVP were determined as follows (click here for the original Sheet):
Naturally, this list was modified somewhat during development (see the Prioritization section for details). The final list can be seen in GitHub Issues.
The initial design of data models was as follows:
Notable aspects of the models are described below.
Partially based on the Post model of the I Think Therefore I Blog walkthrough, but changed several aspects:
Ingredients are available across the project, while IngredientQuantities are specific to individual recipes.
The reasoning behind this setup was threefold:
Decimal instead of float used for quantity.
Recipes can be saved without any ingredients (to allow better management of drafts).
Instances of Ingredient where ingr_name
& preparation
are the same cannot be duplicated.
This is true when adding new ingredients as well as when editing existing ones would result in a duplicated.
Each instance of IngredientQuantity is unique, that is, even if there are 2 recipes that call for 2 apples each, these are treated as separate entities.
This model is based entirely on the Comment model of the I Think Therefore I Blog walkthrough project.
These models were added to the initial design in order to enable more filtering and more precise tagging of recipes. Their implementation parallels IngredientQuantity and Ingredient: RecipeAttribute acts as an intermediary between the Recipe and Attribute models.
Using this design as opposed to a ManyToManyField relation between Recipe and Attribute enables setting up a better control of the scope of permissions for staff users.
When implementing the community
app of the project, this model was added to store public information about the users, with the intention that logged-in users will be able to create and manage profiles for themselves.
Crucially, the Profile model is distinct from the built-in User model, connected by a OnetoOne field.
There are 2 advantages to this setup:
Accordingly, the current Entity Relationship Diagram is as follows:
The project implemented signup, signin and signout functionalities by using Allauth.
CRUD functionalities are only available to logged-in users.
Visitors who are not logged in can still access the search, filter and color theme functionalities.
Logged-in users can Create, Read, Update and Delete their own comments. This functionality is implemented following the walkthrough project.
In addition, Staff users can access the Admin Panel and Create, Read, Update and Delete their own recipes, ingredient quantities, recipe attributes and profiles. Only their own objects are available to Staff users in the Admin Panel, while the Superuser can manage all objects.
This is present on every page, thus it contains elements that are used throughout the site.
The most prominent position has the navigation links letting the user switch between the collection
app containing the recipes, and the community
app containing the user profiles.
The center position of the nav bar has the blog name, logo and tagline.
On the right, we find the color theme selector toggle and the recipe search bar, but of these being important targeted features of the project.
As the primary purpose of the project is to show recipes, the home page of the site displays the list of published recipes.
The recipe filters are prominently placed at the top, since it is anticipated that this feature will be widely used by the target audience.
Clicking on any recipe takes the visitor to the recipe detail page.
To ease navigation, this app is laid out similarly to the collection
app: the main page shows a list of profiles, and clicking on them leads to the profile detail page.
The footer is also present on every page, but the information contained here is predicted to be used less frequently: the developer name and social media profile links.
Since this recipe blog is modeled after the I Think Therefore I Blog walkthrough project, and one of the project's aims is to keep layouts simple and intuitive, the basic layout of the home page and footer was not modified significantly (see the UX improvements section for changes that might not be obvious at first glance).
However, I decided to make several alterations and additions to the navigation bar.
First, I visually separated page navigation from access management functions (signing up/in/out): the page navigation stayed in the top left corner in the navigation, but access management links and information were moved to the so-called "user bar" immediately below.
Within the user bar, (semi-)permanent information was moved to the right side, while the left portion of the user bar was reserved for ephemeral dismissable messages having to do with signing in/out.
I also moved the blog name to the middle of the navigation bar.
The right side of the navigation bar has the color theme toggle and the search field.
The mobile version of the recipe list (with the nav bar open) was mocked up as follows:
I have made some more significant changes to the recipe detail page, since the way the data are stored is also more detailed than in the walkthrough project.
I separated the space under the masthead into 2 columns: the smaller one on the left has concrete, bite-sized and easily parsable information like preparation time, cooking time and ingredients. The larger column on the right contained the instructions.
Not shown on the wireframes is the Comments section – since this is very much the same as the walkthrough project, I did not make a separate mockup of this. One change I implemented was to show messages to do with comment creation/editing/deletion in the comment section rather than at the top of the page (see the section UX improvements).
A further addition to the masthead on the recipe detail page is the inclusion of attribute tags.
The mockup of the mobile version of the recipe detail page is shown below (with the nav bar closed):
I did not make separate wireframes for the profile list and profile detail templates, as these are analogous to their corresponding recipe counterparts.
The logo I chose for this project is the Rainbow Infinity symbol representing autism. This symbol is most widely used by autistic self-advocacy groups, and is in stark contrasts with the puzzle piece symbol that has been used to spread many harmful stereotypes about autistic people.
The rainbow infinity logo represents the many different facets of autism, the wide potential of autistic people, and the fact that autism is a circular spectrum without a "mild" end and "severe" end – mirroring the recognition that labels such as "low functioning" or "high functioning" are harmful and irrelevant.
The logo is also a not-so-subtle nod to Pride month, when this project was developed, as there is a striking correlation between the neurodivergent and queer communities: autistic people are 8 times more likely to identify as queer as neurodivergent people.
I have consciously stayed away from any unnecessary visual clutter, such as excessive borders and shadows, elements of very different shapes, background images, and auto-moving elements of all kinds.
These elements tend to cause problems for a variety of users (e.g. those with visual impairment, executive functioning impairment, vertigo, etc.). Neurodivergent people are highly likely to experience some of these issues due to their heightened sensory processing, so steering clear of these chimes in perfectly with accessibility goals and particularly suited to the target audience.
As detailed in above, I wanted to offer users to customize the color theme of the site to match their particular needs.
For the MVP I designed 3 monochrome color themes: orange, blue and green. I plan to expand the available themes for future versions of this project.
The names of the navigation links were changed to Collection and Community, to better reflect the names of the apps.
On the recipe list and the profile list, the whole card was made clickable instead of just the title, to accommodate those with below average motor coordination (another frequent occurrence within neurodivergent individuals).
I also separated messages based on their function, and had them display in separate locations:
other messages, which at this point are all related to Account Management, pop up in the left hand side of the user bar (where the Account Management links and information are located).
This puts all messages physically close to where the relevant actions have been performed, preventing distractions and confusion, and aiding processing.
For the content of the recipes, I used photos and text from my own recipe collection.
For mocking up the profile cards, I used characters from Terry Pratchett's Discworld (see also the Credits section), as many neurodivergent people see themselves represented by them (see these examples).
Neurospicy is a popular self-identification of neurodivergent people, reclaiming their self definition and reframing neurodiversity as something additional or different to neurotypical identities, rather than lacking.
Given that spicy is also a salient feature of recipes, it seemed natural to combine both meanings in the blog's title.
The work to be done was divided into the following Themes:
Each theme was then divided into Epics, and Epics into User Stories, as seen here (click here for the original Sheet):
Each epic was assigned a distinctive color, which was also used for its label in GitHub Issues. Epics belonging to the same Theme were assigned colors of similar hues. This facilitated getting an overview of the work items.
Finally User Stories were broken down into tasks. These can be seen for each User Story individually in GitHub Issues and on the Project Board.
As this was my first project using Django, some User Stories have a very detailed task list, both as learning and as documentation/reference. Issues that have tasks that were already familiar only have high-level bullet points.
Some work items that have initially been classified as Epics have later been reclassified as User Stories – typically these were "meta" items to do with testing and documentation.
Estimating the time it would take to complete each User Story is notoriously difficult, doubly so with the first project in a new framework. This is why I did not assign sizes to the individual User Stories, instead, I treated them as one unit.
This proved to be the right strategy in retrospect, as inexperince caused me to take disproportionately long on tasks that would be much faster the second time around. On the other side, some other tasks could be completed much faster than estimated. All in all, the lack of relative sizing of individual User Stories did not have an adverse effect on the project.
The Issues were added to the Project Board in GitHub projects. This has a table view and a Kanban board view – this was the one I used most during development.
I have customized the Kanban columns to fit the project needs, and also added swimlanes representing milestones.
I have used several categories of labels during the project:
p:
)epic
label to enable filtering between Epics and User Stories on the Project Boarde:
), to be assigned to the Epic and all its corresponding User Stories(since GitHub Issues does not provide any other way to link these).
The individual epic labels are color-coded to match the Google Sheet containing User Storiesbug
, enhancement
, mentor
, etc.These have provided an excellent way to both filter Issues and to maintain an easier visual overview of them.
As the available time for development was only 3 weeks (setting the 4th week aside for testing and documentation), sorting User Stories into must have
, should have
, could have
and won't have
was done on the whole group of User Stories rather than on a sprint-by-sprint basis.
I have modified the MoSCoW method slightly in that I split the won't have
label into two:
wont have
are duplicates or mistaken issuesv2
.The links below show the User Stories excluding "meta" issues such as testing & documentation.
must have
: 39should have
: 11could have
: 28The statistics on planned vs. implemented User Stories can be seen on the Statistics tab of the User Stories Google Sheet.
Epics that had User Stories of various levels of prioritization received all applicable labels. As the User Stories in the Epic were completed, the labels of completed User Stories were removed from the Epic.
For example, EPIC: View author info has one User Story with priority should have
completed, and another User Story with priority could have
remaining to be done in version 2. Thus the label p: should have
was removed from the Epic, and label the remaining p: could have
.
The available development time for the project was 4 weeks. Accordingly, work items were divided into 4 milestones:
The first 3 milestones were assigned the User Stories discussed so far, while the last milestone was planned for "meta" tasks like testing and documentation.
Each milestone was assigned to a week-long sprint.
Initially, roughly the same percentage of must have
, should have
and could have
Stories were assigned to all 3 sprints.
However, as tends to happen in real life, different sprints had different velocities, which is reflected in the uneven number of User Stories completed in each sprint.
At the beginning of every sprint, I reviewed the Issues assigned to the current milestone and decided the order in which they are to be implemented, in a more fine-grained way than the existing prioritization labels.
I also defined tasks for the highest priority items, with tasks definitions for lower-priority items following as soon as it became plausible that I can finish them that sprint.
Whenever I have received updated information about prioritization or implementation from my mentor or the Code Institute community, I would also make appropriate changes in prioritization during sprints.
At the end of every sprint, I reviewed the items that were not completed, and either reassigned them to the next sprint, or to version 2 of the project.
This section briefly introduces the features implemented in the current version of the project. For videos demonstrating how each feature works, see the Manual feature testing section of TESTING.md
.
collection
appThe navigation bar is present on all pages, and contains the most frequently used functionalities:
On small viewports parts of the navigation bar are hidden by default and revealed by tapping the hamburger icon.
On desktop views, all nav bar items are visible by default.
This dropdown lets users choose between pre-defined color themes. Currently, these are orange, blue and green, but more options are planned for future versions.
The selected color theme is persistent, that is, it remains in effect even if the user navigates to another page within the site, or opens it in another tab.
The user bar is situated immediately below the admin bar and is present on all pages. It contains dynamically updated information on the user's login status, and links to the Signup & Signin or the Signout pages, as appropriate.
The left side of the user bar displays ephemeral messages relating to login status (seen dynamically in the videos in Authentication manual testing).
The user bar is also fully responsive.
The footer shows the site developer information and social media links. These open in a new window. The footer is present on all pages and is fully responsive.
The home page shows published recipes in a responsive grid, with pagination links displaying at the bottom when needed.
Each recipe card is clickable as a whole, to see the details of the selected recipe.
The top of the home page has 4 filters:
These show recipes with the selected recipe attributes in the same grid structure as the home page.
In the current version of the app, only one filter can be active at a time. I hope to extend this functionality for future versions.
The search page displays recipes where the word entered into the Search field (in the navigation bar) is found in any of the following fields:
The results are displayed in a responsive grid used on the home page.
This page shows the different pieces of information relating to the selected recipe in visually distinct, minimally styled blocks.
These include:
Visual separation and simplicity aids processing, which can accommodate users with attention or executive functioning issues.
Signed-in users can comment on recipes using the form at the bottom of each recipe detail page. All comments need approval before becoming visible to other users.
Once a superadmin approved a comment, it becomes visible regardless of login status.
Comments can be edited by their author. Edited comments change back to unapproved.
Users can also delete their own comments regardless of approval status.
community
appThis is the starting page of the community
app, and shows all user profiles in a responsive grid.
Similarly to the recipe list, the whole surface of a profile card is clickable to view individual profile pages.
Each profile page shows the information users chose to share publicly (if any):
The profile detail page is also fully responsive.
Access management has been implemented using Allauth. All functionalities work as intended, and the Allauth templates have been adjusted to fit the styling of the site.
See the the writeups and videos in Authentication manual testing for more details.
The Admin Panel enables the superuser to manage all objects in all models in the app.
They can add any objects associated to any user, for example, add a recipe with any user in the database as the author.
They can also manage all instances of related models from the Recipe Admin view.
The current version of the app does not contain the functionality to manage recipes from the website's UI. Following the suggestion of my mentor, I have deprioritized this and focused my time on creating automated tests instead.
As an interim workaround, I have set up the Admin Panel to provide restricted access to Staff users (Gytha and Tiffany), so that they can manage their own items, but not others'.
Below, we can see the options of the Admin Panel for staff user Tiffany. The available models on the left hand side are considerably restricted, as is the list of recipes, as only those recipes are shown where Tiffany is the author.
Inline foreign keys are also restricted, as shown below: the Staff user can only select themselves as the author of the recipe.
Finally, we see that related models are also limited: the Comment model does not appear in the Recipe view for the Staff user, and Attributes can be added to the recipe, but cannot be modified (as opposed to the superadmin view).
For future versions of the project, I would like to implement those User Stories that could not be done for this version for lack of time. They are listed under the label v2
.
In addition, I would like to extend customization options for the color theme selector, with a wide range of monochromatic palettes, thematic multicolored palettes and dark mode(s).
Similarly, I would like to extend filtering capabilities to combine several filter vectors and also filter for negative attributes (e.g., "not bitter").
Code was manually tested and validated throughout development. At the end of the development process, a final, comprehensive round of testing and validating was completed. The results are detailed in TESTING.md.
Apart from making sure that the app functions as intended, I have also taken special care to make sure the code is well organized and appropriately commented. Since I am just becoming familiar with Django (and dealing with executive functioning issues), I have erred on the side of "more is more" for code comments and docstrings for methods that were new to me.
I have also done my best to adhere to the principle of Don't Repeat Yourself (DRY).
The Javascript files written for this project have been through several iterations of refactoring.
I have also restructured the templates of the collection
app so that the home page, filter results page and search page all use the same code snippets for displaying the recipes and pagination links.
.mov
to .mp4
The following instructions describe the deployment process with the tools used for this project. Of course, you can choose other tools/providers for the individual functions described below, e. g., a different Postgres database instead of Neon, or a different development environment instead of GitPod. Naturally, detailed instructions are only provided for the tools used in this project.
You can fork the repository by following these steps:
[!TIP] If you do rename the repository, make sure to keep the GitHub naming conventions in mind.
pip3 -r requirements.txt.
env.py
in your top-level project directory.
Before adding any content to it, add env.py
to .gitignore
and commit your changes.
This will prevent the contents of env.py
from being pushed to the Git repository.env.py
file:
CLOUDINARY_URL
-you can find this in your Cloudinary console under API KeysDATABASE_URL
DEFAULT_FROM_EMAIL
SECRET_KEY
settings.py
, add your GitPod workspace URL to ALLOWED_HOSTS
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
Make sure to complete the following pre-deployment steps in your development environment, especially if you made changes to the project:
pip3 freeze > requirements.txt
. This popuplates your requirements.txt
file with the list of required files.python manage.py collectstatic
settings.py
, make sure DEBUG=False
CLOUDINARY_URL
-you can find this in your Cloudinary console under API KeysDATABASE_URL
DEFAULT_FROM_EMAIL
: this can be the same as EMAIL_APP_USER
EMAIL_APP_PASSWORD
: instructions for obtaining oneEMAIL_APP_USER
: the email used with your email serverSECRET_KEY
main
branch of your GitHub repository (but make sure your settings.py
file always has DEBUG=False
when you do). See the document TESTING.md
for details.
The following resources were used to learn/double check general, atomic functionalities/syntax/errors:
durationfield
in Djangoverbose_name
: change model display name in admin panelAttribute error (missing)
caused by indentation error in views.py
sessionStorage
docsquerySelector
documentationReverseManyToOneDescriptor
object has no attribute" errorinclude
documentationelif
vs else
error: "Exception Value: Unexpected end of expression in if tag"import cloudinary
in settings.py
ModelAdmin.get_queryset(request)
formfield_for_foreignkey
documentationfloatformat
template tag Profile texts for the mockup users based on Terry Pratchett's Discworld series were taken from Wikipedia. The description of Geoffrey Swivel was adjusted to use the correct pronouns.
All other text was written by me.
Lemon bar recipe based on Chili&Vanilia's post.
Red velvet cake recipe based on Pamela Moxley's post.
Logo/favicon by janeb13 on Pixabay, converted to ico
format with Favicon.io
.
All other pictures taken by me.
A person unknown to me has forked the project repository and submitted a pull request with some code comments added. I had not communicated with this person before this nor asked for their contribution to the repository. The pull request was closed without merging.
I would like to express my deepest gratitude to my mentor, Rory Patrick Sheridan for his incredibly useful and understanding support throughout the project. Issues raised by him or discussed with him can be found here (see the individual ticket descriptions for the details of his contribution).
I am also grateful to the Code Institute tutoring team, in particular, to John and Roo for their help. The details of their contributions can be found here.
I would also like to thank Peter Litauszki for photo and video editing help.