Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Visit the app at myreviews.my

Or read the instructions below to host your own.

I have a need for this app as I visit and order from many places and want to keep track of my personal reviews on them, as I kept ordering from the same bad places that look good on paper.

At some point, Google Keep becomes unmanageable, and it's also not searchable. GSheets would be better, but an app is best.

Development

Tech stack

I mainly chose this stack as I want to learn them. They are not used in my daily job.

Backend:

  • Golang with standard library only (no framework): I will repeat. No framework by default.
  • slogs for logging. lumberjack for log file rotation.
    • Sever-Send Events to tail the log file
  • No ORM. Use raw SQLs and sqlc for typed queries: This is the best db experience I have ecome across.
  • Goose to manage migrations: It's alright.
  • Elasticsearch: Bad experience with the Typed API. Let's just use the Untyped API.
    • Example: The bulk operations just don't work with the Typed API.

Frontend:

  • React and Typescript
  • Vite for building
  • Zustand for state management: I like it
  • Mantine UI: quite good, can use again
  • Tailwind: I do get some conflicts with Mantine as Mantine is not Tailwind-native, but no major blocker

Launch the app locally

Backend:

  • Start postgres server
  • Start elasticsearch server
    • On WSL:
    • On Native Arch:
      • sudo pacman -S elasticsearch
      • sudo /usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactive
      • Use the password in .envrc
      • sudo systemctl enable elasticsearch
      • sudo systemctl start elasticsearch
      • Verify by visiting localhost:9200
  • cd server
  • direnv allow .
  • createdb myreviews
  • goose up
  • air

Frontend:

  • cd web
  • direnv allow .
  • npm run dev or npx vite

To add a new query

  • Write the SQL in query.sql
  • sqlc generate: The code is added to models/

Deployment

Build for production

  • make build-be
  • make build-fe

Retrospectives

  • I wasn't able to a inject a more extensive use of channels and concurrency patterns: Channels were used, but quite limitedly.
  • sqlc is great and I want to use it again, but I can't figure out a way to force it to always use int. At first, I tried to live with int32, but I hated the fact that I have to remember something is int32 or intt. In the end, I forced everything to int, but even with the current config, it will generate Postgres's integer[] as int32[] and I had to manually make the change after sqlc generate. This may be improved in a future version.
  • I wasn't sure at first whether the i18n of backend error messages should be done on the backend or on the frontend, but by now I have a preference: doing it all on the frontend will allow the frontend to check the error message more easily (e.g. if (error?.message?.toLowerCase()?.includes("access denied")). However, the tradeoff goes the other way if there are multiple frontends.

About

Web app to keep track of your own personal reviews on everything in Golang and Typescript

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages