Trying to get back into writing music this year https://1679326685939.s3.us-east-1.amazonaws.com/1.m4a
For the web client, we're not actually sending your private key, because it's not safe to persist in the browser (without something like a Chrome extension). We're sharing the auth token via the same end-to-end encryption that we use for direct casts.
The biggest perf difference that you'd notice, I think, is for FMP, but a CSR app can narrow that gap with code splitting, caching, etc.
If done very well, I think SSR would be marginally more performant than CSR, but it's nowhere near as clear a winner as it's made out to be, and the added complexity is often not worth it IMO.
I think SSR tends to be more performant for FMP at the beginning of the session (notably with a delay before JS becomes interactive), but assuming you are hydrating the app, I think you end up sending more data over the wire and may get into waterfall situations for subsequent page loads.
(In addition to things like the server-side environment not having access to the same runtime variables as the client)
First I've heard of Deno Fresh! I think any SSR solution comes with the same fundamental problem, which is that for apps of sufficient complexity, you will probably want to enable interactions (e.g. liking a cast) that mutate the state without refreshing the whole page. That's where the complexity comes in.
If you need to do something similar yourself, I would recommend hosting a simple express app that responds with common OG meta tags that inject the user agent in the description/title, so you can see how things render on various sites and also what user agent they are hitting your site with.
It is not at all standardized, and figuring out the user agents for each site was rather cumbersome. We are surely missing many in our allowlist, but I think we have most of the big ones at this point. I don't actually know what the full regex is at the point, but maybe @sds can share.
The web app itself is just CRA. I would have loved to use something like Vite, but I couldn't get a basic app running in the context of our monorepo with the dependencies we already have / will need. Hopefully in the future we can migrate to something faster + more modern without needing to touch any client code
that 1) the main web app isn't burdened with additional complexity relating to SSR, 2) almost all incoming requests just require us to serve static assets, and 3) a separation of concerns between OG/SEO logic for robots and an actual web app for humans
For example, a request for @dwr's profile from TwitterBot will go to https://ssr.warpcast.com/dwr, which will server-side render OG meta tags and some very basic HTML for SEO. All non-bot traffic will just get served https://warpcast.com/dwr. This approach adds some maintenance burden, but the benefits are
Ultimately, we ended up implementing a simple Next server (opting for the framework just for convenience of having out-of-the-box support for JSX) to live in parallel with the web app, which is all just client-side rendering. We configure Cloudflare to look at the incoming user agent, and route to the appropriate site
A CSR solution was simpler and I would argue potentially more performant, but we still needed to solve the OG problem. We considered outsourcing the server-side rendering to someone like prerender.io, but we didn't love the idea of relying on a third-party, particularly when our product reqs weren't that demanding.
Knowing that we would want OpenGraph support and eventually SEO, we seriously considered SSR solutions like Next and Remix. Ultimately, though, we felt that they introduced a fair amount of complexity with relatively little upside – the biggest benefit being "free" server-side rendering for OG and SEO.
but I think the pattern of parsing the text within the mobile app, then rendering with native components is probably the move. As far as parsing/tokenizing, I would consider doing it yourself from scratch, but there are also some libs out there to assist.
For rich text, we use a library called linkify-it, which assists with the tokenization, then we we join those tokens, wrapping segments with native components (e.g. View, Text, etc.). I'm not a big fan of the linkify-it library, because I think the interface is awkward and unintuitive,
but at a minimum it will add some awkwardness to your code, since you'll have native Javascript + Javascript that gets injected into the web view, which will either mean you'll give up type safety, auto-complete, etc. or you'll need to setup a whole separate build process to compile the webview Javascript.
I haven't built it out to verify, but I would expect rendering several webviews (e.g. one for each cast in a feed) would be pretty expensive from a CPU/memory perspective, since you're effectively spinning up a dozen little mobile Safari browsers. That would be less of a problem if you're only using it for one view,
We avoid sharing any UI-related code, for the reason you alluded to but also just because mobile + desktop interfaces tend to be different enough that it doesn't always make sense to share even if there weren't the platform differences to deal with.
We only share code that's runtime agnostic – an API client, stateful hooks to wrap API calls + manage caching, an abstract cryptography API (the actual implementations for RN vs desktop/web live in separate packages), Typescript + ESLint configs.
It's possible there's a better way. IMO having all the apps live in a monorepo where they can easily share code + you can get immediate feedback on breaking changes before they're merged is worth the trouble. But wrt RN, there be dragons