C# Jamstack Project Templates

ServiceStack's Jamstack templates encapsulates the latest technologies at the forefront of modern web development to deliver both a great developer experience and performant end-user UX.

Jamstack (JavaScript, APIs, and Markup) is a modern architecture pattern to build fast, secure and easy to scale web applications where pre-rendering content, enhancing with JavaScript and leveraging CDN static hosting results in a highly productive, flexible and performant system that takes advantage of CDN edge caches to deliver greater performance & efficiency at lower cost.

Jamstack Benefits

It's become the preferred architecture for modern performant web apps with benefits extending beyond performance to improved:

  • Security from a reduced attack surface from hosting read-only static resources and requiring fewer App Servers
  • Scale with non-essential load removed from App Servers to CDN's architecture capable of incredible scale & load capacity
  • Maintainability resulting from reduced hosting complexity and the clean decoupling of UI and server logic
  • Portability with your static UI assets being easily capable from being deployed and generically hosted from any CDN or web server
  • Developer Experience with major JavaScript Frameworks embracing Jamstack in their dev model, libraries & tooling

Ultimately, it's hosting your App's pre-rendered static UI assets on Content Delivery Network (CDN) edge caches close to users locations that's primarily responsible for its lightning performance.

$0.40 /month

Other by-products of generating pre-computed CDN hostable assets, is interchangeable cost-effective hosting and great SEO - characteristics our Jamstack Demos take advantage of with free UI hosting on GitHub Pages CDN leaving their only cost to host its .NET 6 API back-ends, deployed with SSH in Docker compose containers to a vanilla Digital Ocean droplet costing only $0.40 /month each.

These templates represent the best-in class experiences for their respective React, Vue & Blazor WASM ecosystems each, packed with features & examples common in many websites including Integrated Auth, rich Markdown content as well as TODOs MVC and CRUD examples with built-in contextual validation binding. As such they're now recommended over our existing SPA and C# MVC Templates.

We've put together a quick check list to help decide which templates we'd recommend:

Project Recommendation
Next.js If you prefer React
Vue SSG If you prefer Vue and SEO is important
Blazor Tailwind If you prefer a full C# Stack or are developing Line of Business (LOB) Apps
Vue SPA If you prefer Vue and happy to trade SEO benefits of SSG for a simpler template

Still not sure? familiarize yourself with their respective dev models by comparing their functionality equivalent TODOs MVC Examples:

TODOs MVC

All projects utilize the same back-end ServiceStack Services with TODOs MVC implemented in TodosServices.cs.

As Bookings CRUD is an AutoQuery CRUD API, it defines all its functionality in its declarative Bookings.cs DTOs and serves as a good example for the minimal dev model effort required to implement a typical Authenticated CRUD UI in each framework:

Bookings CRUD

Once you know the framework you wish to use, create a new App using your preferred Project Name below:

Download new C# Jamstack Project Template

INFO

An updated list of available Jamstack project templates is also at https://jamstacks.net (built with Razor SSG)

Pre-configured Jamstack App Deployments

All project templates supports CDN hostable UI assets and include the necessary GitHub Actions that takes care of building and SSH deploying a Docker compose production build of your App to any Linux Host with just a few GitHub Action Secrets in your GitHub repo.

The optional DEPLOY_CDN secret lets you control whether to deploy your App's static /wwwroot assets to your GitHub Pages CDN by specifying the custom domain to use and is what all JamStack Live demos used to deploy a copy of their UIs to GitHub Pages CDN:

Project Source GitHub Pages CDN Digital Ocean Docker .NET API
nextjs nextjs.jamstacks.net nextjs-api.jamstacks.net
vue-ssg vue-ssg.jamstacks.net vue-ssg-api.jamstacks.net
blazor blazor.web-templates.io blazor.web-templates.io
vue-spa vue-spa.jamstacks.net vue-spa-api.jamstacks.net
blazor-wasm blazor-wasm.web-templates.io blazor-wasm.web-templates.io

Blazor WebAssembly

The Blazor WebAssembly (WASM) template offers a pure end-to-end integrated C# solution to building a high performance web application with Blazor and ServiceStack. Due to the integrated dev model we've been able to achieve in Blazor it's become our preferred technology to use to develop Line of Business Apps since it's the only C# Razor solution adopting our preferred API First Development model with Web UIs reusing the same well-defined APIs as Mobile and Desktop Apps.

Great Perceived Performance and SEO

Typically the large download sizes & slow initial load times of Blazor WASM Apps would make it a poor choice for Internet hosted sites. However, our Blazor WASM template has largely mitigated this with easily maintainable built-in pre-rendering techniques to make every page appear to load quickly, including instant loading of its Markdown Pages courtesy of the GitHub Actions publish task generating & deploying pre-rendered content pages.

You can see the results of this in its live demo when loading the home page, which only has a slight delay:

blazor-wasm.web-templates.io

Learn more

To find out more watch its YouTube overview and visit the Blazor WASM docs.

Razor SSG

The razor-ssg ServiceStack template leverages the power of .NET Razor to provide seamless static site generation (SSG) capabilities. It's perfect for building content-rich applications like product websites, blogs, portfolios, and more.

This template streamlines the development process while offering versatility in customizing and extending your project. With GitHub Codespaces integration, you can develop, test, and manage your application all within your browser, eliminating the need for a dedicated development environment and expediting your workflow.

Next.js

