{"id":17861659,"url":"https://github.com/marcusbuffett/newreads","last_synced_at":"2025-03-20T22:31:02.299Z","repository":{"id":42733805,"uuid":"281498159","full_name":"marcusbuffett/newreads","owner":"marcusbuffett","description":"The code for the newreads site","archived":false,"fork":false,"pushed_at":"2023-01-06T12:42:10.000Z","size":2340,"stargazers_count":9,"open_issues_count":17,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-05-01T13:08:23.763Z","etag":null,"topics":["books","functional-programming","hacktoberfest","halogen","haskell","purescript"],"latest_commit_sha":null,"homepage":"https://nextgreatbook.com","language":"PureScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marcusbuffett.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-21T20:31:19.000Z","updated_at":"2022-10-04T05:35:36.000Z","dependencies_parsed_at":"2023-02-06T02:46:21.382Z","dependency_job_id":null,"html_url":"https://github.com/marcusbuffett/newreads","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcusbuffett%2Fnewreads","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcusbuffett%2Fnewreads/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcusbuffett%2Fnewreads/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcusbuffett%2Fnewreads/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcusbuffett","download_url":"https://codeload.github.com/marcusbuffett/newreads/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244085007,"owners_count":20395523,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["books","functional-programming","hacktoberfest","halogen","haskell","purescript"],"created_at":"2024-10-28T08:46:45.410Z","updated_at":"2025-03-20T22:31:01.894Z","avatar_url":"https://github.com/marcusbuffett.png","language":"PureScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Newreads\n\nNewreads is a site to exchange book recommendations. It lives at [https://nextgreatbook.com](https://nextgreatbook.com) currently.\n\nNewreads is open source, donates all revenue (from affiliate links) to\n[GiveDirectly](https://www.givedirectly.org/), ~~and it's transparent~~ (update:\nI like the open metrics idea and I'll try to make it happen, but the setup got\nscrewed up in the migration to kubernetes, not sure how to make it open now,\nideas welcome).\n\n## Running locally\n\n### Db, traefik, ackee, etc.\n\nTo avoid repeating my configs between dev and prod I've got a python script that\nwill fill jinja templates in [docker_templates](docker_templates) with env\nvariables. So you'll have to export the right env file, run the python script,\nthen run docker-compose, something like this:\n\n```\npip install jinja2\nENV_FILE=.dev.env \u0026\u0026 export $(xargs \u003c $ENV_FILE) \u0026\u0026 python render_templates.py \u0026\u0026 docker-compose up db traefik ackee\n```\n\nThis will start the PostgreSQL db, and traefik for routing. Ackee is optional,\nit's just for analytics.\n\n### Server\n\n```\ncd server\nstack run -- --recreatetables --scrapemockbooks --mockdata --startserver\n```\n\nSomewhat self-explanatory, but this will create the db tables, scrape some books\nfrom goodreads (defined in [MockBooks.hs](./server/app/MockBooks.hs)),\nseed some data, then start the server.\n\nFor future invocations you'll only need to run the server:\n\n```\ncd server\nstack run -- --startserver\n```\n\n### Client\n\n```\ncd frontend\nyarn start\n```\n\nKeep in mind this will open 127.0.0.1:4201, but you'll need to go to\nhttp://web.lvh.me:4200 instead, since that's where traefik is running, which proxies\napi requests to the server.\n\n## Tech stack\n\n- Backend\n  - [Haskell](https://www.haskell.org/)\n  - [Selda](https://selda.link/)\n  - [Scotty](https://hackage.haskell.org/package/scotty)\n  - [Scalpel](https://hackage.haskell.org/package/scalpel)\n- Frontend\n  - [Purescript](https://www.purescript.org/)\n  - [Halogen](https://github.com/purescript-halogen/purescript-halogen)\n- Etc.\n  - [Docker compose](https://docs.docker.com/compose/)\n  - [kubernetes](https://kubernetes.io/)\n  - [Kong Ingress Controller](https://docs.konghq.com/2.1.x/kong-for-kubernetes/)\n  - [Traefik](https://containo.us/traefik/)\n  - [Ackee](https://ackee.electerious.com/)\n\n### Frontend - Purescript\n\nThe frontend is written in PureScript, using the Halogen framework. It's a bit\nof a mess for all the usual reasons a project in a never-before-used language\nis, but feel free to check it out [here](./frontend/src) (or for a\ndigestible component, check out [the recommendation\ncard](./frontend/src/Component/RecommendationCard.purs)). Shout out to\nthe PureScript community for being fucking awesome.\n\n### Backend - Haskell\n\nThe backend is written in Haskell. For DB stuff I'm using Selda (all the models\nlive [in Models.hs](./server/app/Models.hs)). For [the goodreads\nscraping](./server/app/BookUrlsScraping.hs) I use Scalpel, and for [the\nserver](./server/app/Server.hs) I use Scotty. The text search is powered\nby a fork I've made of full-text-search, to get around some performance issues\nwith indexing 100s of thousands of documents.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcusbuffett%2Fnewreads","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcusbuffett%2Fnewreads","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcusbuffett%2Fnewreads/lists"}