Skip to content

marcusbuffett/newreads

Repository files navigation

Newreads

Newreads is a site to exchange book recommendations. It lives at https://nextgreatbook.com currently.

Newreads is open source, donates all revenue (from affiliate links) to GiveDirectly, and it's transparent (update: I like the open metrics idea and I'll try to make it happen, but the setup got screwed up in the migration to kubernetes, not sure how to make it open now, ideas welcome).

Running locally

Db, traefik, ackee, etc.

To avoid repeating my configs between dev and prod I've got a python script that will fill jinja templates in docker_templates with env variables. So you'll have to export the right env file, run the python script, then run docker-compose, something like this:

pip install jinja2
ENV_FILE=.dev.env && export $(xargs < $ENV_FILE) && python render_templates.py && docker-compose up db traefik ackee

This will start the PostgreSQL db, and traefik for routing. Ackee is optional, it's just for analytics.

Server

cd server
stack run -- --recreatetables --scrapemockbooks --mockdata --startserver

Somewhat self-explanatory, but this will create the db tables, scrape some books from goodreads (defined in MockBooks.hs), seed some data, then start the server.

For future invocations you'll only need to run the server:

cd server
stack run -- --startserver

Client

cd frontend
yarn start

Keep in mind this will open 127.0.0.1:4201, but you'll need to go to http://web.lvh.me:4200 instead, since that's where traefik is running, which proxies api requests to the server.

Tech stack

Frontend - Purescript

The frontend is written in PureScript, using the Halogen framework. It's a bit of a mess for all the usual reasons a project in a never-before-used language is, but feel free to check it out here (or for a digestible component, check out the recommendation card). Shout out to the PureScript community for being fucking awesome.

Backend - Haskell

The backend is written in Haskell. For DB stuff I'm using Selda (all the models live in Models.hs). For the goodreads scraping I use Scalpel, and for the server I use Scotty. The text search is powered by a fork I've made of full-text-search, to get around some performance issues with indexing 100s of thousands of documents.