What is Lumia
Lumia is a QnA platform that revolves around courses provided by school/universities , so that students can ask questions around those courses, and better prepare for their semesters.
Github Link
https://github.com/AshCatchEmAll/-Lumia-
Inspiration
Planning your semester and enrolling in a combination of classes that will help you maintain or improve your GPA are important for students. Talking to students who have taken a particular course before might be beneficial in order to learn how they managed the course load, which textbooks they used, what they would do differently if they had to do the course again, and so on.
This can help students to manage their semesters and plan ahead properly before enrolling into a course.
Tech Stack
- Nextjs : Since Lumia involves user generated content , I wanted the SEO to be good and use server side rendering for the pages.
- Firebase : Lumia delegated authentication and user management to Firebase.
- Graphql : For live notification updates while using Lumia , Lumia relies on Graphql Subscriptions. It will further improve upon realtime updates for better UX through graphql.
- Planetscale : For complex relations and no pain schema change deployments, Lumia heavily relies on planetscale, a MySQL DB that just works.
- Prisma : To utilize its full type safety and automated workflows to ship schema changes and write queries with less work.
- Render : To deploy Next.js app.
Features
Search page : Search questions on Lumia. This is possible with help of Prisma+Planetscale full text search.
Bookmarks : You can bookmark questions or answers and view them in your bookmarks sections.
Drafts : You can write a question and save it as a draft so that you can come back to it later, perhaps on a different device and continue editing it before posting it.
Engaging comment section : Taking inspiration from Youtube comments, I build a comment section which can be intuitive. For the actual comment sections , its mostly just modern CSS and Flex box.
Notifications : You can view if someone likes your question or answer and replied to your question.
Designing
Product definition : Lumia is a QnA platform that revolves around subjects provided by school/universities , so that students can ask questions around those courses, learn about what previous students did to survive the course load, get to know useful resources for that course and much more which will help them better prepare for the school / University semesters.
Value proposition : Being a student made easier
Goal statement : Our platform will let users organize their semesters efficiently which will affect students by helping them keep healthy study - life balance and maintain a tolerable course load. We will measure effectiveness by feedback forms and Net Promoter Score.
User persona
Storyboard
Low Fidelity
Medium Fidelity
Logo making process
First Sketch
Importing to figma and tracing with Pen tool
Setting up Planetscale
To harness the power of Planetscale we need to set it up first. The following setup is for MacOS
Installing pscale CLI
Type the following commands one by one.
brew install planetscale/tap/pscale
brew install planetscale/tap/pscale
Type pscale --version to check if installation was successful. If It throws and error with something like command not found: pscale , execute the command below
brew link pscale
Best practices
Prisma & PlanetScale best practices
Lumia follows the following best practices when it comes to Prisma + PlanetScale setup.
Referential integrity : Since planet scale doesn't support foreign key, that means the referential integrity that the underlying DB (MySQL in this case) provides i.e your relations being valid are no longer enforced in context of PlanetScale. For that reason we have to set referential integrity in your Prisma schema. With this, Prisma will emulate the database behavior and ensures referential integrity of your relations.
Migration using db push
: Typically with Prisma you use prisma migrate
in order to generate SQL migrations for you based on changes in Prisma Schema. But in this context since the resposiblity of actually applying the schema changes in on PlanetScale side (along with having different branches for your schema โจ) , we need to use db push
instead.
Defining indices on foreign keys : Adding to the first point about referential integrity, since its Prisma that is taking care of relations, no foreign keys are created in your database schema and therefore no indexes is created for those fields that represent the foreign key pointing to another table. This can lead to inefficient table scans for a query. This not only slows down your queries but might increase your bills on PlanetScale. So its a good practice to add indices on these "foreign keys".
Prisma + Next.js best practices
Lumia follows the following best practices when it comes to Prisma + Next.js setup.
When using next dev
for local developement, it clears Node.js cache on run. This in turn initializes a new PrismaClient instance each time due to hot reloading which can quickly exhaust the database connections as each PrismaClient
instance holds its own connection pool.
To avoid this for Lumia, it instantiates a single instance PrismaClient and save it on the global object. Then it keeps a check to only instantiate PrismaClient if it's not on the global object otherwise use the same instance again if already present.
Graphql + Next.js
Lumia follows the following best practices when it comes to Prisma + Next.js setup.
For Graphql Queries and Mutations you can add your Graphql server to your nextjs app by using Graphql-Yoga by following this setup documentation. After adding this when you hit /api/graphql , the calls are delegated to Graphql-Yoga.
If you want to use Graphql Subscriptions its better to have a different server outside of the Next.js server. Mostly because GraphQL-Yoga uses Pubsub class for subscription. You need to make that the Pubsub instance your client is subscribed to is the same one that your server is publishing to. Otherwise your client would never get the Subscription payload.
Hence Lumia separates the Graphql logic into a separate Graphql server instead of in api/ directory.
What I learned
PlanetScale : PlanetScale makes working with MySQL painless. There were so many times where I updated my schema along the way, created new branches if there was a drastic update, or had to switch back to another schema. Its so smooth it seems like magic ๐ช.
Prisma : The Prisma ORM has been evolving with features very quickly and has become a go to tool in a short amount of time. Using Prisma + PlanetScale is such a delight. Dev tools like Prisma studio can help you a lot during development. I am glad I learned how to utilize it through this project.
- Flex Box : I mostly used Grid for layouts but sometimes flex box makes layouts easier. Especially to make columns and rows or combination of those. Best resource to learn about FlexBox is (given that you know fair bit of html & css) this guide to Flexbox by Chris Coyier on CSS tricks
Dynamic state with Redux and React - In Lumia, there are places where grab a list of something and I want to have state for each of them dynamically. Something like the following:
{ [id1] : { name : "name here", title: "title here", content: "content here", }, [id2] : { name : "name here", title: "title here", content: "content here", } }
So every item in the list has their own state attached to their ID which is dynamically added to Redux store when I fetch em. Pretty neat ๐ The implementation will differ based on which libraries you are using (redux-tools, react-redux so on) but a general explanation is here by Muhi Masri
What I would do differently next time
The Cascading mess : Lumia uses Material UI and custom CSS. Adding
className
to MaterialUI components with corresponding CSS doesn't always give you the result you want. You can add custom styles to MaterialUI by using thesx
attribute. Now because of this along the way , you might find yourself directly adding styling to the component itself, unable to reuse them, unable to debug when necessary cause they are not organized at one place and also makes it hard to change the design in future.Luckily in MaterialUI V5.9.2, there is a
styled
utility. It helps us create reusable components with the same overrides in different locations across your application. I would definitely be using this oversx
attribute.Because there is a lot of CSS in Lumia, I decided to read up on how other devs really organize their CSS. There is anamaaazing article on this by Inessa Brown on CSS-Tricks. Definitely following one of these methods next time.
Spend more time on prototyping : Value of prototyping lies not in the code produces but in lessons learned. It helps with understanding the architecture and how you will be putting all the stack components together. Following is a sort off todo list for prototyping from the book Pragmatic Programmer :
- Are responsibilities of major areas well defined and appropriate?
- Are collaborations between major components well defined?
- Can you identify potential sources of duplication?
- Does every module have an access path to the data it needs during execution?
Broken window theory : Avoiding broken windows and not leaving them unrepaired , fixing them as soon as it is discovered. In this context the broken windows are all the unconventional
- Optimistic UI : Platforms like Lumia where its mostly user generated content, the user experience has to be enjoyable. Users don't wanna see loading animation everytime they do some simple task. I learned something called Optimistic UI while using Meteor.js (another framework for fullstack dev). I would spend more time in coding necessary components for Optimistic UI. If you are interested to know what Optimistic UI is, you can read this article.
Most of these might seem like a newbie mistakes. For me as a dev , there will always be a knowing doing gap. More I learn more I realize I know so little of these different programming languages , stacks, software programming in general. My goal is to revisit all the things I know & learn more until I have almost closed the knowing doing gap.
Whats next for Lumia
Dockerizing Lumia : The main idea for Lumia is that , every university/school will have their own cluster (Kubernetes Cluster in dev terms) which the admin can deploy. This way the admin can control who gets to signup , have moderation and also every university/school will have their own Lumia which will help with relevancy when it comes to the questions and answers.
Option to mark as "Best Answer" : This will help users find answers correctly without having to scroll all the answers.
Support images and emojis in questions and answers : Most of the times , emoji and pictures are necessary to get a point across. A q&a website would be more useful if it supports images and emojis.
Adding translate options (like in youtube comments) and dark mode : Accesibility score for Lumia can be increased by adding translation options (Using Firebase) and adding dark mode for users who prefer darker colors.
Adding PWA support : Progressive Enhancement and Graceful Degradation are the two essential components of a mobile-first design approach. Lumia is designed using mobile first approach. It would add to the UX if it gets PWA support so that users can run Lumia natively on their devices especially mobile phones and ipads which students tend to use more often.
Thank you
Big thanks to PlanetScale and Hashnode for giving me opportunity to build this project โจ๐ธ ๐ป