Monday, June 19 2023

Elaichi: Open-Source Jira Alternative with Upstash, Firebase Storage, SvelteKit and TailwindCSS

While online solutions such as Linear, ClickUp, Jira, etc. offer Kanban Board for great plans, I was in trouble finding a one which was self-hostable (and hence cost saving). These tools often require teams to pay for user licenses or monthly subscriptions, which can become expensive as the team grows or if multiple projects are being managed simultaneously.

While Linear is a great modern tool to manager your tasks, it doesn't support self-hosting.

So I set out on creating the system with Firebase Storage, TailwindCSS, SvelteKit and Upstash.

The Tutorial

Find the tutorial covering technical implementation of the app at Upstash's Blog: Building an open-source JIRA using Firebase, Upstash and SvelteKit

Key Highlights

1. SvelteKit Auth with Auth.js

Authenticating users is a common way to prevent misuse of a product. With Auth.js, I was able to integrate Google OAuth 2.0 in a few lines (including building a custom login page!). Beyond that, I was able to protect edge functions with the auth by accessing SvelteKit Locals. Read more about that here.

2. Detailed Task View

Inspired from Linear, the task view includes the ability to upload any kind of content, establishes a debounced sync between the current task data vs what's in the database, multiple task status parameters such as priority, status, due date, and if the task is active anymore. Combine all this with as you like it refresh button to hit when you want to sync the task view with the database. Learn all about that here

3. Writing my own very lightweight 422B Toast library

In the process of finding a toast library with Svelte, I set out to create one instead. I wrote a function which manages Toast timeouts, ids, and is able to show non-text toasts. All of it just weights 422B and uses TailwindCSS as it's styling library. Great thing? It can be used with any framework! Here you go:

export const showToast = (message: string, time: number = 1000) => {
    try {
        if (typeof window !== 'undefined') {
            if (!window.toasts) {
                window.toasts = {}
            let randomToastID = Math.random().toString(16).slice(2)
            let div = document.createElement('div')
            div.className = 'w-[75vw] md:w-[420px] z-[1000] bg-white fixed right-10 bottom-10 py-4 px-6 rounded shadow border flex flex-col text-sm text-black'
   = `toast-${randomToastID}`
            div.innerHTML = message
            document.body.insertAdjacentElement('beforeend', div)
            let timeOutForThisToast = setTimeout(() => {
                const selector = document.getElementById(`toast-${randomToastID}`)
                if (selector) {
                    if (window.toasts) {
                        delete window.toasts[randomToastID]
            }, time)
            window.toasts[randomToastID] = timeOutForThisToast
    } catch (e) {
        const error = e.message || e.toString()

4. Using TypeScript in a production app

After a long interval of procrastination, I finally used TypeScript in full fledged form in a production app using SvelteKit. The previous instance of using TypeScript was during my product engineer internship at wellOwise, where I used Angular for the first time in my life, and translated the whole product idea to workflows to reusable UI.

5. Using Upstash for Rate Limiting

As greatly advertised, Upstash's Rate Limiting can be used for various purposes, from preventing DDOS to restricting the number of tasks a person can create in a given time. This allows to prevent abuse (or misuse) of the APIs shipped with the product. In turn, this overall helps ensures a greater uptime, and less hassle in our meaningful lives.

Write a comment

Email will remain confidential.