SEO for SPA-like apps

Hi there.

We have a Next.JS web app that is being served with service stack (in a similar way as the vue service stack template). One of our pages is a detail view for some of our content and we set it up to allow for the link to be publicly shared through social media.

However, due to the nature of the web app being a SPA there is no way for us to set meta tags (open graph) through server side rendering. Is there any way you recommend to solve this?

One solution that I thought might work would be to check the user agent on the page request to see if it is a bot and return a razor templated page that just has the meta tags.

Here is how the link card looks on linkedin, for example:

Side Note: For some reason it shows the title as being 404, but when i curl the url the title tag has “Video Detail”. Is ServiceStack checking user agent already and auto redirecting to a 404 page?


  • Is there any way you recommend to solve this?
  • Does ServiceStack have any built in solutions for this? Bot detection?
  • Should this be done with a request filter or routing?


SPA’s aren’t great for SEO, so you’d typically split your site where you want SEO to use server side rendering vs SPA for your authenticated dynamic content.

For vue-spa you can change the global HTML meta tags for every page in /public/index.html which as SharpPagesFeature is enabled will let you dynamically render additional HTML based on UserAgent, e.g:

{{if Request.UserAgent.contains("Googlebot") }}
<!-- HTML markup to render -->

Otherwise to dynamically change what HTML content is rendered for a page I’d disable using the built-in fallback route:

Plugins.Add(new SharpPagesFeature {
//    EnableSpaFallback = true

So you can use your explicit Fallback Route, e.g:

[FallbackRoute("/{PathInfo*}", Matches="AcceptsHtml")]
public class FallbackForClientRoutes
    public string PathInfo { get; set; }

public class MyServices : Service
    //Return index.html for unmatched requests so routing is handled on client
    public object Any(FallbackForClientRoutes request) => Request.GetPageResult("/");

There you can inspect Request.UserAgent to change what content is rendered, some html response examples from docs:

//Return static HTML file
return new HttpResult(VirtualFileSources.GetFile("index.html"));

//Return HTML String
return new HttpResult(VirtualFileSources.GetFile("index.html").ReadAllText());

//Return ServiceStack.Razor View
return new HttpResult(request)
    View = "/default.cshtml"

Personally I’d prefer to use #Script since it’s already registered and is a lot more flexible in being able to generate HTML in memory as seen with the HTML Email Example. But you can return a ServiceStack.Razor View if preferred.

We don’t maintain any bot UserAgent detection in ServiceStack.dll.

You’ll need to look at the HTTP Request/Response headers to work out what’s happening with your 404 page request.

1 Like