Hammock moves your favorite newsletters outside of your understandably cluttered inbox, letting you focus on and learn from the content you love in a distraction-free reading space.
A user is a person; someone who uses the app.
A subscription is a recurring newsletter from a specific email address.
A message is an email from a recurring newsletter (extends Subscription
).
Included below are some high-level descriptions of how Hammock is implemented. The purpose of this writing is not so much to act as documentation but rather to encourage better README-driven development.
Our Gmail sync is composed of various methods to ensure that our Supabase-managed PostgreSQL database is always up-to-date with our users' Gmail inboxes:
- When the user first signs up, they call our
/api/sync
endpoint which starts a full sync using Gmail'smessages.list
API endpoint. This endpoint syncs 10 messages and then redirects (using thenextPageToken
) to/api/sync
recursively to sync the next 10 messages and so on and so forth. We save the current sync cursor (thenextPageToken
returned by the lastmessages.list
call) in our database so subsequent calls to/api/sync
start right where we left off. - When the user signs up, we also setup a Google Pub/Sub subscription
using Gmail's
users.watch
API endpoint. This push subscription then calls our/api/push
endpoint which uses Gmail'shistory.list
API to sync newly received messages as they come in.
Hammock aims to use the most cutting-edge, performant, and production-ready solutions available. Included below is our current selection and the reasoning behind it, but we're always open to improvements!
- Typescript - As our language of choice (mostly for static typing, stronger linting capabilities, etc). Typescript is also well supported by Next.js and React.
- CSS-in-JS - Instead of packaging styles separately from our React components, all styles are included alongside them in the same files. This allows for better code-splitting, etc.
- React - As our front-end framework.
- Next.js - To easily support SSR and other performance PWA features.
- SWR - Used to manage global state. SWR fetches data from our back-end, stores it in a global cache, and allows local mutations of that cache (with or without automatic revalidation).
next-auth
- Manages authentication with JWT session cookies.
- Yarn - To manage dependencies much faster than NPM (and for better community support, advanced features, etc). This project uses Yarn Berry (v2) and takes advantage of its new plug-n-play functionality.
- ESLint - For code linting to avoid common mistakes and to enforce styling. Follow these instructions to install it in the text editor of your choice (so you won't have to wait until our pre-commit hooks fail to update your code).
- Cypress for integration, UI, and some unit tests. Cypress is like Selenium; but built from the ground-up with the developer in mind. Cypress runs alongside your code in the browser, enabling DOM snapshots, time travel, and overall faster test runs.
- Supabase - For their managed PostgreSQL relational database.
I have very precise rules over how Git commit messages in this repository must be formatted. This format leads to easier to read commit history.
Please refer to the following documentation for more info:
Commit messages that do not adhere to the following commit style will not be
merged into develop
:
<type>(<scope>): <short summary>
│ │ │
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
│ │
│ └─⫸ Commit Scope: The page, API route, or component modified.
│
└─⫸ Commit Type: ci|docs|feat|fix|perf|refactor|test|deps|chore
The <type>
and <summary>
fields are mandatory, the (<scope>)
field is
optional.
Must be one of the following:
- ci: Changes to our CI configuration files and scripts.
- docs: Documentation only changes.
- feat: A new feature.
- fix: A bug fix.
- perf: A code change that improves performance.
- refactor: A code change that neither fixes a bug nor adds a feature.
- test: Adding missing tests or correcting existing tests.
- deps: A change in dependencies.
- chore: A code change in utility scripts, build configurations, etc.
This repository follows the standard git-flow workflow with a couple of important exceptions:
develop
should always be stable and ready for release.develop
just has not yet been released (e.g. for marketing purposes, we release changes in large batches).master
represents the current production state of the app.