Spekni - A recognition platform built for developer endorsements
Spekni is a platform for recognizing developers making an impact, contributing to better open-source projects, helping other developers, creating quality tutorials, and writing helpful articles in the tech community for the sole purpose of getting them noticed by the right people.
Spekni also works as a platform for finding capable developers because we simplify the process for recruiters to find passionate developers. We know most companies find it hard to find well-experienced developers who match the skills on their resumes. Endorsements from other experienced developers can go a long way in fixing that problem.
Inspiration
Most developers do not seek credit for their work, tirelessly putting in a lot of effort to deliver great projects for users, clients, and other devs. Sometimes developers who constantly give back to the community are the least appreciated, and as such, they sometimes find it hard to get recognition for their work. This is what we hope to fix with Spekni ๐
UI/UX and Style Guide
We choose the color blue which signifies trust, peace, loyalty, and competence just like Hashnode. The design was done completely on Figma, and we drew inspirations from several websites like Vercel, Toptal, Peerlist, etc. Since this is a product for developers, we had to add a dark mode feature with system default theme switching. ๐
How does Spekni Work?
๐ Login
To get started on Spekni, simply visit the login page, in this page, we've provided two sign-up mediums: GitHub and Google. This authentication is powered by NextAuthJS.
๐ Edit Account
After connecting your account, you'll be redirected to the edit account page, in this page users can fill up the form with their bio information, job description, social accounts, and finally, their stack/tech skills,
The skills in this section are set up in a way that they would be endorsable by another user that is fully registered and authenticated on the platform. For now, a user can have a minimum of 3 skills and a maximum of 6 skills which we might increase later. The skills input fields are limited to 40 characters because we expect keywords like JavaScript, Public Speaking, Open source, NextJS, Technical Writing, C++, PHP, etc.
Though we are still working on making this more accessible to users, so if you have suggestions or ways we can improve on it, you can drop your suggestions, and we might give you a shout-out in our changelogs if they are implemented. ๐
๐ Profile
Automatically all data provided in this form are stored on the PlanetScale database. A simple configuration of the database and code will allow these skills to be endorsable. Your profile is stored in your unique username which another user can visit to see your profile, for example, you can check out my profile: https://spekni.vercel.app/eke
๐ Endorsements
Once you finish setting up your profile, you can now start getting your skills endorsed by other people who register on the platform. It's pretty straightforward.
๐ Recommendation
Users can also drop recommendations to other developers by visiting their profile and adding what they will like to say about the developer in the input box. Here you can talk in-depth about someone's particular skill, past projects, or overall behavior.
๐ Explore
The explore page is where all successfully registered members can be found. Once you set up your account, you are automatically added to this explore page. These users are stored in the PlanentScale database.
Excited about this? Join here ๐
Tools used in building Spekni
Spekni is completely built with NextJS for the frontend, NodeJS for the backend, and of course, PlanetScale was used for the database. Here's a short list of some of these tools:
- ๐ฏ NextJS - Frontend
- ๐ NodeJS
- โ๏ธ Vercel - Hosting and deployment
- ๐ NextAuth.js: GitHub and Google Authentication
- ๐ฆ PlanetScale: Database Storage & API
- ๐ ๐ฝ TailwindCSS / CSS - Styling and UI
- ๐๏ธ Prisma: database schema design
- โ๏ธ Next Themes: Color Theme
- ๐ญ Cloudinary - Cloud media storage
- ๐ผ๏ธ Lazyload NPM package: Image optimization
- โ๏ธ Mit License - Open source License
Frontend
UI framework
We used NextJS for the frontend because of its speed and SEO analytics. This is my first time working with NextJS and I have to say, I'm quite impressed with the framework ecosystem. One of the key reasons we used NextJS was to harness its SEO power and automatic routing system, which helped us tremendously to make Spekni fast and have a great SEO.
Without the need of using a routing system like react-router. Here's the folder structure of each of the pages on Spekni. Creating a file on this page automatically creates a route with the subdomain. Which is mind-blowing ๐คฏ
โโโ pages
โ โโโ [username]
โ โโโ 404
โ โโโ about
โ โโโ account
โ โโโ API
โ โ โโโ auth
โ โ โโโ users
โ โโโ explore
โ โโโ login
โ โโโ _app.js
โ โโโ _document.js
โ โโโ error.js
โ โโโ index.js
โ โโโ profile.js
TailwindCSS & NextJS module CSS
For the styling, we used TailwindCSS and their UI components from Headless UI to speed up the development of this project. In some cases where Tailwind was not reachable, we complimented with NextJS built-in CSS
Modules which allowed us to use the same CSS
class name in different files without worrying about collisions. The result of pairing these two resulted in smaller bundle size.
Backend
The backend for Spekni was built with NodeJS
Role of PlanetScale
Plantescale is an excellent service for creating databases swiftly. We used PlanetScale to store user data of people signed up on the platform. Here's a graphical representation of what the database schema looks like
We used Prisma as an ORM(Object-relational mapping tool) for our database, we also leveraged Prisma's schema feature to define types for database tables and entities which we pushed to planetscale
And here's an in-depth look of our schema
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialIntegrity"]
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
referentialIntegrity = "prisma"
}
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model Profile {
id Int @id @default(autoincrement())
bio String? @db.TinyText
job_title String?
githubLink String?
username String? @unique
portfolioLink String?
twitterLink String?
linkedinLink String?
fullName String?
userId String
email String @unique
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model Endorsement {
id Int @id @default(autoincrement())
userId String
skillId Int
fromUserId String
endorsers User @relation(fields: [fromUserId], references: [id], onDelete: Cascade)
skill Skill @relation(fields: [skillId], references: [id], onDelete: Cascade)
}
model Recommendation {
id Int @id @default(autoincrement())
userId String
fromUserId String
summary String @db.Text
createdAt DateTime @default(now())
user User @relation(fields: [fromUserId], references: [id], onDelete: Cascade)
}
model Skill {
id Int @id @default(autoincrement())
skillName String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
endorsements Endorsement[]
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
endorsements Endorsement[]
Profile Profile[]
Skill Skill[]
recommendations Recommendation[]
}
model VerificationToken {
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}
Best Practices
- Prettier and ESLint for linting, indentation, and consistent code styles.
- NextJS components and CSS variables to enforce DRY code.
- Asset optimization for mobile users.
- Using accessible and semantic elements
- Great lighthouse audit
We followed best practices and rules to ensure Spekni was accessible, easier to read, review and contribute to. Automatically, NextJS provided much of the configuration by default which is why we opted to use it. Even the lighthouse score was pretty amazing.
Running spekni locally.
git clone https://github.com/Evavic44/spekni.git
cd src
npm install
npm run dev
Open http://localhost:3000
with your browser to see the result.
Challenges
Building Spekni was an amazing experience, but there were some challenges we had that I believe will be beneficial to explain how we solved them.
Prisma windows error
We had a few system compatibility issues when running prisma generate
locally, and what was worse is that this error affected only the windows environment, running Prisma on Mac and Linux environments worked flawlessly.
Here is the error:
error - Error: @prisma/client did not initialize yet. Please run "Prisma generate" and try to import it again.
In case this error is unexpected for you, please report it at https://github.com/prisma/prisma/issues
Attempted to load @next/swc-win32-x64-msvc, but an error occurred: The specified module could not be found.
It took a lot of research and debugging but we finally discovered the issue was Microsoft VC++ redistributable package Prisma depended on was missing on my PC. After downloading and installing both the x32 and x64 bit versions, prisma generate
finally worked!
Additional Features and Summary
These are some of the features we weren't able to implement before launching Spekni. Though we are currently working on them so keep an eye out for the next release. ๐
- Endorsements Export: Users can add endorsements to their portfolio website through an
iframe
. - Recruiters: Find a list of endorsed recruiters with a good track record of hiring the best developers.
- Explore Search: A feature for finding developers registered on the platform.
Credits
It will be impossible to complete this project without giving proper credit to the persons that made this a success. After all, that's what Spekni is all about. In no particular order, here are the credits.
- PlanetScale - For providing an excellent database service
- Hashnode - For organizing this hackathon. ๐
- James Q Quick - For support and answering our dumbest questions on Discord ๐
- Eleftheria Batsou - For her amazing feedback and reviews.
Creators of Spekni
- Victor Eke - Frontend & UI Lead
- Spiff Jekey Green - Backend Lead
- Nicholas Ovunda - Backend and UI design
Important Links
This project was built for the PlanetScale and Hashnode Hackathon
Subscribe to my newsletter
Read articles from Victor Eke directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Victor Eke
Victor Eke
My expertise lies in building interactive web applications on the client side. Primarily working with technologies like JavaScript, Next.js, TypeScript and Python. I strongly believe in continuous learning and improving myself, so I try my best to learn in any situation possible, unfavorable or not. Beyond learning, I enjoy writing technical articles and creating projects that both inspire and benefit fellow developers.