sunniejs/vue-h5-template: a Vue 3 mobile H5 starter that ships a real app, not a playground
:tada:vue搭建移动端开发,基于vue-cli4.0+webpack 4+vant ui + sass+ rem适配方案+axios封装,构建手机端模板脚手架
At a glance
- What is it?
- The v2 branch of this MIT-licensed template targets mobile H5 business apps with typed Axios, TanStack Query, streaming AI chat and a build-time single-choice UI framework. It is opinionated, and the opinions are the point.
- Who is it for?
- Adopt it if you are starting a mobile H5 product in Vue 3 and want request typing, server-state separation and a working demo app on day one; skip it if you need IE or very old Android support, since the README states the target is iOS Safari 15+, Android Chrome 80+ and modern WeChat WebViews, with no full polyfill bundle.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Vue, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What sunniejs/vue-h5-template solves, and who it is built for
Most Vue mobile starters stop at a router, a UI library and a rem setup. This one starts where those stop. The README states v2 is aimed at real mobile H5 business work and explicitly says it is not a component-library playground: the repository carries a working shop, a delivery-project CRUD module, an AI chat page and an error-handling example set. That changes who it is for. A solo developer building a landing page will find the surface area larger than needed. A team that already knows it will need server state, request tracing, i18n and a mock-to-real backend switch is the intended audience, because those concerns are wired into the directory layout rather than left as an exercise.
The stack is fixed and current: Vue 3.5, Vite 8 with Rolldown, TypeScript 5.9, Vue Router 4, Pinia 3. The template's own package.json pins axios at 1.20.0 and carries vant, @nutui/nutui and @varlet/ui as dependencies. The repository is not archived and the last push was on 2026-09-03, so it is still moving, though the README's roadmap shows P1 and P2 items that are recommended or optional rather than shipped.
State separation: Pinia for client, TanStack Query for server
The clearest architectural decision in the template is where state lives. Pinia holds login session, cart, theme and feature flags. Remote data, caching, retry, cancellation, mutations, pagination and infinite queries go through @tanstack/vue-query. The README gives the reason plainly: Pinia manages client state only. This matters because the common failure mode in Vue apps is a store that slowly becomes a cache, with hand-written loading flags and stale data bugs. Here the boundary is stated in the docs and reflected in the directory layout, where src/store and src/plugins sit apart.
The AI chat follows the same logic but takes a third path. Session lifecycle is orchestrated by a useStreamingChat composable, while the provider transport lives under src/services/ai. The README says the transport is deliberately kept out of Pinia and out of the Query cache. That is a defensible split: a streaming response is neither a store value nor a cacheable query result, and forcing it into either would produce awkward code. The cost is one more concept for a newcomer to learn before the chat page makes sense.
The API layer and OpenAPI contract generation
Pages do not call Axios directly, and the README states that catch (error: any) is not written. Instead, functions are added under src/api/modules and consumed in pages or query composables, with errors narrowed through an isApiError helper. The client itself handles ApiResponse<T>, ApiError, request IDs, tokens, 401 responses, timeouts and network errors, and request IDs are toggled by VITE_REQUEST_ID_ENABLED.
Contract types come from a local OpenAPI file. The README describes the replacement flow: swap openapi/schema.yaml for a real schema or point the generator at a URL, run pnpm api:generate, have API modules reference the generated types, then commit both the schema and the generated file so CI typecheck catches contract drift. The script in package.json runs openapi-typescript against openapi/schema.yaml and writes src/types/api/generated.d.ts before formatting it. Committing the generated file is the part teams argue about; here it is a deliberate choice that turns drift into a build failure rather than a runtime surprise.
Install and first run: from pnpm install to the mock AI chat
The README requires Node.js >=22.12.0 and pnpm >=9.12.0. The quick start is three commands, and the development server enables mocks by default, so no backend is needed to see the app working.
pnpm install
cp .env.example .env.local
pnpm devThe third command starts Vite and prints a local address. Opening it shows the app shell. Login accepts any non-empty username and password in mock mode. The bottom navigation's third tab is the engineering examples, and a floating AI entry in the lower right opens /ai/chat, where the mock server returns SSE chunks from POST /api/ai/chat.
Routes you can visit immediately include /shop, /shop/cart, /examples/request and /examples/workspace. The request example covers 400, 401, 403, 404, 409, business 422, 500 and timeout cases, which is a practical way to see how the error narrowing behaves. The environment file exposes the switches you will touch first:
VITE_API_BASE_URL=/api
VITE_USE_MOCK=true
VITE_UI_FRAMEWORK=vant
VITE_PWA_ENABLED=falseSetting VITE_UI_FRAMEWORK to vant, nutui or varlet changes which resolver and #ui-demo alias Vite selects. The README states the production bundle contains only the chosen framework even though all three stay in the dependency list. Before pushing, pnpm check runs lint, typecheck, test and build in sequence; it deliberately excludes E2E, and CI runs Playwright separately.
Where the template pushes back: polyfills, PWA caching and mock safety
The browser baseline is a real constraint, not a footnote. The README targets iOS Safari 15+, Android Chrome 80+ and modern WeChat and WeCom WebViews, and says it will not inject a full polyfill bundle for IE or very old Android. If your product still has to run in an old embedded WebView, this template is the wrong starting point and no configuration flag will fix that.
PWA is off by default through VITE_PWA_ENABLED=false. When enabled, the service worker caches the built App Shell and static images, and the README states /api is explicitly excluded from caching. That is a sensible default for authenticated apps, but it means enabling PWA will not make your API responses available offline, which some teams assume it will. Image optimization through Sharp and SVGO runs only in production builds and is controlled by VITE_IMAGE_OPTIMIZE, which the README suggests turning off when a CDN image pipeline already handles compression.
Security defaults are documented rather than enforced by the framework. Markdown disallows raw HTML and passes through DOMPurify, redirects accept only same-site absolute paths, mocks are off in production, and the token example uses sessionStorage. The README is direct that production projects should prefer SameSite, Secure, HttpOnly cookies or a BFF, and configure CSP, CSRF and rate limiting at the gateway. A template cannot do that for you, and the documentation says so instead of implying otherwise.
Choosing between this and a plain Vite Vue starter
The obvious alternative is create-vue or a bare Vite Vue scaffold. The difference is not quality but scope and timing. A bare scaffold gives you a router, a build and nothing else, and you decide everything afterward. This template decides first: TanStack Query instead of hand-rolled fetching, a typed Axios client with request IDs, an OpenAPI generation step, a single UI framework selected at build time, three locales with lazy loading, and a mock server that mirrors the real backend contract.
That trade is worth naming. With a bare scaffold you spend the first weeks writing the request layer, the error model and the mock setup, and you own every decision. With this template those decisions are already made, and changing them later means working against the directory rules in AGENTS.md, which the README describes as the primary engineering context for Codex, Claude Code, Cursor and Copilot. If your team has strong existing conventions, the template's conventions will be friction. If your team has none, they are a starting position that is at least internally consistent.
Maintenance, licence and the cost of upgrading
The repository is MIT licensed, which permits commercial use and modification; the README links to a License file at the repository root. Nothing in the repository suggests additional terms, but licence questions about your own derivative work belong with your legal counsel, not with this review.
The last push was on 2026-09-03, so the project is not archived and has recent activity. Upgrade cost is the more interesting question. The v2 branch is a break from the earlier version, and the README links a dedicated migration page, which tells you the maintainers expect existing users to move deliberately rather than by pulling. Release Please maintains versions, the CHANGELOG and GitHub Releases from Conventional Commits, so version history is generated rather than hand-written. The CI pipeline runs lint, typecheck, test and build through pnpm check, then Playwright separately, which means a dependency bump that breaks types will fail before merge. The practical cost sits in the OpenAPI step: if your backend schema changes, you regenerate and commit, and the typecheck is what tells you which call sites moved.
Editorial conclusion
Adopt it if you are starting a mobile H5 product in Vue 3 and want request typing, server-state separation and a working demo app on day one; skip it if you need IE or very old Android support, since the README states the target is iOS Safari 15+, Android Chrome 80+ and modern WeChat WebViews, with no full polyfill bundle. Before committing, run pnpm check, confirm the 60% coverage gate passes on your machine, and replace openapi/schema.yaml with your own schema so pnpm api:generate produces contract types you actually own.
Frequently asked questions
Does sunniejs/vue-h5-template need a backend to run?
No. The README states that pnpm dev uses the frontend mock by default and does not require installing the backend, and that in development any non-empty username and password will log you in. A real backend is only needed for the integration mode started with pnpm dev:integration.
How do I switch sunniejs/vue-h5-template between Vant, NutUI and Varlet?
Set VITE_UI_FRAMEWORK to vant, nutui or varlet in the environment file. The README states Vite then selects the matching resolver and #ui-demo alias, and that the production bundle contains only the framework matching the current value.
Where do the API types in sunniejs/vue-h5-template come from?
They are generated from a local OpenAPI schema. Running pnpm api:generate reads openapi/schema.yaml and writes src/types/api/generated.d.ts, and the README recommends committing both the schema and the generated file so CI typecheck catches contract drift.
Does sunniejs/vue-h5-template support Internet Explorer or old Android WebViews?
No. The README states the target is iOS Safari 15+, Android Chrome 80+ and modern WeChat and WeCom WebViews, and that it does not inject a full polyfill bundle for IE or very old Android.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sunniejs-vue-h5-template)