This template contains our essential recommendations for a modern Vue Single Page App optimal for both productivity and performance.
Vite | Modern typed API, Lighting fast reloads, optimal builds, growing ecosystem |
Vue3 | Elegant, composable reactive typed API that scales from small to large Apps |
Tailwindcss | Productive responsive-first utility-based css framework with growing rich component ecosystem |
TypeScript | Advanced type-safety, static analysis and richer IDE tooling |
Iconify | Unified registry to access 100k+ high quality SVG icons from 100+ icon sets |
Markdown | Native Markdown integration with advanced featureset supporting embedding of HTML & Vue Components |
Vite SSG | Server-side generation for Vue 3 on Vite |
SWRV | stale-while-revalidate library for Vue 3’s composition API enabling optimal end-user UX for API integrations |
Dark Mode | OS defined & user toggable dark mode |
Pinia | Vue 3 Intuitive, TypeSafe Reactive State Management, checkout Todos |
tailwind/typography | Beautiful css typography for markdown articles & blog posts |
tailwind/forms | Beautiful css form & input styles that’s easy to override with utilities |
plugin/pages | 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/auto-import | Global imports in source files for reduced boilerplate |
Authentication | Simple, built-in flexible auth protected by route guards |
Validation | Auto form binding, submission, loading and validation |
Vue Plugins
The Vite plugins registered in vite.config.ts
improves productivity by adopting popular conventions that automating-away manual tasks & configurations.
unplugin-vue-components
For Auto Registering Vue Components, either .vue
SFC’s, .md
Markdown components or Iconify’s icons as Vue3 components.
Components({
extensions: ['vue', 'md'],
include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
resolvers: [
// auto import icons without any prefix
IconsResolver({
componentPrefix: ''
}),
],
dts: 'src/components.d.ts', // auto-gen type definitions
})
unplugin-icons
For accessing thousands of Iconfigy’s SVG icons as Vue components on-demand universally.
Icons({ })
vite-plugin-pages
For auto generating vue routing configurations for each Vue 3 component from NuxtJS inspired File System Routing conventions.
Pages({
dirs: [
{ dir: "src/pages", baseRoute: "posts" }, // at: /posts/*
{ dir: "src/views", baseRoute: "" }, // at: /*
],
extensions: ['vue', 'md'],
extendRoute(route:any) {
// attach markdown frontmatter metadata to their routes
},
})
vite-plugin-md
For enabling Markdown Support by converting each .md
document into a Vue Component that’s rendered using markdown-it.
Markdown({
markdownItOptions: {
// html: true,
},
markdownItSetup(md) {
//md.use(markdownPlugin)
},
wrapperComponent: 'MarkdownPage'
})
App Features
Stale While Revalidate
stale-while-revalidate is a popular UI pattern helps developers balance between immediacy—loading cached content right away—and freshness—ensuring updates to the cached content are used in the future.
This template includes a swrClient
that provides a typed wrapper around Vue3’s SWVR library for making typed API Requests with ServiceStack’s typed JsonServiceClient.
<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>
This reactively sets up the UI to handle multiple states:
loading
- displays theloading...
message whilst API request is in transitdata
- when completed, populated with aHelloResponse
and displayederror
- when failed, populated withResponseStatus
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, which updates the UI when completed.
Ultimately this provides the optimal end-user UX with the UI being immediately updated with stale results initially, before being re-updated with the latest UI when the new API Request is completed.