Introduction
Projectree is a service that you can use to create simplified showcases of projects you have worked on.
Create and showcase your projects lists without the hassle of building it yourself. Just add your project details, choose a theme, and generate!
Creating a projectree is as simple as entering the information for each project, choosing a predefined theme, and generating the project! You can then download your generated projectree and host it on your own site.
Projectree was developed by Sophia and me (Danidre) for the PlanetScale x Hashnode Hackathon, where the main criteria involved using PlanetScale as the database.
How Projectree Qualifies for the Hackathon
What I described so far is a tool that lets developers create and download their mini project showcases. A simple tool, right? Thus, you may ask: "Where is the database involved?"
Additional Features
By default, Projectree can only create and edit one projectee for users on that browser. However, if developers want to save multiple projectrees (for different purposes), they can do so by creating an account. Signed in users have access to a dashboard overviewing all their projectrees, where they can tweak each individually.
Even More Features!
With a Projectree account, developers can also host their projectrees directly on the website for others to view.
In Summary
User accounts, authentication, multiple projectrees, published projectrees... all these features require the database, which qualifies this project for the hackathon, as we use PlanetScale as this database.
Features
Tier | Signed Out | Registered User |
Generated Projectrees Available | Unlimited | Unlimited |
Maximum Projectree Drafts Available | 1 (overwrites previous information) | Unlimited (create and edit any amount) |
Hosting Plans | Not available (only downloading available) | Unlimited |
Creating a Projectree
To create a projectree, a developer can navigate to the /create
route and begin editing. There, they can enter the details of their projectree, add project items, and customize those items, entering the project's name, description, languages used, source repository link, and demo site link.
Additionally, developers can add photos to the projectree by pasting existing links of photos.
There are plans on the roadmap to allow developers to upload their own photos, hosting them on cloudinary or uploadcare.
After the developer enters the data, they can choose an existing theme from which the projectree will be styled and generated.
Target Audience
While doing market research on the need for such a project, a FANG interviewer said that they would instantly skip a generated portfolio for a frontend position. I also believe that frontend developers/designers should develop their own portfolios and take the opportunity to showcase their skills.
Benefits for developers
Projectree may be most useful for fullstack, backend, devops, or other relevant positions where the focus of their work is not on the display of their design skills. If they still want a tool to quickly showcase their projects (without having to click into every GitHub repository, for example), Projectree can help. The showcase can display what the project is about, before checking out the repositories, allowing the viewer to decide whether to look further on any one project that catches their eye.
Built With
Projectree is a tool that allows developers to create project showcases, host it for them, or allow them to download it and host it elsewhere. Seems like a pretty simple application, right? However, it's not!
While accustomed to full stack development, I generally despise the database and deployment side of development. Thus, I partnered with Sophia for this hackathon. The agreement was that Sophia would work on the backend, connect to the database, deploy it, and provide APIs for me to consume on the frontend.
Frontend Stack (Danidre)
Langauges and libraries used
- HTML
- CSS (using Twind; for styling)
- JavaScript (using DCL)
- Netlify (for hosting)
Why I used them
I just planned to create something simple; nothing complex. I just needed some HTML, CSS, and JavaScript, and would use many fetch requests to the backend. But I would not be serving multiple views from the server, as everything would be client side. However, I still wanted the flexibility of reusing multiple components (like navigation bars and footers) without duplicating the code on separate frontend pages.
Additionally, I could not choose between React, Svelte, Solid, Vue, Handlebars, Pug, or other libraries and frameworks. React and other libraries come with the complication of requiring build tools or bundlers to compile or transpile code. I just wanted something I could drag and drop into Netlify, and it would work! Thus, I decided to create a library myself!
Because who gives up on an opportunity to learn something new!
I called it DCL, short for Danidre's Client Library (for lack of better name) and it has its own routing system, component nesting, event listeners, global states, and more.
All in all I probably spent 60% of the frontend work developing DCL, and the other 40% developing the frontend for Projectree, using DCL.
A lot of nights were spent teeth grinding and bug solving DCL errors that made me wish more and more than I used an existing framework...but... did it for the learning experience ๐
For styling, I used Twind, the smallest, fastest, most feature complete tailwind-in-js solution in existence. With this, I did not need PostCSS (which includes a build-step) which benefitted the Netlify drag and drop model I wanted.
In Summary
I wanted something simple; nothing complex. I did not need React or anything else that required bundlers and extra steps. In the end I created a mini library that caused headaches throughout development, but I'm really proud of what it turned out to be.
There is no official public repository dedicated to DCL yet, but you can check it out in Projectree's source code.
Backend Stack (Sophia)
Langauges and tools used
- Python (using Django & DjangoRest Framework; for API)
- MySQL (using PlanetScale; for database)
- Heroku (for deployment)
Why I used them
The backend structure is built using Django and Django rest framework. I used the framework to build the API (Application Program Interface) that connects the frontend to the database. I used Django because it is robust and easy to use; in addition, every API built using Django is very secure.
Since Projectree is a simple web app, it was easy for me to build and secure users' data. I chose Django because building API with its framework is easy and creating secured APIs and optimizing the database using Django was smooth for me.
The user authentication system on the backend is built based on JWT Authenticatication and each user uses a bearer token to create, edit, delete and view projectrees, project items, and published projects. Once the token expires, the user is logged out and must log in again to continue accessing advanced services on Projectree.
Building this project gave me a better insight into the authentication and authorization of Django and its framework. I talk about authentication because without that, the backend system and database would be exposed to malicious users. I believe security is the major thing to consider when building a backend system. Always validate. Never just trust the client.
In Summary
It was an exciting journey learning about how Django works and the way authentication and APIs work. Django being robust, SEO optimized, rapid, easily scalable, and versatile were my main reasons for choosing the stack for this project.
Development Roadmap
Projectree aims to be simple enough to use that a developer can create their project showcase in as little as 5 minutes. For that, the features prioritized were minimal proofs of concept, with future plans for features than can enhance the user experience of the service:
Icon | Meaning |
๐ป | Frontend |
๐๏ธ | Backend |
โ๏ธ | Both Frontend and Backend |
[x] v 0.1
- [x] ๐ป Set up a single page application
- [x] ๐ป Develop custom frontend library
- [x] ๐๏ธ Set up a django application
- [x] โ๏ธ Add readmes and licenses
- [x] โ๏ธ Determine database models and schemas
- [x] โ๏ธ Plan API routes
- [x] โ๏ธ Set up github repos
[x] v 0.2
- [x] ๐ป Make "Create Projectree" prototype page
- [x] ๐ป Develop a standard theme for projectrees
- [x] ๐ป Allow users to download generated projectree
- [x] ๐๏ธ Set up local database
- [x] ๐๏ธ Develop register/login authentication
[x] v 0.3
- [x] ๐ป Create sign up, sign in, and dashboard pages
- [x] ๐ป Make "Create Projectree" prototype page
- [x] ๐ป Deny or allow access to pages based on user authorization
- [x] ๐๏ธ Create projectree models
- [x] ๐๏ธ Develop REST APIs for projectrees
- [x] ๐๏ธ Add route validation based on user authorization
[x] v 0.5
- [x] ๐ป Create and style landing page, 404 page, and remaining pages
- [x] ๐ป Host frontend on Netlify
- [x] ๐๏ธ Connect to planetscale database
- [x] ๐๏ธ Test all API routes locally
- [x] ๐๏ธ Deploy backend to Heroku
[x] v 0.6
- [x] ๐ป Add meta tags for SEO
- [x] ๐ป Create page to view published projectrees
- [x] ๐ป Add privacy policy and tos pages
- [x] โ๏ธ Connect frontend to backend
- [x] ๐ป Add more predefined themes users can choose for their projectrees
[ ] v 0.7
- [ ] ๐ป Use modals for alerts, prompts and confirms instead of browser natives
- [ ] ๐๏ธ Add email confirmation when registering
- [ ] ๐ป Allow users to upload their project images instead of using a link only
- [ ] ๐ป Add user profile dashboard
- [ ] โ๏ธ Allow users to reset passwords
- [ ] ๐ป Allow exporting and importing projectree drafts as json
Challenges Faced
While Projectree seems like a really simple project, the challenges we faced during development took us the entirety of the month to complete it!
Frontend Challenges (Danidre)
I spent majority of the time working on DCL (Danidre's Client Library) for everything to work. Most of my challenges involved tweaking its source, fixing bugs that broke everything, and adding features that would make development easier for me. These include the following:
Creating a Router for Pages
I originally started off with this code on YouTube to create an SPA (single page application) with just JavaScript. I made use of history push and pop state so that the page would not have to refresh on every link clicked.
Creating Nested Components
Afterward, I modified the code to make everything a component. That way, they can render other components by looking for the returned html in each.
Handling State Changes
When state changes in a component, it needs to rerender everything in it to reflect the updated state. Instead of using a Virtual DOM (like React), I opted to wrapping each component in a fragment div by default, with unique dataSet IDs to identify those components alone. Then, the classes and dataSets are passed from that wrapper div to the main element returned for that component.
When it is rerendered, the element is first found on the page by the dataSet ID, rerendered with the wrapper, and then swapped to the child again, where the wrapper is removed again. This way, the wrappers do not break the intended developer's html semantics, as they are used just for rerendering, and then removed.
Handling Global Changes
Similar to React's useContext, DCL uses context in a publish/subscribe model, where components can monitor changes of specific context values from the global application, and rerender based on that global change.
Handling Focused Inputs
React has onchange handlers for input components that set the state as it is entered by the keyboard. However, when the components are then rerendered in DCL, the selected component is deleted and recreated, thus focus is lost. To regain the illusion of focus, DCL "remembers" the last component selected using the html's XPath, and after rerendering, tries its best to find and focus that element again. It also remembers the point in the input element that was selected, and reselects it, maintaining the focused element even when input changes.
Preventing Leaving Unsaved Changes
DCL also has a beforeNavigate
event that the developer can use to prevent the page from being left (or reloaded) if data is not yet saved.
Ignoring Certain Routes
DCL also has an ignoreRoute
method that can be called inside any component to skip rendering that page. For example, if a logged out user tries to navigate to the dashboard, the route will be ignored and the Error 404 page will appear instead.
In Summary
All these features were worked on side by side with the development of Projectree itself. During each hurdle, I wished more and more that I used an existing library that already solved these challenges, but in the end I am very proud of what I managed to create, and how fast it works!
It is plain JavaScript, after all.
Backend Challenges (Sophia)
I spent my time sketching the database (DB) schemas and thinking of the best way to design the database so that requests are seamless and fast. Unfortunately, I had lots of bumps on this development road and had lots of challenges fixing bugs. Deploying the backend with PlanetScale was the most challenging:
Pushing to PlanetScale DB
After extensive development, I finally realized PlanetScale DB does not support foreign-key constraints. It was a bit difficult for me to return to the drawing board and re-design everything. After that, deploying the backend to Heroku took me a week to solve because Heroku could not recognize the django_psbd_engine
:
I had to clone another open source project to help me understand what I did wrong and how I can resolve that. In the end, the error was caused because I did not set the wrapper correctly around the database settings in the backend's settings.py
file.
Thanks to Brian from the Developer Education team at PlanetScale for his support and assistance in deploying to Heroku.
Building a Custom User System
When Danidre brought up this idea, I made it a mission to build a custom user authentication system rather than using Django's packages such as django-allauth, or djangrest-routes.
It was a bit difficult because I had no idea what to do or where to start, so I read some articles and watched videos explaining how to start building a custom user model and securing the model using authentication and authorization. I finally got it right the third day!
...and then came the errors and bugs...
In Summary
All features are currently working successfully! It may not be as professional as full fledged APIs in enterprise projects, but I loved the experience, the thrills I got, and the excitement I got from every fixed bug or error. In the end, I am super proud of the system I built and its level of security; sometimes I can't believe I wrote this!
Running and Deployment
Check the GitHub Documentation on deploying a fork of Projectree.
Conclusion
Projectree aims to allow the quick creation of project showcases. We hope you find it useful!
See the links below to support us or check the project out yourself:
- GitHub: Frontend | Backend
- Application Link: projectree.net
- Twitter: @danidre | @sophiairoegbu_
- Patreon: Danidre