New Vue SPA Template

New Vue SPA Template Background
9 min read

With ServiceStack now fully integrated with .NET 8, our focus has shifted from providing platform-agnostic solutions that supports all ServiceStack's .NET Framework and .NET hosts to building on the new capabilities of .NET 8 by enhancing ASP .NET Core's built-in features and templates with ServiceStack's high-productivity features.

ServiceStack Vue SPA Template

The latest Vue SPA template is a good example of this, building on and enhancing the built-in ASP.NET Core Vue SPA template with many high-productivity features.

Vite Vue SPA Template

Explore the high productivity features in the new ServiceStack Vue SPA template

Live Demo

ASP.NET Core Vue SPA Template

The Vue and ASP.NET Core template provides a seamless starting solution which runs both the .NET API backend and Vite Vue frontend during development.

It's a modern template capturing the best Vue has to offer, configured with Vite's fast HMR (Hot Module Reload) and TypeScript support - it allows App's to be developed with Vue's typed Single File Components enabling both a productive development experience and an optimal high-performance production build at runtime.

Minimal API integration

Whilst a great starting point, it's still only a basic template configured with a bare-bones Vue Vite App that's modified to show an example of calling a Minimal API.

Built-in API Integration

Although the approach used isn't very scalable, with a proxy rule needed for every user-defined API route:

export default defineConfig({
    //...
    server: {
        proxy: {
            '^/weatherforecast': {
                target,
                secure: false
            }
        },
    }
})

And the need for hand maintained Types to describe the shape of the API responses with Stringly Typed fetch API calls referencing string routes:

import { defineComponent } from 'vue';

type Forecasts = {
    date: string,
    temperatureC: string,
    temperatureF: string,
    summary: string
}[];

interface Data {
    loading: boolean,
    post: null | Forecasts
}

export default defineComponent({
    data(): Data {
        return {
            loading: false,
            post: null
        };
    },
    created() {
        // fetch the data when the view is created and the data is
        // already being observed
        this.fetchData();
    },
    watch: {
        // call again the method if the route changes
        '$route': 'fetchData'
    },
    methods: {
        fetchData(): void {
            this.post = null;
            this.loading = true;

            fetch('weatherforecast')
                .then(r => r.json())
                .then(json => {
                    this.post = json as Forecasts;
                    this.loading = false;
                    return;
                });
        }
    },
});

Which is used to render the API response in a hand rolled table:

<div v-if="post" class="content">
    <table>
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            <tr v-for="forecast in post" :key="forecast.date">
                <td>{‎{ forecast.date }‎}</td>
                <td>{‎{ forecast.temperatureC }‎}</td>
                <td>{‎{ forecast.temperatureF }‎}</td>
                <td>{‎{ forecast.summary }‎}</td>
            </tr>
        </tbody>
    </table>
</div>

ServiceStack API Integration

Fortunately ServiceStack can significantly improve this development experience with the /api pre-defined route where only a single proxy rule is needed to proxy all APIs:

export default defineConfig({
    //...
    server: {
        proxy: {
            '^/api': {
                target,
                secure: false
            }
        },
    }
})

End-to-end Typed APIs

Instead of hand-rolled types and Stringly Typed API calls, it utilizes server generated TypeScript DTOs with a generic JsonServiceClient to enable end-to-end Typed APIs:

import { ref, onMounted } from 'vue'
import { ApiResult } from "@servicestack/client"
import { useClient } from "@servicestack/vue"
import { GetWeatherForecast } from "@/dtos"

const client = useClient()
const api = ref(new ApiResult())

onMounted(async () => {
    api.value = await client.api(new GetWeatherForecast())
})

This benefits in less code to maintain, immediate static typing analysis to ensure correct usage of APIs and valuable feedback when APIs are changed, that's easily updated with a single command:

npm run dtos

High Productivity Vue Components

With access to the ServiceStack Vue Components library there's also less code to maintain in the UI, where you can render a beautiful tailwind styled DataGrid with just:

