iresharma/reach.md

live

Reach

Started as a SaaS. Became a lifestyle. The GitHub org chart is the confession: reach-io-remix, reachv2, reach-auth-proxy, reach-page-server, reach-page-analytics, Reach-file-server, reach-kanban-service, reach-k8s, a Bun starter script so he could boot the whole circus. He said he wanted to learn error handling. He learned gRPC, Glacier, and how many databases a calendar app can acquire.

Reach is a work desk for content-heavy teams: issue tracking, files and versions, review, calendar, mail, Shopify, analytics, and a Linktree-shaped brand page. Version one was a Remix monolith with loaders full of backend. Version two is a Remix SSR talking to a Go auth proxy that fans out over gRPC to Go and Python services, Postgres, Redis, Cloudflare R2 with a Kafka relay into Glacier, and a Next.js ISR farm for the public pages.

Why the monolith had to go

The first app put API surface in Remix loaders, actions, and handler routes. No TypeScript. Prisma on MongoDB. It taught error handling. It did not teach a clean boundary, and it did not perform. The rewrite keeps Remix as the SSR shell and moves authority to an auth proxy that is the only thing on the internet.

I will still have a remix SSR that talks to RESTful API which acts as a auth proxy, this auth proxy then delegates traffic to all the other services via gRPC. … The go auth proxy on look is giving me extremely good performance. On my local setup with postgres and redis cache the auth proxy responds with sub millisecond responses.
WatchIreshStruggle · Remix to microservices

ROP as a stack, not a slogan

The later architecture post is explicit about the three goals — resiliency, observability, performance — and about the tax. Microservices give feature isolation, independent scale, and mixed runtimes. They also scatter logs and add network failure modes. The proxy exists so browsers never speak gRPC, so caching has one throat to choke, and so only one service is exposed. Protobufs and HTTP/2 are the inter-service bet; REST is the browser bet.

Browser support for gRPC isn't great. Utilizing a proxy becomes particularly valuable when dealing with microservices that communicate using gRPC and Protobufs. … gRPC provides strong typing through Protobuf's schema definition.
WatchIreshStruggle · Learning ROP
  • Frontend: Remix, shadcn/ui, Tailwind — reachv2 describes real-time collaboration, tasks, roles, chat, an analytics dashboard.
  • Auth proxy: Go, Redis sessions, protoc-generated clients for kanban, page, and storage. Postman collection is the public contract.
  • Files: Flask talking to Cloudflare R2, with a Kafka relay so objects also land in Glacier. Two vendors on purpose.
  • Brand pages: Next 13 App Router, generateStaticParams from Mongo at build, generateMetadata from the page template, ISR. 'A URL shortener which instead of redirecting you to a link, shows you a page with a multitude of links.'
  • Analytics: Flask ingest, Mongo aggregations. Views and clicks are events. Uniques are IP plus user-agent, which also feeds geo. The blog says a queue would be correct at scale; they shipped the simple path first.
  • Orchestration: reach-k8s, plus a Bun script that starts every local service because twelve terminals is not a personality.
A simple file server for handling files in Reach, also a relay for kafka to support data duplication into glacier.
github.com/iresharma/Reach-file-server
I create a Next 13 app with ISR. Now next allows me to use server components and things like generateStaticParams and generateMetaData. So during build time I look up my database for existing pages and generate params based on route.
WatchIreshStruggle · Linktree on Next 13