Projects

Napkin Notes

An encrypted, lightweight, note-taking app for quick math, short-term tasks, and temporary notes.

Published March 23, 2024 | Updated April 1, 2024

napkin-notes

Links
Github →API Docs →Website →

Backstory

Napkin Notes was built over the course of a weekend as part of a solo-mission hack-a-thon. As a result, I paried down the feature set to only things I’d need when I need to quickly paste content or perform quick math during my day-to-day.

Quick Start

Napkin Notes is available at https://napkinnotes.app/ You can try it out anonymously, but to sync your notes across devices you’ll need to create a free account!

✨ Napkin Notes is a Progressive Web App, so on supported browsers and devices you’ll be able to install the app to your desktop. ✨

Supported Features & Widgets

FeatureTrigger Action
Headings (H1-H4)Markdown headings syntax (#)
BoldHighlight text and CTRL+B
ItalicsHighlight text and CTRL+I
UnderlineHighlight text and CTRL+Y
LinkHighlight text and CTRL+K
Unordered ListType * (* + SPACE)
Ordered ListType 1. (1. + SPACE)
Interactive CheckboxesType - [] or - [x]
Interactive Math ✨Type $ ($ + SPACE)
Code Blocks with Syntax HighlightingFence code in ```

Caveats & Known Issues

Napkin Notes is built using contenteditable which is prone to issues across browsers. Napkin Notes was built and tested on Chrome.


Dev Log

Development Stack

Catalog of the tools, resources, and services used in the creation of this project.

App

Tool or ServiceLinkDescription
Vue (Vue3)https://vuejs.org/Frontend framework
Vite PWAhttps://vite-pwa-org.netlify.app/Adds PWA Support to Vue
Vue useWebsocketshttps://vueuse.org/core/useWebSocket/Vue Websockets Support
Tailwindhttps://tailwindcss.com/Design system and CSS Components
Tailwind Componentshttps://tailwindui.com/Pre-built components from Tailwind; Uses Headless UI and Heroicons
Vue Google Loginhttps://github.com/devbaji/vue3-google-loginPowers “Login with Google” functionality
Hero Iconshttps://heroicons.com/
Bootstrap Icons Vuehttps://github.com/tommyip/bootstrap-icons-vueVue components for Bootstrap Icons
Highlight JShttps://highlightjs.org/Code Syntax Highlighting

Api

Tool or ServiceLinkDescription
Djangohttps://www.djangoproject.com/Backend framework
Django Channelshttps://channels.readthedocs.io/en/latest/index.htmlDjango websocket support
Django Rest Frameworkhttps://www.django-rest-framework.org/RESTFul Django APIs
DRF Social Oauthhttps://github.com/wagnerdelima/drf-social-oauth2Provides support for social login; Uses Python Social Auth and Django OAuth2 Toolkit;
Python Cryptographyhttps://github.com/pyca/cryptographyEncryption library used for storing note content
DRF Spectactularhttps://drf-spectacular.readthedocs.io/en/latest/Open API Schema Generator & Viewer
Stoplight Elementshttps://github.com/stoplightio/elementsBeautiful Open API Schema Docs
Django Unfold Adminhttps://github.com/unfoldadmin/django-unfoldA better Django Admin Experience

Dev Ops

Tool or ServiceLinkDescription
Renderhttps://render.com/Deployment and hosting for both the app and api
VSCode Dev Containershttps://code.visualstudio.com/docs/devcontainers/containersDevelopment environment
Pre-Commit Hookshttps://github.com/pre-commit/pre-commit-hooksAuto-runs lint and format checks on commit

Diary of Challenges

How we got to Vue: The Challenges of React and Svelte

React’s control of the dom was interferring with contenteditable components, especially once I added support for checkboxes. There was most likely an issue with my implementation, but I didn’t want to spend too much time debugging.

Once React became a no-go, I tried using Svelte instead. I confirmed in the Svelte online editor that contenteditable would work with checkboxes, but I quickly got confused on how to use Svelte Kit for creating a simple application.

Since this project was a quick hack, I didn’t want to spend too much time getting setup, so made the ultimate and final switch to Vue as the app’s framework.

Contenteditable

From everything I saw online (Stackoverflow), contenteditable is a headache and difficult to work with. While that was the case when figuring out how to handle custom compoents; I found it equally as challenging to find a simple text editor framework that was well supported, not behind a paywall, and allowed for easy customization.

At the end of this weekend, I’d say that I wouldn’t recommend contenteditable if working on a production-grade high-traffic platform, but for a quick editor it’s highly recommended!!

Django Channels and Token Auth

Django Channels doesn’t seem to support token authentication by default, so I add to create my own auth token middleware for use of Django Channels to authenticate websocket requests. https://github.com/thalida/napkinnotes/blob/ee942bd460c80500b40851985d145863a2ce32dc/api/api/middleware.py

The middleware takes in the token and token_type query paramaters from the websocket request, and directly calls oauth2_provider.contrib.rest_framework.OAuth2Authentication to perform the authtentication.