T
TanStack2mo ago
equal-jade

use SPA mode with server functions on another hostname

I’d like to use SPA mode with server functions, but those functions will be hosted on another domain. Is that possible?
29 Replies
adverse-sapphire
adverse-sapphire2mo ago
right now, no. but we could add a config for that i think would not affect dev though
equal-jade
equal-jadeOP2mo ago
Thank you, do you think this makes sense for the community?
adverse-sapphire
adverse-sapphire2mo ago
it's niche for sure. so not a high priority right now. but when we have time we can look into it
fair-rose
fair-rose2mo ago
I need this desperately. Currently the last thing holding be back from switching. There is currently a work around (https://www.youtube.com/watch?v=H84he9ijMfc). This is my exact reason, we deploy with Capacitor
Aaron Saunders
YouTube
I Tried TANSTACK with Capacitor for Mobile and Here's What Happened
TANSTACK + Capacitor FINALLY Working Together, Fullstack Mobile Apps Wanting to get TanStack Start running on mobile with Capacitor? This quick guide shows you the few quick config changes that makes it work—plus a live demo of what fails and what succeeds." Ready to turn your web application into a native mobile app? This in-depth tutoria...
fair-rose
fair-rose2mo ago
It also blocks using Firebase Hosting, instead of Firebase App Hosting
adverse-sapphire
adverse-sapphire2mo ago
20 mins, tldw 🤪 what's the workaround ?
fair-rose
fair-rose2mo ago
Pretty much just manually fetching if it's on Capacitor, and using the regular fetch if it's not Really bad, wouldn't recommend lmfao. I kinda thought I could override it in a Vite build step but I really don't want janky in this project
adverse-sapphire
adverse-sapphire2mo ago
ok let's see if this is maybe rather easy
fair-rose
fair-rose2mo ago
You'd save me a lot of pain right now haha. It really doesn't matter for me in the SSR world, but that with SPA allows us to deploy the server functions to a separate server, run the static site on any device using something like Capactior, and still get every feature that comes with Tanstack which would be awesome
adverse-sapphire
adverse-sapphire2mo ago
this would mean that the build would contain a static url of the domain where the server functions are hosted
fair-rose
fair-rose2mo ago
Yes, correct
judicial-coral
judicial-coral2mo ago
I'm going to see what I can do to create a perfect hybrid setup for Capacitor + Tauri + TanStack Start, deploying web + server endpoints with Better Auth on Netlify / Cloudflare, since I'm officially leaving Next.js & Vercel now. I'll share my findings soon
fair-rose
fair-rose2mo ago
Honestly, for my jobs use case, I can use Firebase Cloud Functions as an alternative, but this gets rid the possibility of using: - Tanstack server functions - Nitro (You cannot use Regular Firebase Hosting) - Firebase App Hosting Capacitor works fine, haven't tried Tauri. Still, for future projects, I would love to use Tanstack in a more fullstack way.
judicial-coral
judicial-coral2mo ago
With Next.js variant I had theoutput: "export" option get set when you ran pnpm export script from package.json. During exports, it would skip server API routes and just give you the static build into the out folder for Capacitor. For normal builds, I would still deploy it to serverless hosting and serve those API routes. And then anything that interacts with those API routes from the front end would use a BASE_URL variable that contains the production domain when process.env.EXPORT === "true".
I think I should be able to come up with something similar here. I'm not particularly sure about TanStack "server functions" and how those are different from API routes This was a lot easier than I thought, I just enabled spa mode and renamed _shell.html to index.html and pointed webDir to dist/client For server functions I think they are prefixed with _serverFunction/ ? or something
fair-rose
fair-rose2mo ago
Hiya, yes. That’s correct, the issue for me at least is server functions expect the client and server are running on the same device, but when using something like Capacitor, that doesn’t quite work serverFn but that is changeable in the configuration
judicial-coral
judicial-coral2mo ago
Right so it tries to fetch localhost/_serverFunction? What you could do is over-ride window.fetch with a custom fetcher that checks for serverFn in the URL and pre-pends your prod domain
fair-rose
fair-rose2mo ago
Yeah, I’ve also just explored rewriting it in a build step but at the end of the day, it’s only a RC, and I’d rather not rely on hacky workarounds at least not in production
judicial-coral
judicial-coral2mo ago
Is there a way to force TanStack Start to output index.html instead of _shell.html ?
fair-rose
fair-rose2mo ago
Yes, in your vite configuration, let me find the option It’s in the spa -> prerender -> outputPath
judicial-coral
judicial-coral2mo ago
Thanks! As far as overriding window.fetch, it's not too bad I can try to come up with a very simple example
fair-rose
fair-rose2mo ago
Of course! Sounds good. I'm interested to see
judicial-coral
judicial-coral2mo ago
@DaddyImPregnant Here is the fix for server functions in exports: override-fetch.ts
import { baseURL, isExport } from "./utils"

let ogFetch: typeof fetch

export const overrideFetch = () => {
if (!isExport) return
if (typeof window === "undefined") return
if (!ogFetch) ogFetch = window.fetch

window.fetch = (input, init) => {
const urlString = input.toString()

if (urlString.startsWith("/_serverFn")) {
input = `${baseURL}${urlString}`
}

return ogFetch(input, init)
}
}
import { baseURL, isExport } from "./utils"

let ogFetch: typeof fetch

export const overrideFetch = () => {
if (!isExport) return
if (typeof window === "undefined") return
if (!ogFetch) ogFetch = window.fetch

window.fetch = (input, init) => {
const urlString = input.toString()

if (urlString.startsWith("/_serverFn")) {
input = `${baseURL}${urlString}`
}

return ogFetch(input, init)
}
}
utils.ts
import { Capacitor } from "@capacitor/core"

export const isExport = Capacitor.isNativePlatform()

export const baseURL = isExport
? "https://tanstack-start-hybrid.daveycodez-a93.workers.dev"
: ""
import { Capacitor } from "@capacitor/core"

export const isExport = Capacitor.isNativePlatform()

export const baseURL = isExport
? "https://tanstack-start-hybrid.daveycodez-a93.workers.dev"
: ""
Then in your __root.tsx you just call overrideFetch() at the top level. To deal with CORS you just use the Capacitor HTTP Plugin in your capacitor.config.ts
plugins: {
CapacitorHttp: {
enabled: true
}
}
plugins: {
CapacitorHttp: {
enabled: true
}
}
fair-rose
fair-rose2mo ago
Oh awesome! Great work! Will definitely play around with it
judicial-coral
judicial-coral2mo ago
__root.tsx
import { TanStackDevtools } from "@tanstack/react-devtools"
import { createRootRoute, HeadContent, Scripts } from "@tanstack/react-router"
import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"

import { overrideFetch } from "@/lib/override-fetch"
import appCss from "../styles.css?url"

overrideFetch()
// export const Route...
import { TanStackDevtools } from "@tanstack/react-devtools"
import { createRootRoute, HeadContent, Scripts } from "@tanstack/react-router"
import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"

import { overrideFetch } from "@/lib/override-fetch"
import appCss from "../styles.css?url"

overrideFetch()
// export const Route...
Yea I just tested it, works great You could probably use this with /api as well as /_serverFn in the override to avoid manually putting baseURL everywhere you use fetches
fair-rose
fair-rose2mo ago
Awesome, will definitely play around with it! Thank you!
judicial-coral
judicial-coral2mo ago
GitHub
GitHub - daveycodez/tanstack-start-hybrid: Hybrid TanStack Start + ...
Hybrid TanStack Start + Capacitor + Tauri Application - daveycodez/tanstack-start-hybrid
judicial-coral
judicial-coral2mo ago
Alright I just updated that Repo with Tauri fully set up as well! Works perfectly, even with server functions on both dev and production for macOS
rare-sapphire
rare-sapphire4w ago
Why the spa not working with me it is only white page .I same config as this hybrid repo
judicial-coral
judicial-coral4w ago
What environment exactly are you seeing this white page? dev? hosted? Tauri? Capacitor?

Did you find this page helpful?