For those preferring working with React, there's a clear choice in Nextjs.org - currently the flagship & most popular Jamstack framework backed by the folks over at Vercel, where it enjoys deep engineering talent committed to maintaining and continually improving it, so you can be confident in the longevity of the technology and the React framework maintained by Meta (Facebook).

Designed as an SSG framework from the start, its pre-defined patterns include static generation and UX focused functionality built-in.

Stale While Revalidate

Its SWR Data Fetching React Hooks library is one innovative example utilizing the popular stale-while-revalidate UX pattern to help developers balance between immediacy — loading cached content right away — and freshness — ensuring updates to the cached content are used in the future.

To take advantage of this, the nextjs template includes a swrClient that provides a typed wrapper for making typed SWR API Requests with ServiceStack's generic JsonServiceClient:

import { swrClient } from "../lib/gateway"
import { Hello } from "../lib/dtos"

const HelloApi = ({ name }) => {
  const {data, error} = swrClient.get(() => 
    new Hello({ name }))
  if (error) return <div>{error.message}</div>
  return <div>{data?data.result:'loading...'}</div>
}

This reactively sets up the UI to handle multiple states:

  • loading - displays loading... message whilst API request is in transit
  • data - when completed, populated with a HelloResponse and displayed
  • error - when failed, populated with ResponseStatus and displayed

The primary UX benefits are realized when re-making an existing request in which a locally-cached stale version is immediately returned and displayed whilst a new API Request is made behind the scenes, updating the UI if the fresh response was modified.

Vite

Despite Vercel's full-time resources, Next.js is still reliant on the Webpack ecosystem, who although have done a formidable job managing complex tooling requirements for npm projects over a number of years, has since lost the Developer Experience (DX) crown to vitejs.dev

Vite is being built for speed in the modern era and takes advantage of modern browser features like native ES modules support to remove bundling entirely during development and adopts performance leading technologies like esbuild to pre-bundle dependencies and transpile TypeScript which is able to do 20-30x faster than TypeScript's own tsc compiler.

Ultimately its architectural choices allows Vite to deliver Lightning Fast Hot Module Reload (HMR) to remain at the developer-experience forefront of modern web development serving a growing ecosystem of frameworks with a rich typed suite of Universal Plugins.

Vue SSG or SPA

Both Vue & Vite being led by Evan You, which ensures both have stellar integration and delivers a well-supported & productive development experience making it the clear choice for any new Vue project.

Both vue-ssg.jamstacks.net and vue-vite.jamstacks.net utilizing the same high-end Vue3, TypeScript and Tailwind components means their included pages like TODOs MVC, Bookings and Sign In contain identical source code, the choice on which to use effectively becomes if you need advanced features like Static Site Generation (SSG) and Dark Mode or would otherwise prefer to start with a simpler template.

Features list comparison

  • vue-ssg.jamstacks.net/features
  • vue-vite.jamstacks.net/features

Stale-while-revalidate in Vue3

Just like Next.js's Stale While Revalidate, both Vue templates includes a swrClient providing a typed wrapper around SWVR Vue3 composition library around making typed SWR API Requests using ServiceStack’s typed JsonServiceClient, e.g:

<template>
  <div v-if="error">{‎{ error.message }‎}</div>
  <div v-else>{‎{data ? data.result :'loading...'}‎}</div>
</template>

<script setup lang="ts">
import { Hello } from "@/dtos"
import { swrClient } from "@/api"

const props = defineProps<{ name: string }>()

const { data, error } = swrClient.get(() => 
    new Hello({ name: props.name }))
</script>

Where it yields the same optimal UX with cached API responses rendered instantly before later updating itself if modified.

Vue SSG

React & Next.js are primarily corporate-led efforts whilst the Vue ecosystem is largely community led, with one of Vue's lieutenants Anthony Fu being the primary developer behind many of the developer-experience focused features adopted in his vite-ssg project. Most of these features are designed to reduce developer effort by auto registering routes and components by convention which effectively gives it Nuxt like productivity by utilizing hand-picked quality dependencies without needing to be reliant on the slow development pace of a heavy framework like Nuxt.

Anthony's own opinionated Vite Starter Template - Vitesse serves as a great resource for an experienced insight into a curated list of Vue & Vite packages offering the nicest developer experience, although Vue SSG will be more conservative and adopt more well-known technologies like tailwindcss in favor of Windi CSS.

Otherwise, it's still jam-packed full of features for modern Web Apps, including built-in Dark Mode support:

Vue Vite

Don't need SSG or Dark mode? Try the simpler SPA template instead:

/api route

Each Jamstack templates are configured to the /api predefined route for JSON APIs:

/api/{Request}

This simple and popular convention makes it easy to remember the route new APIs are immediately available on & also pairs nicely with:

/ui/{Request}

i.e. An easy to remember route for API Explorer's Auto Form UI, together we expect both to yield greater utility out-of-the-box in ServiceStack Apps.

Benefits in Jamstack Apps

The /api route is particularly useful in Jamstack Apps as the 2 ways to call back-end APIs from decoupled UIs hosted on CDNs is to make CORS requests which doesn't send pre-flight CORS requests for Simple Browser requests. As such, we can improve the latency of GET and POST API Requests by configuring our JsonServiceClient to use /api and to not send the Content-Type: application/json HTTP Header which isn't necessary for /api who always expects and returns JSON:

Configuring in TypeScript

import { JsonServiceClient } from "@servicestack/client"

const client = new JsonServiceClient(baseUrl)

It also benefits the alternative method to CORS in only needing to define a single reverse proxy rule on the CDN host to proxy all API requests to downstream back-end servers.