https://github.com/thalida/napkinnotes
A digital 'napkin' (just what everyone's wanted). Jot down quick math, list todos, paste notes, etc.
https://github.com/thalida/napkinnotes
calculator devlog django django-channels django-rest-framework notes pwa side-project tasks vue vue3 websocket
Last synced: about 1 month ago
JSON representation
A digital 'napkin' (just what everyone's wanted). Jot down quick math, list todos, paste notes, etc.
- Host: GitHub
- URL: https://github.com/thalida/napkinnotes
- Owner: thalida
- License: agpl-3.0
- Created: 2024-03-23T04:42:29.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-04-02T18:24:30.000Z (about 2 years ago)
- Last Synced: 2025-10-10T08:56:47.801Z (8 months ago)
- Topics: calculator, devlog, django, django-channels, django-rest-framework, notes, pwa, side-project, tasks, vue, vue3, websocket
- Language: TypeScript
- Homepage: https://napkinnotes.app
- Size: 2.07 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Napkin Notes
Napkin Notes is an encrypted, lightweight, note-taking app for quick math, short-term tasks, and temporary notes.
Hacked together by: thalida 🦄 | napkinnotes@thalida.com | thalida.com

## 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/](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
| Feature | Trigger Action |
| ---------------------- | --------------------------- |
| Headings (H1-H4) | Markdown headings syntax (#) |
| Bold | Highlight text and `CTRL+B` |
| Italics | Highlight text and `CTRL+I` |
| Underline | Highlight text and `CTRL+Y` |
| Link | Highlight text and `CTRL+K` |
| Unordered List | Type `* ` (`*` + `SPACE`) |
| Ordered List | Type `1. ` (`1.` + `SPACE`) |
| Interactive Checkboxes | Type `- []` or `- [x]` |
| Interactive Math ✨ | Type `$ ` (`$` + `SPACE`) |
| Code Blocks with Syntax Highlighting | Fence 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 Service | Link | Description |
|-----------------|------|-------------|
| Vue (Vue3) | | Frontend framework |
| Vite PWA | | Adds PWA Support to Vue |
| Vue useWebsockets | https://vueuse.org/core/useWebSocket/ | Vue Websockets Support |
| Tailwind | | Design system and CSS Components |
| Tailwind Components | | Pre-built components from Tailwind; Uses [Headless UI](https://headlessui.com/) and [Heroicons](https://heroicons.com/) |
| Vue Google Login | | Powers "Login with Google" functionality |
| Hero Icons | | |
| Bootstrap Icons Vue | | Vue components for [Bootstrap Icons](https://icons.getbootstrap.com/) |
| Highlight JS | | Code Syntax Highlighting |
### Api
| Tool or Service | Link | Description |
|-----------------|------|-------------|
| Django | https://www.djangoproject.com/ | Backend framework |
| Django Channels | https://channels.readthedocs.io/en/latest/index.html | Django websocket support |
| Django Rest Framework | https://www.django-rest-framework.org/ | RESTFul Django APIs |
| DRF Social Oauth | https://github.com/wagnerdelima/drf-social-oauth2 | Provides support for social login; Uses [Python Social Auth](https://python-social-auth.readthedocs.io/en/latest/) and [Django OAuth2 Toolkit](https://django-oauth-toolkit.readthedocs.io/en/latest/); |
| Python Cryptography | https://github.com/pyca/cryptography | Encryption library used for storing note content |
| DRF Spectactular | https://drf-spectacular.readthedocs.io/en/latest/ | Open API Schema Generator & Viewer |
| Stoplight Elements | https://github.com/stoplightio/elements | Beautiful Open API Schema Docs |
| Django Unfold Admin | https://github.com/unfoldadmin/django-unfold | A better Django Admin Experience |
### Dev Ops
| Tool or Service | Link | Description |
| --------------------- | ------------------------------------------------------------- | ----------------------------------------------- |
| Render | | Deployment and hosting for both the app and api |
| VSCode Dev Containers | | Development environment |
| Pre-Commit Hooks | | Auto-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.