<DataGrid :items="api.response" />

ServiceStack Vue SPA Features

Other high-productivity features available in the ServiceStack Vue SPA template include:

Integrated Identity Auth

Pre-configured with ASP.NET Core Identity Auth, including Sign In and Custom Registration APIs and UI Pages which can be customized as needed, examples of Role-based security as well as a turn key solution for Integrating Identity Auth Registration workflow with your SMTP Provider with all emails sent from a managed non-blocking Background MQ for optimal responsiveness and execution.

tailwindcss

Tailwind has quickly become the best modern CSS framework for creating scalable, mobile-first responsive websites built upon a beautiful expert-crafted constraint-based Design System that enables effortless reuse of a growing suite of Free Community and professionally-designed Tailwind UI Component Libraries, invaluable for quickly creating beautiful websites.

Dark Mode

In addition to revolutionizing how we style mobile-first responsive Apps, Tailwind's Dark Mode does the same for enabling Dark Mode a feature supported throughout all of ServiceStack's Vue Component Library.

Built for Productivity

So that you're immediately productive out-of-the-box, the template includes a rich set of high-productivity features, including:

tailwind/typography Beautiful css typography for markdown articles & blog posts
tailwind/forms Beautiful css form & input styles that's easily overridable
Markdown Native Markdown integration
plugin/press Static markdown for creating blogs, videos and other content
plugin/vue-router Conventional file system based routing for Vue 3 on Vite
plugin/layouts Support for multiple page layouts
plugin/components Auto importing & registering of components on-demand
plugin/svg Load SVG files as Vue components
Iconify Unified registry to access 100k+ high quality SVG icons

Bookings CRUD Pages

Bookings CRUD example shows how you can rapidly develop beautiful responsive, customized CRUD UIs with minimal effort using AutoQuery APIs, AutoForms & AutoQueryGrid Vue Components.

Admin Pages

Whilst Bookings CRUD is a good example of creating custom UI for end users, you may also want to quickly develop a set of back-office CRUD Admin UIs to manage your App's Database tables, which is easily achievable AutoQueryGrid's default behavior:

The development UX of Admin Pages is further improved in Vue Vite which is able to use SFC Pages and conventional file system routing to quickly add Admin Pages to manage an App's back-end tables, e.g:

/admin/coupons.vue

<AutoQueryGrid type="Coupon" />

/admin/bookings.vue

<AutoQueryGrid type="Booking"
selected-columns="id,name,roomType,roomNumber,bookingStartDate,cost,couponId,discount"
  :header-titles="{ roomNumber:'Room No', bookingStartDate:'Start Date' }"
   :visible-from="{ roomNumber:'lg', cost:'md', couponId:'xl', discount:'never' }" />

Vite Press Plugin

Most Apps typically have a mix of dynamic functionality and static content which in our experience is best maintained in Markdown, which is why excited about the new Vite Press Plugin which brings the same Markdown features in our razor-ssg, razor-press and our blazor-vue templates, and re-implements them in Vite where they can be used to add the same rich content features to Vite Vue and Vite React Apps.

A goal for vite-press-plugin is to implement a suite of universal markdown-powered features that can be reused across all our Vue, React and .NET Razor and Blazor project templates, allowing you to freely copy and incorporate same set of markdown feature folders to power markdown content features across a range of websites built with different technologies.

All of Razor SSG's features are available in Vite Press Plugin, including:

  • Blog - Full Featured, beautiful Tailwind Blog with multiple discoverable views
  • What's New - Build Product and Feature Release pages
  • Videos - Maintain Video Libraries and Playlists
  • Metadata APIs - Generate queryable static .json metadata APIs for all content
  • Includes - Create and reuse Markdown fragments

It also supports an enhanced version of markdown for embedding richer UI markup in markdown content where most of VitePress Containers are supported, including:

Vue Components In Markdown

At the cost of reduced portability, you’re also able to embed richer Interactive Vue components directly in markdown: