Published on

Go Keep - Clone of Google Keep

Authors

Go Keep

I was going through John Crickett's Coding Challenges and Build Your Own Google Keep caught my eye. I thought why not build a clone's of Google's product with a language designed by their own developers.

the killer functionality of Google Keep [is] being a simple to use distributed note taking tool with a mobile and web UI.

I decided to build the backend service in Go and left out the frontend (for some future date?).

API Design

The entire design hinges on Creation, Read, Updation and Deletion (CRUD) of a Note (reource entity).

For authentication, there are four more endpoints for login, callback, logout, and fetch user details.

The new release of net/http has eliminiated the use of any router and URL matcher and I have stuck to using the standard library.

Authentication

Without authentication basically anyone can read your notes. We need to introduce session management that link authentication and authorization (access control).

HTTP is a stateless protocol, where each request and response pair is independent of other web interactions. The session ID or token adds authentication credentials to the user HTTP traffic and the appropriate access controls enforced by the web application.

I could have rolled out my own implementation of authentication. One good library for it is Goth. I thought of exploring a pre-built identity solution like KeyCloak, Firebase etc. I chose Auth0.

Auth0 documentation recommends the use of gin sessions. I wanted to write my own session management code. To draw inspiration, I adopted code from Acebond/session. It is a fast-in-memory backend session storage middleware. I spent significant time here; going through documentation and coming up with a working solution.

Cookies store the login information on the client's device which is validated at backend by the session middleware.

Database design

I usually use MariaDB (MySQL) at work, so to shake things up I tried out Postgres.

create table customer
(
    id   uuid    not null
        constraint user_pkey
            primary key,
    name varchar not null
        constraint customer_pk
            unique
);
create table note
(
    id         uuid                                not null
        primary key,
    title      text                                not null,
    content    text                                not null,
    updated_at timestamp default CURRENT_TIMESTAMP not null,
    "userId"   uuid                                not null
);

The uuid generation is handled at the server. I preferred using uuidv7 because it makes time based queries more efficient and intuitive.

Tech Stack

Go and its standard libraries, Postgres, Auth0