Full Code of antfu-collective/vitesse for AI

main 8a01bc9283fe cached
75 files
102.7 KB
30.6k tokens
15 symbols
1 requests
Download .txt
Repository: antfu-collective/vitesse
Branch: main
Commit: 8a01bc9283fe
Files: 75
Total size: 102.7 KB

Directory structure:
gitextract_7rc8tos6/

├── .dockerignore
├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       └── ci.yml
├── .gitignore
├── .npmrc
├── .vscode/
│   ├── extensions.json
│   └── settings.json
├── Dockerfile
├── LICENSE
├── README.md
├── README.zh-CN.md
├── cypress/
│   ├── e2e/
│   │   └── basic.spec.ts
│   └── tsconfig.json
├── cypress.config.ts
├── eslint.config.js
├── index.html
├── locales/
│   ├── README.md
│   ├── ar.yml
│   ├── de.yml
│   ├── en.yml
│   ├── es.yml
│   ├── fr.yml
│   ├── id.yml
│   ├── it.yml
│   ├── ja.yml
│   ├── ka.yml
│   ├── ko.yml
│   ├── pl.yml
│   ├── pt-BR.yml
│   ├── ru.yml
│   ├── tr.yml
│   ├── uk.yml
│   ├── uz.yml
│   ├── vi.yml
│   └── zh-CN.yml
├── netlify.toml
├── package.json
├── pnpm-workspace.yaml
├── public/
│   └── _headers
├── src/
│   ├── App.vue
│   ├── auto-imports.d.ts
│   ├── components/
│   │   ├── README.md
│   │   ├── TheCounter.vue
│   │   ├── TheFooter.vue
│   │   └── TheInput.vue
│   ├── components.d.ts
│   ├── composables/
│   │   └── dark.ts
│   ├── layouts/
│   │   ├── 404.vue
│   │   ├── README.md
│   │   ├── default.vue
│   │   └── home.vue
│   ├── main.ts
│   ├── modules/
│   │   ├── README.md
│   │   ├── i18n.ts
│   │   ├── nprogress.ts
│   │   ├── pinia.ts
│   │   └── pwa.ts
│   ├── pages/
│   │   ├── README.md
│   │   ├── [...all].vue
│   │   ├── about.md
│   │   ├── hi/
│   │   │   └── [name].vue
│   │   └── index.vue
│   ├── route-map.d.ts
│   ├── shims.d.ts
│   ├── stores/
│   │   └── user.ts
│   ├── styles/
│   │   ├── main.css
│   │   └── markdown.css
│   └── types.ts
├── test/
│   ├── __snapshots__/
│   │   └── component.test.ts.snap
│   ├── basic.test.ts
│   └── component.test.ts
├── tsconfig.json
├── uno.config.ts
└── vite.config.ts

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
node_modules
dist


================================================
FILE: .editorconfig
================================================
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true


================================================
FILE: .github/FUNDING.yml
================================================
open_collective: antfu
github: [antfu]


================================================
FILE: .github/workflows/ci.yml
================================================
name: CI

on:
  push:
    branches:
      - main

  pull_request:
    branches:
      - main

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v3
      - uses: actions/setup-node@v4
        with:
          node-version: lts/*
          cache: pnpm

      - name: Install
        run: pnpm install

      - name: Lint
        run: pnpm run lint

  typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v3
      - uses: actions/setup-node@v4
        with:
          node-version: lts/*
          cache: pnpm

      - name: Install
        run: pnpm install

      - name: Typecheck
        run: pnpm run typecheck

  test:
    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        node-version: [20.x, 22.x]
        os: [ubuntu-latest]
      fail-fast: false

    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v3
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          registry-url: https://registry.npmjs.org/
          cache: pnpm

      - run: pnpm install
      - run: pnpm run test:unit

  test-e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: |
            ~/.cache
          key: cypress-cache-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}

      - uses: pnpm/action-setup@v3

      - name: Use Node.js
        uses: actions/setup-node@v4
        with:
          node-version: lts/*
          registry-url: https://registry.npmjs.org/
          cache: pnpm

      - run: pnpm install

      - name: Cypress PNPM Patch
        run: cp pnpm-lock.yaml package-lock.json

      - name: Cypress
        uses: cypress-io/github-action@v6
        with:
          install-command: echo
          build: pnpm run build
          start: npx vite preview --port 3333


================================================
FILE: .gitignore
================================================
.DS_Store
.vite-ssg-dist
.vite-ssg-temp
*.local
dist
dist-ssr
node_modules
.idea/
*.log
cypress/downloads
public/assets/fonts


================================================
FILE: .npmrc
================================================
shamefully-hoist=true


================================================
FILE: .vscode/extensions.json
================================================
{
  "recommendations": [
    "antfu.iconify",
    "antfu.unocss",
    "antfu.vite",
    "antfu.goto-alias",
    "csstools.postcss",
    "dbaeumer.vscode-eslint",
    "vue.volar",
    "lokalise.i18n-ally",
    "streetsidesoftware.code-spell-checker"
  ]
}


================================================
FILE: .vscode/settings.json
================================================
{
  "cSpell.words": ["Vitesse", "Vite", "unocss", "vitest", "vueuse", "pinia", "demi", "antfu", "iconify", "intlify", "vitejs", "unplugin", "pnpm"],
  "i18n-ally.sourceLanguage": "en",
  "i18n-ally.keystyle": "nested",
  "i18n-ally.localesPaths": "locales",
  "i18n-ally.sortKeys": true,

  // Disable the default formatter
  "prettier.enable": false,
  "editor.formatOnSave": false,

  // Auto fix
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit",
    "source.organizeImports": "never"
  },

  // Silent the stylistic rules in you IDE, but still auto fix them
  "eslint.rules.customizations": [
    { "rule": "style/*", "severity": "off" },
    { "rule": "format/*", "severity": "off" },
    { "rule": "*-indent", "severity": "off" },
    { "rule": "*-spacing", "severity": "off" },
    { "rule": "*-spaces", "severity": "off" },
    { "rule": "*-order", "severity": "off" },
    { "rule": "*-dangle", "severity": "off" },
    { "rule": "*-newline", "severity": "off" },
    { "rule": "*quotes", "severity": "off" },
    { "rule": "*semi", "severity": "off" }
  ],

  // The following is optional.
  // It's better to put under project setting `.vscode/settings.json`
  // to avoid conflicts with working with different eslint configs
  // that does not support all formats.
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "vue",
    "html",
    "markdown",
    "json",
    "jsonc",
    "yaml"
  ]
}


================================================
FILE: Dockerfile
================================================
FROM node:20-alpine AS build-stage

WORKDIR /app
RUN corepack enable

COPY .npmrc package.json pnpm-lock.yaml pnpm-workspace.yaml ./
RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store \
    pnpm install --frozen-lockfile

COPY . .
RUN pnpm build

FROM nginx:stable-alpine AS production-stage

COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020-PRESENT Anthony Fu

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<p align='center'>
  <img src='https://user-images.githubusercontent.com/11247099/154486817-f86b8f20-5463-4122-b6e9-930622e757f2.png' alt='Vitesse - Opinionated Vite Starter Template' width='600'/>
</p>

<p align='center'>
Mocking up web app with <b>Vitesse</b><sup><em>(speed)</em></sup><br>
</p>

<br>

<p align='center'>
<a href="https://vitesse.netlify.app/">Live Demo</a>
</p>

<br>

> **Note**: This template is created during the early transition of Vue 3 and Vite. At this moment, if you are seeking for better Vue developer experience and more consistent maintenance, we recommend using [Nuxt](https://nuxt.com) instead (it also works perfectly with SPA or SSG as needed). This template still serves as a reference, but expect slower updates.

<br>

<p align='center'>
<b>English</b> | <a href="https://github.com/antfu-collective/vitesse/blob/main/README.zh-CN.md">简体中文</a>
<!-- Contributors: Thanks for getting interested, however we DON'T accept new translations to the README, thanks. -->
</p>

<br>

## Features

- ⚡️ [Vue 3](https://github.com/vuejs/core), [Vite](https://github.com/vitejs/vite), [pnpm](https://pnpm.io/), [esbuild](https://github.com/evanw/esbuild) - born with fastness

- 🗂 [File based routing](./src/pages)

- 📦 [Components auto importing](./src/components)

- 🍍 [State Management via Pinia](https://pinia.vuejs.org/)

- 📑 [Layout system](./src/layouts)

- 📲 [PWA](https://github.com/antfu/vite-plugin-pwa)

- 🎨 [UnoCSS](https://github.com/antfu/unocss) - the instant on-demand atomic CSS engine

- 😃 [Use icons from any icon sets with classes](https://github.com/antfu/unocss/tree/main/packages/preset-icons)

- 🌍 [I18n ready](./locales)

- 🔎 [Component Preview](https://github.com/johnsoncodehk/vite-plugin-vue-component-preview)

- 🗒 [Markdown Support](https://github.com/unplugin/unplugin-vue-markdown)

- 🔥 Use the [new `<script setup>` syntax](https://github.com/vuejs/rfcs/pull/227)

- 📥 [APIs auto importing](https://github.com/antfu/unplugin-auto-import) - use Composition API and others directly

- 🖨 Static-site generation (SSG) via [vite-ssg](https://github.com/antfu/vite-ssg)

- 🦔 Critical CSS via [beasties](https://github.com/danielroe/beasties)

- 🦾 TypeScript, of course

- ⚙️ Unit Testing with [Vitest](https://github.com/vitest-dev/vitest), E2E Testing with [Cypress](https://cypress.io/) on [GitHub Actions](https://github.com/features/actions)

- ☁️ Deploy on Netlify, zero-config

<br>

## Pre-packed

### UI Frameworks

- [UnoCSS](https://github.com/antfu/unocss) - The instant on-demand atomic CSS engine.

### Icons

- [Iconify](https://iconify.design) - use icons from any icon sets [🔍Icônes](https://icones.netlify.app/)
- [Pure CSS Icons via UnoCSS](https://github.com/antfu/unocss/tree/main/packages/preset-icons)

### Plugins

- [Vue Router](https://github.com/vuejs/router)
  - [`unplugin-vue-router`](https://github.com/posva/unplugin-vue-router) - file system based routing
  - [`vite-plugin-vue-layouts`](https://github.com/JohnCampionJr/vite-plugin-vue-layouts) - layouts for pages
- [Pinia](https://pinia.vuejs.org) - Intuitive, type safe, light and flexible Store for Vue using the composition api
- [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components) - components auto import
- [`unplugin-auto-import`](https://github.com/antfu/unplugin-auto-import) - Directly use Vue Composition API and others without importing
- [`unplugin-vue-macros`](https://github.com/sxzz/unplugin-vue-macros) - Explore and extend more macros and syntax sugar to Vue.
- [`vite-plugin-pwa`](https://github.com/antfu/vite-plugin-pwa) - PWA
- [`unplugin-vue-markdown`](https://github.com/unplugin/unplugin-vue-markdown) - Markdown as components / components in Markdown
  - [`@shikijs/markdown-it`](https://github.com/shikijs/shiki) - [Shiki](https://github.com/shikijs/shiki) for syntax highlighting
- [Vue I18n](https://github.com/intlify/vue-i18n-next) - Internationalization
  - [`unplugin-vue-i18n`](https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n) - unplugin for Vue I18n
- [VueUse](https://github.com/antfu/vueuse) - collection of useful composition APIs
- [`vite-ssg-sitemap`](https://github.com/jbaubree/vite-ssg-sitemap) - Sitemap generator
- [`@unhead/vue v2`](https://github.com/unjs/unhead) - manipulate document head reactively
- [`vite-plugin-vue-devtools`](https://github.com/vuejs/devtools-next) - Designed to enhance the Vue developer experience.

### Coding Style

- Use Composition API with [`<script setup>` SFC syntax](https://github.com/vuejs/rfcs/pull/227)
- [ESLint](https://eslint.org/) with [@antfu/eslint-config](https://github.com/antfu/eslint-config), single quotes, no semi.

### Dev tools

- [TypeScript](https://www.typescriptlang.org/)
- [Vitest](https://github.com/vitest-dev/vitest) - Unit testing powered by Vite
- [Cypress](https://cypress.io/) - E2E testing
- [pnpm](https://pnpm.js.org/) - fast, disk space efficient package manager
- [`vite-ssg`](https://github.com/antfu/vite-ssg) - Static-site generation
  - [beasties](https://github.com/danielroe/beasties) - Critical CSS
- [Netlify](https://www.netlify.com/) - zero-config deployment
- [VS Code Extensions](./.vscode/extensions.json)
  - [Vite](https://marketplace.visualstudio.com/items?itemName=antfu.vite) - Fire up Vite server automatically
  - [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) - Vue 3 `<script setup>` IDE support
  - [Iconify IntelliSense](https://marketplace.visualstudio.com/items?itemName=antfu.iconify) - Icon inline display and autocomplete
  - [i18n Ally](https://marketplace.visualstudio.com/items?itemName=lokalise.i18n-ally) - All in one i18n support
  - [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)

## Variations

As this template is strongly opinionated, the following provides a curated list for community-maintained variations with different preferences and feature sets. Check them out as well. PR to add yours is also welcome!

###### Official

- [vitesse-lite](https://github.com/antfu/vitesse-lite) - Lightweight version of Vitesse
- [vitesse-nuxt3](https://github.com/antfu/vitesse-nuxt3) - Vitesse for Nuxt 3
- [vitesse-nuxt-bridge](https://github.com/antfu/vitesse-nuxt-bridge) - Vitesse for Nuxt 2 with Bridge
- [vitesse-webext](https://github.com/antfu/vitesse-webext) - WebExtension Vite starter template

###### Community

- [vitesse-ssr-template](https://github.com/frandiox/vitesse-ssr-template) by [@frandiox](https://github.com/frandiox) - Vitesse with SSR
- [vitailse](https://github.com/zynth17/vitailse) by [@zynth17](https://github.com/zynth17) - Like Vitesse but with TailwindCSS
- [vitesse-modernized-chrome-ext](https://github.com/xiaoluoboding/vitesse-modernized-chrome-ext) by [@xiaoluoboding](https://github.com/xiaoluoboding) - ⚡️ Modernized Chrome Extension Manifest V3 Vite Starter Template
- [vitesse-stackter-clean-architect](https://github.com/shamscorner/vitesse-stackter-clean-architect) by [@shamscorner](https://github.com/shamscorner) - A modular clean architecture pattern in vitesse template
- [vitesse-enterprise](https://github.com/FranciscoKloganB/vitesse-enterprise) by [@FranciscoKloganB](https://github.com/FranciscoKloganB) - Consistent coding styles regardless of team-size.
- [vitecamp](https://github.com/nekobc1998923/vitecamp) by [@nekobc1998923](https://github.com/nekobc1998923) - Like Vitesse but without SSG/SSR/File based routing, includes Element Plus
- [vitesse-h5](https://github.com/YunYouJun/vitesse-h5) by [@YunYouJun](https://github.com/YunYouJun) - Vitesse for Mobile
- [bat](https://github.com/olgam4/bat) by [@olgam4](https://github.com/olgam4) - Vitesse for SolidJS
- [vitesse-solid](https://github.com/xbmlz/vitesse-solid) by [@xbmlz](https://github.com/xbmlz) - Vitesse for SolidJS, build with [`SolidStart`](https://start.solidjs.com/), includes [UnoCSS](https://github.com/unocss/unocss).
- [vue3-vant-mobile](https://github.com/easy-temps/vue3-vant-mobile) by [CharleeWa](https://github.com/CharleeWa) - Like Vitesse but without SSG/SSR, includes Vant

## Try it now!

> Vitesse requires Node >=14.18

### GitHub Template

[Create a repo from this template on GitHub](https://github.com/antfu-collective/vitesse/generate).

### Clone to local

If you prefer to do it manually with the cleaner git history

```bash
npx degit antfu-collective/vitesse my-vitesse-app
cd my-vitesse-app
pnpm i # If you don't have pnpm installed, run: npm install -g pnpm
```

## Checklist

When you use this template, try follow the checklist to update your info properly

- [ ] Change the author name in `LICENSE`
- [ ] Change the title in `App.vue`
- [ ] Change the hostname in `vite.config.ts`
- [ ] Change the favicon in `public`
- [ ] Remove the `.github` folder which contains the funding info
- [ ] Clean up the READMEs and remove routes

And, enjoy :)

## Usage

### Development

Just run and visit http://localhost:3333

```bash
pnpm dev
```

### Build

To build the App, run

```bash
pnpm build
```

And you will see the generated file in `dist` that ready to be served.

### Deploy on Netlify

Go to [Netlify](https://app.netlify.com/start) and select your clone, `OK` along the way, and your App will be live in a minute.

### Docker Production Build

First, build the vitesse image by opening the terminal in the project's root directory.

```bash
docker buildx build . -t vitesse:latest
```

Run the image and specify port mapping with the `-p` flag.

```bash
docker run --rm -it -p 8080:80 vitesse:latest
```

## Why

I have created several Vite apps recently. Setting the configs up is kinda the bottleneck for me to make the ideas simply come true within a very short time.

So I made this starter template for myself to create apps more easily, along with some good practices that I have learned from making those apps. It's strongly opinionated, but feel free to tweak it or even maintain your own forks. [(see community maintained variation forks)](#variations)


================================================
FILE: README.zh-CN.md
================================================
<p align='center'>
  <img src='https://user-images.githubusercontent.com/11247099/154486817-f86b8f20-5463-4122-b6e9-930622e757f2.png' alt='Vitesse - Opinionated Vite Starter Template' width='600'/>
</p>

<p align='center'>
快速地<sup><em>Vitesse</em></sup> 创建 Web 应用
<br>
</p>

<br>

<p align='center'>
<a href="https://vitesse.netlify.app/">在线 Demo</a>
</p>

<br>

> **Note**: 本模板创建于 Vue 3 和 Vite 的早期过渡时期。目前,如果您正在寻求更好的 Vue 开发体验和更持续的维护,我们建议您使用 [Nuxt 3](https://nuxt.com) 来代替(它也可以根据需要使用 SPA 或 SSG)。本模板仍会作为参考缓慢地维护下去,但将不会有太多的更新。

<br>

<p align='center'>
<a href="https://github.com/antfu-collective/vitesse/blob/main/README.md">English</a> | <b>简体中文</b>
</p>

<br>

## 特性

- ⚡️ [Vue 3](https://github.com/vuejs/core), [Vite](https://github.com/vitejs/vite), [pnpm](https://pnpm.io/), [esbuild](https://github.com/evanw/esbuild) - 就是快!

- 🗂 [基于文件的路由](./src/pages)

- 📦 [组件自动化加载](./src/components)

- 🍍 [使用 Pinia 的状态管理](https://pinia.vuejs.org)

- 📑 [布局系统](./src/layouts)

- 📲 [PWA](https://github.com/antfu/vite-plugin-pwa)

- 🎨 [UnoCSS](https://github.com/unocss/unocss) - 高性能且极具灵活性的即时原子化 CSS 引擎

- 😃 [各种图标集为你所用](https://github.com/antfu/unocss/tree/main/packages/preset-icons)

- 🌍 [I18n 国际化开箱即用](./locales)

- 🗒 [Markdown 支持](https://github.com/unplugin/unplugin-vue-markdown)

- 🔥 使用 [新的 `<script setup>` 语法](https://github.com/vuejs/rfcs/pull/227)

- 📥 [API 自动加载](https://github.com/unplugin/unplugin-auto-import) - 直接使用 Composition API 无需引入

- 🖨 使用 [vite-ssg](https://github.com/antfu/vite-ssg) 进行服务端生成 (SSG)

- 🦔 使用 [beasties](https://github.com/danielroe/beasties) 的生成关键 CSS

- 🦾 TypeScript, 当然

- ⚙️ 结合 [GitHub Actions](https://github.com/features/actions),使用 [Vitest](https://github.com/vitest-dev/vitest) 进行单元测试, [Cypress](https://cypress.io/) 进行 E2E 测试

- ☁️ 零配置部署 Netlify

<br>

## 预配置

### UI 框架

- [UnoCSS](https://github.com/antfu/unocss) - 高性能且极具灵活性的即时原子化 CSS 引擎

### Icons

- [Iconify](https://iconify.design) - 使用任意的图标集,浏览:[🔍Icônes](https://icones.netlify.app/)
- [UnoCSS 的纯 CSS 图标方案](https://github.com/antfu/unocss/tree/main/packages/preset-icons)

### 插件

- [Vue Router](https://github.com/vuejs/router)
  - [`unplugin-vue-router`](https://github.com/posva/unplugin-vue-router) - 以文件系统为基础的路由
  - [`vite-plugin-vue-layouts`](https://github.com/JohnCampionJr/vite-plugin-vue-layouts) - 页面布局系统
- [Pinia](https://pinia.vuejs.org) - 直接的, 类型安全的, 使用 Composition API 的轻便灵活的 Vue 状态管理
- [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components) - 自动加载组件
- [`unplugin-auto-import`](https://github.com/antfu/unplugin-auto-import) - 直接使用 Composition API 等,无需导入
- [`vite-plugin-pwa`](https://github.com/antfu/vite-plugin-pwa) - PWA
- [`unplugin-vue-markdown`](https://github.com/unplugin/unplugin-vue-markdown) - Markdown 作为组件,也可以让组件在 Markdown 中使用
  - [`markdown-it-prism`](https://github.com/jGleitz/markdown-it-prism) - [Prism](https://prismjs.com/) 的语法高亮
  - [`prism-theme-vars`](https://github.com/antfu/prism-theme-vars) - 利用 CSS 变量自定义 Prism.js 的主题
- [Vue I18n](https://github.com/intlify/vue-i18n-next) - 国际化
  - [`unplugin-vue-i18n`](https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n) - Vue I18n 的 Vite 插件
- [VueUse](https://github.com/antfu/vueuse) - 实用的 Composition API 工具合集
- [`vite-ssg-sitemap`](https://github.com/jbaubree/vite-ssg-sitemap) - 站点地图生成器
- [`@vueuse/head`](https://github.com/vueuse/head) - 响应式地操作文档头信息
- [`vite-plugin-vue-devtools`](https://github.com/webfansplz/vite-plugin-vue-devtools) - 旨在增强Vue开发者体验的Vite插件

### 编码风格

- 使用 Composition API 地 [`<script setup>` SFC 语法](https://github.com/vuejs/rfcs/pull/227)
- [ESLint](https://eslint.org/) 配置为 [@antfu/eslint-config](https://github.com/antfu/eslint-config), 单引号, 无分号.

### 开发工具

- [TypeScript](https://www.typescriptlang.org/)
- [Vitest](https://github.com/vitest-dev/vitest) - 基于 Vite 的单元测试框架
- [Cypress](https://cypress.io/) - E2E 测试
- [pnpm](https://pnpm.js.org/) - 快, 节省磁盘空间的包管理器
- [`vite-ssg`](https://github.com/antfu/vite-ssg) - 服务端生成
  - [beasties](https://github.com/danielroe/beasties) - 关键 CSS 生成器
- [Netlify](https://www.netlify.com/) - 零配置的部署
- [VS Code 扩展](./.vscode/extensions.json)
  - [Vite](https://marketplace.visualstudio.com/items?itemName=antfu.vite) - 自动启动 Vite 服务器
  - [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) - Vue 3 `<script setup>` IDE 支持
  - [Iconify IntelliSense](https://marketplace.visualstudio.com/items?itemName=antfu.iconify) - 图标内联显示和自动补全
  - [i18n Ally](https://marketplace.visualstudio.com/items?itemName=lokalise.i18n-ally) - 多合一的 I18n 支持
  - [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)

## 衍生项目

由于这个模板的业务场景非常的局限,下面提供了一个精心策划的列表,列出了社区维护的具有不同偏好和功能集的衍生项目。也可以看看他们。当然也欢迎你 PR 提供自己的项目!

###### 官方

- [vitesse-lite](https://github.com/antfu/vitesse-lite) - Vitesse 的轻量版本
- [vitesse-nuxt3](https://github.com/antfu/vitesse-nuxt3) - Vitesse 的 Nuxt 3 版本
- [vitesse-nuxt-bridge](https://github.com/antfu/vitesse-nuxt-bridge) - Vitesse 的 Nuxt2 桥接版本
- [vitesse-webext](https://github.com/antfu/vitesse-webext) - 开箱即用的浏览器扩展 vite 模板

###### 社区

[查看英文版](./README.md#community)

## 现在可以试试!

> Vitesse 需要 Node 版本 >=14.18

### GitHub 模板

[使用这个模板创建仓库](https://github.com/antfu-collective/vitesse/generate).

### 克隆到本地

如果您更喜欢使用更干净的 git 历史记录手动执行此操作

```bash
npx degit antfu-collective/vitesse my-vitesse-app
cd my-vitesse-app
pnpm i # 如果你没装过 pnpm, 可以先运行: npm install -g pnpm
```

## 清单

使用此模板时,请尝试按照清单正确更新您自己的信息

- [ ] 在 `LICENSE` 中改变作者名
- [ ] 在 `App.vue` 中改变标题
- [ ] 在 `vite.config.ts` 更改主机名
- [ ] 在 `public` 目录下改变favicon
- [ ] 移除 `.github` 文件夹中包含资助的信息
- [ ] 整理 README 并删除路由

紧接着, 享受吧 :)

## 使用

### 开发

只需要执行以下命令就可以在 http://localhost:3333 中看到

```bash
pnpm dev
```

### 构建

构建该应用只需要执行以下命令

```bash
pnpm build
```

然后你会看到用于发布的 `dist` 文件夹被生成。

### 部署到 Netlify

前往 [Netlify](https://app.netlify.com/start) 并选择你的仓库, 一路 `OK` 下去,稍等一下后,你的应用将被创建.


================================================
FILE: cypress/e2e/basic.spec.ts
================================================
context('Basic', () => {
  beforeEach(() => {
    cy.visit('/')
  })

  it('basic nav', () => {
    cy.url()
      .should('eq', 'http://localhost:3333/')

    cy.contains('[Home Layout]')
      .should('exist')

    cy.get('#input')
      .type('Vitesse{Enter}')
      .url()
      .should('eq', 'http://localhost:3333/hi/Vitesse')

    cy.contains('[Default Layout]')
      .should('exist')

    cy.get('[btn]')
      .click()
      .url()
      .should('eq', 'http://localhost:3333/')
  })

  it('markdown', () => {
    cy.get('[data-test-id="about"]')
      .click()
      .url()
      .should('eq', 'http://localhost:3333/about')

    cy.get('.shiki')
      .should('exist')
  })
})


================================================
FILE: cypress/tsconfig.json
================================================
{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "types": [
      "cypress"
    ]
  },
  "include": [
    "**/*.ts"
  ],
  "exclude": []
}


================================================
FILE: cypress.config.ts
================================================
import { defineConfig } from 'cypress'
import vitePreprocessor from 'cypress-vite'

export default defineConfig({
  e2e: {
    baseUrl: 'http://localhost:3333',
    chromeWebSecurity: false,
    specPattern: 'cypress/e2e/**/*.spec.*',
    supportFile: false,
    setupNodeEvents(on) {
      on('file:preprocessor', vitePreprocessor())
    },
  },
})


================================================
FILE: eslint.config.js
================================================
// @ts-check
import antfu from '@antfu/eslint-config'

export default antfu(
  {
    unocss: true,
    formatters: true,
    pnpm: true,
  },
  {
    files: ['README.md', 'README.zh-CN.md'],
    rules: {
      'markdown/heading-increment': 'off',
    },
  },
)


================================================
FILE: index.html
================================================
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="apple-touch-icon" href="/pwa-192x192.png" />
    <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#00aba9" />
    <meta name="msapplication-TileColor" content="#00aba9" />
    <script>
      ;(function () {
        const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
        const setting = localStorage.getItem('vueuse-color-scheme') || 'auto'
        if (setting === 'dark' || (prefersDark && setting !== 'light'))
          document.documentElement.classList.toggle('dark', true)
      })()
    </script>
  </head>
  <body class="font-sans">
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
    <noscript> This website requires JavaScript to function properly. Please enable JavaScript to continue. </noscript>
  </body>
</html>


================================================
FILE: locales/README.md
================================================
## i18n

This directory is to serve your locale translation files. YAML under this folder would be loaded automatically and register with their filenames as locale code.

Check out [`vue-i18n`](https://github.com/intlify/vue-i18n-next) for more details.

If you are using VS Code, [`i18n Ally`](https://github.com/lokalise/i18n-ally) is recommended to make the i18n experience better.


================================================
FILE: locales/ar.yml
================================================
button:
  about: حول
  back: رجوع
  go: تجربة
  home: الرئيسية
  toggle_dark: التغيير إلى الوضع المظلم
  toggle_langs: تغيير اللغة
intro:
  desc: vite مثال لتطبيق
  dynamic-route: عرض لتوجيهات ديناميكية
  hi: مرحبا {name}
  aka: معروف أيضا تحت مسمى
  whats-your-name: ما إسمك؟
not-found: صفحة غير موجودة


================================================
FILE: locales/de.yml
================================================
button:
  about: Über
  back: Zurück
  go: Los
  home: Startseite
  toggle_dark: Dunkelmodus umschalten
  toggle_langs: Sprachen ändern
intro:
  desc: Vite Startvorlage mit Vorlieben
  dynamic-route: Demo einer dynamischen Route
  hi: Hi, {name}!
  aka: Auch bekannt als
  whats-your-name: Wie heißt du?
not-found: Nicht gefunden


================================================
FILE: locales/en.yml
================================================
button:
  about: About
  back: Back
  go: GO
  home: Home
  toggle_dark: Toggle dark mode
  toggle_langs: Change languages
intro:
  desc: Opinionated Vite Starter Template
  dynamic-route: Demo of dynamic route
  hi: Hi, {name}!
  aka: Also known as
  whats-your-name: What's your name?
not-found: Not found


================================================
FILE: locales/es.yml
================================================
button:
  about: Acerca de
  back: Atrás
  go: Ir
  home: Inicio
  toggle_dark: Alternar modo oscuro
  toggle_langs: Cambiar idiomas
intro:
  desc: Plantilla de Inicio de Vite Dogmática
  dynamic-route: Demo de ruta dinámica
  hi: ¡Hola, {name}!
  aka: También conocido como
  whats-your-name: ¿Cómo te llamas?
not-found: No se ha encontrado


================================================
FILE: locales/fr.yml
================================================
button:
  about: À propos
  back: Retour
  go: Essayer
  home: Accueil
  toggle_dark: Basculer en mode sombre
  toggle_langs: Changer de langue
intro:
  desc: Exemple d'application Vite
  dynamic-route: Démo de route dynamique
  hi: Salut, {name}!
  aka: Aussi connu sous le nom de
  whats-your-name: Comment t'appelles-tu ?
not-found: Page non trouvée


================================================
FILE: locales/id.yml
================================================
button:
  about: Tentang
  back: Kembali
  go: Pergi
  home: Beranda
  toggle_dark: Ubah ke mode gelap
  toggle_langs: Ubah bahasa
intro:
  desc: Template awal vite
  dynamic-route: Contoh rute dinamik
  hi: Halo, {name}!
  aka: Juga diketahui sebagai
  whats-your-name: Siapa nama anda?
not-found: Tidak ditemukan


================================================
FILE: locales/it.yml
================================================
button:
  about: Su di me
  back: Indietro
  go: Vai
  home: Home
  toggle_dark: Attiva/disattiva modalità scura
  toggle_langs: Cambia lingua
intro:
  desc: Modello per una Applicazione Vite
  dynamic-route: Demo di rotta dinamica
  hi: Ciao, {name}!
  whats-your-name: Come ti chiami?
not-found: Non trovato


================================================
FILE: locales/ja.yml
================================================
button:
  about: これは?
  back: 戻る
  go: 進む
  home: ホーム
  toggle_dark: ダークモード切り替え
  toggle_langs: 言語切り替え
intro:
  desc: 固執された Vite スターターテンプレート
  dynamic-route: 動的ルートのデモ
  hi: こんにちは、{name}!
  whats-your-name: 君の名は。
not-found: 見つかりませんでした


================================================
FILE: locales/ka.yml
================================================
button:
  about: შესახებ
  back: უკან
  go: დაწყება
  home: მთავარი
  toggle_dark: გადართე მუქი რეჟიმი
  toggle_langs: ენის შეცვლა
intro:
  desc: Opinionated Vite Starter Template
  dynamic-route: დინამიური როუტინგის დემო
  hi: გამარჯობა, {name}!
  aka: ასევე ცნობილი როგორც
  whats-your-name: რა გქვია?
not-found: ვერ მოიძებნა


================================================
FILE: locales/ko.yml
================================================
button:
  about: 소개
  back: 뒤로가기
  go: 이동
  home: 홈
  toggle_dark: 다크모드 토글
  toggle_langs: 언어 변경
intro:
  desc: Vite 애플리케이션 템플릿
  dynamic-route: 다이나믹 라우트 데모
  hi: 안녕, {name}!
  whats-your-name: 이름이 뭐예요?
not-found: 찾을 수 없습니다


================================================
FILE: locales/pl.yml
================================================
button:
  about: O nas
  back: Wróć
  go: WEJDŹ
  home: Strona główna
  toggle_dark: Ustaw tryb nocny
  toggle_langs: Zmień język
intro:
  desc: Opiniowany szablon startowy Vite
  dynamic-route: Demonstracja dynamicznego route
  hi: Cześć, {name}!
  aka: Znany też jako
  whats-your-name: Jak masz na imię?
not-found: Nie znaleziono


================================================
FILE: locales/pt-BR.yml
================================================
button:
  about: Sobre
  back: Voltar
  go: Ir
  home: Início
  toggle_dark: Alternar modo escuro
  toggle_langs: Mudar de idioma
intro:
  desc: Modelo Opinativo de Partida de Vite
  dynamic-route: Demonstração de rota dinâmica
  hi: Olá, {name}!
  aka: Também conhecido como
  whats-your-name: Qual é o seu nome?
not-found: Não encontrado


================================================
FILE: locales/ru.yml
================================================
button:
  about: О шаблоне
  back: Назад
  go: Перейти
  home: Главная
  toggle_dark: Включить темный режим
  toggle_langs: Сменить язык
intro:
  desc: Самостоятельный начальный шаблон Vite
  dynamic-route: Демо динамического маршрута
  hi: Привет, {name}!
  whats-your-name: Как тебя зовут?
not-found: Не найден


================================================
FILE: locales/tr.yml
================================================
button:
  about: Hakkımda
  back: Geri
  go: İLERİ
  home: Anasayfa
  toggle_dark: Karanlık modu değiştir
  toggle_langs: Dilleri değiştir
intro:
  desc: Görüşlü Vite Başlangıç Şablonu
  dynamic-route: Dinamik rota demosu
  hi: Merhaba, {name}!
  aka: Ayrıca şöyle bilinir
  whats-your-name: Adınız nedir?
not-found: Bulunamadı


================================================
FILE: locales/uk.yml
================================================
button:
  about: Про шаблон
  back: Назад
  go: Перейти
  home: Головна
  toggle_dark: Переключити темний режим
  toggle_langs: Змінити мову
intro:
  desc: Самостійний початковий шаблон Vite
  dynamic-route: Демо динамічного маршруту
  hi: Привіт, {name}!
  whats-your-name: Як тебе звати?
not-found: Не знайдено


================================================
FILE: locales/uz.yml
================================================
button:
  about: Haqida
  back: Orqaga
  go: Kettik
  home: Bosh sahifa
  toggle_dark: Qorong‘i rejimga o‘tish
  toggle_langs: Tilni o‘zgartirish
intro:
  desc: O‘ylangan boshlang‘ich Vite shabloni
  dynamic-route: Dynamic route demo'si
  hi: Assalomu alaykum, {name}!
  aka: shuningdek
  whats-your-name: Ismingiz nima?
not-found: Topilmadi


================================================
FILE: locales/vi.yml
================================================
button:
  about: Về
  back: Quay lại
  go: Đi
  home: Khởi đầu
  toggle_dark: Chuyển đổi chế độ tối
  toggle_langs: Thay đổi ngôn ngữ
intro:
  desc: Ý kiến cá nhân Vite Template để bắt đầu
  dynamic-route: Bản giới thiệu về dynamic route
  hi: Hi, {name}!
  whats-your-name: Tên bạn là gì?
not-found: Không tìm thấy


================================================
FILE: locales/zh-CN.yml
================================================
button:
  about: 关于
  back: 返回
  go: 确定
  home: 首页
  toggle_dark: 切换深色模式
  toggle_langs: 切换语言
intro:
  desc: 固执己见的 Vite 项目模板
  dynamic-route: 动态路由演示
  hi: 你好,{name}
  aka: 也叫
  whats-your-name: 输入你的名字
not-found: 未找到页面


================================================
FILE: netlify.toml
================================================
[build]
publish = "dist"
command = "pnpm run build"

[build.environment]
NODE_VERSION = "22"

[[redirects]]
from = "/*"
to = "/index.html"
status = 200

[[headers]]
for = "/manifest.webmanifest"

[headers.values]
Content-Type = "application/manifest+json"


================================================
FILE: package.json
================================================
{
  "type": "module",
  "private": true,
  "packageManager": "pnpm@10.30.2",
  "scripts": {
    "build": "vite-ssg build",
    "dev": "vite --port 3333 --open",
    "lint": "eslint .",
    "preview": "vite preview",
    "preview-https": "serve dist",
    "test": "vitest",
    "test:e2e": "cypress open",
    "test:unit": "vitest",
    "typecheck": "vue-tsc --noEmit",
    "up": "taze major -I",
    "postinstall": "npx simple-git-hooks",
    "sizecheck": "npx vite-bundle-visualizer"
  },
  "dependencies": {
    "@unhead/vue": "catalog:frontend",
    "@unocss/reset": "catalog:frontend",
    "@vueuse/core": "catalog:frontend",
    "nprogress": "catalog:frontend",
    "pinia": "catalog:frontend",
    "vue": "catalog:frontend",
    "vue-i18n": "catalog:frontend",
    "vue-router": "catalog:frontend"
  },
  "devDependencies": {
    "@antfu/eslint-config": "catalog:dev",
    "@iconify-json/carbon": "catalog:dev",
    "@intlify/unplugin-vue-i18n": "catalog:build",
    "@shikijs/markdown-it": "catalog:build",
    "@types/markdown-it-link-attributes": "catalog:types",
    "@types/nprogress": "catalog:types",
    "@unocss/eslint-config": "catalog:build",
    "@vitejs/plugin-vue": "catalog:build",
    "@vue-macros/volar": "catalog:dev",
    "@vue/test-utils": "catalog:dev",
    "beasties": "catalog:build",
    "cypress": "catalog:dev",
    "cypress-vite": "catalog:dev",
    "eslint": "catalog:dev",
    "eslint-plugin-cypress": "catalog:dev",
    "eslint-plugin-format": "catalog:dev",
    "https-localhost": "catalog:dev",
    "lint-staged": "catalog:dev",
    "markdown-it-link-attributes": "catalog:build",
    "rollup": "catalog:build",
    "shiki": "catalog:build",
    "simple-git-hooks": "catalog:dev",
    "taze": "catalog:dev",
    "typescript": "catalog:dev",
    "unocss": "catalog:build",
    "unplugin-auto-import": "catalog:build",
    "unplugin-vue-components": "catalog:build",
    "unplugin-vue-macros": "catalog:build",
    "unplugin-vue-markdown": "catalog:build",
    "vite": "catalog:build",
    "vite-bundle-visualizer": "catalog:build",
    "vite-plugin-inspect": "catalog:build",
    "vite-plugin-pwa": "catalog:build",
    "vite-plugin-vue-devtools": "catalog:build",
    "vite-plugin-vue-layouts": "catalog:build",
    "vite-ssg": "catalog:build",
    "vite-ssg-sitemap": "catalog:build",
    "vitest": "catalog:dev",
    "vue-tsc": "catalog:dev"
  },
  "resolutions": {
    "unplugin": "catalog:build",
    "vite": "catalog:build",
    "vite-plugin-inspect": "catalog:build"
  },
  "simple-git-hooks": {
    "pre-commit": "pnpm lint-staged"
  },
  "lint-staged": {
    "*": "eslint --fix"
  }
}


================================================
FILE: pnpm-workspace.yaml
================================================
shellEmulator: true

trustPolicy: no-downgrade

packages: []

catalogs:

  build:
    '@intlify/unplugin-vue-i18n': ^11.0.7
    '@shikijs/markdown-it': ^3.23.0
    '@unocss/eslint-config': ^66.6.1
    '@vitejs/plugin-vue': ^6.0.4
    beasties: ^0.4.1
    markdown-it-link-attributes: ^4.0.1
    rollup: ^4.59.0
    shiki: ^3.23.0
    unocss: ^66.6.1
    unplugin: ^2.3.11
    unplugin-auto-import: ^21.0.0
    unplugin-vue-components: ^31.0.0
    unplugin-vue-macros: ^2.14.5
    unplugin-vue-markdown: ^29.2.0
    vite: ^7.3.1
    vite-bundle-visualizer: ^1.2.1
    vite-plugin-inspect: ^11.3.3
    vite-plugin-pwa: ^1.2.0
    vite-plugin-vue-devtools: ^8.0.6
    vite-plugin-vue-layouts: ^0.11.0
    vite-ssg: ^28.3.0
    vite-ssg-sitemap: ^0.10.0

  dev:
    '@antfu/eslint-config': ^7.6.1
    '@iconify-json/carbon': ^1.2.18
    '@vue-macros/volar': ^3.1.2
    '@vue/test-utils': ^2.4.6
    cypress: ^15.10.0
    cypress-vite: ^1.8.0
    eslint: ^10.0.2
    eslint-plugin-cypress: ^6.1.0
    eslint-plugin-format: ^2.0.1
    https-localhost: ^4.7.1
    lint-staged: ^16.2.7
    simple-git-hooks: ^2.13.1
    taze: ^19.9.2
    typescript: ^5.8.2
    vitest: ^4.0.18
    vue-tsc: ^3.2.5

  frontend:
    '@unhead/vue': ^2.1.7
    '@unocss/reset': ^66.6.1
    '@vueuse/core': ^14.2.1
    nprogress: ^0.2.0
    pinia: ^3.0.4
    vue: ^3.5.29
    vue-i18n: ^11.2.8
    vue-router: ^5.0.3

  types:
    '@types/markdown-it-link-attributes': ^3.0.5
    '@types/nprogress': ^0.2.3

onlyBuiltDependencies:
  - cypress
  - esbuild
  - simple-git-hooks


================================================
FILE: public/_headers
================================================
/assets/*
  cache-control: max-age=31536000
  cache-control: immutable


================================================
FILE: src/App.vue
================================================
<script setup lang="ts">
// https://github.com/vueuse/head
// you can use this to manipulate the document head in any components,
// they will be rendered correctly in the html results with vite-ssg
useHead({
  title: 'Vitesse',
  meta: [
    {
      name: 'description',
      content: 'Opinionated Vite Starter Template',
    },
    {
      name: 'theme-color',
      content: () => isDark.value ? '#00aba9' : '#ffffff',
    },
  ],
  link: [
    {
      rel: 'icon',
      type: 'image/svg+xml',
      href: () => preferredDark.value ? '/favicon-dark.svg' : '/favicon.svg',
    },
  ],
})
</script>

<template>
  <RouterView />
</template>


================================================
FILE: src/auto-imports.d.ts
================================================
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
// biome-ignore lint: disable
export {}
declare global {
  const EffectScope: typeof import('vue').EffectScope
  const asyncComputed: typeof import('@vueuse/core').asyncComputed
  const autoResetRef: typeof import('@vueuse/core').autoResetRef
  const computed: typeof import('vue').computed
  const computedAsync: typeof import('@vueuse/core').computedAsync
  const computedEager: typeof import('@vueuse/core').computedEager
  const computedInject: typeof import('@vueuse/core').computedInject
  const computedWithControl: typeof import('@vueuse/core').computedWithControl
  const controlledComputed: typeof import('@vueuse/core').controlledComputed
  const controlledRef: typeof import('@vueuse/core').controlledRef
  const createApp: typeof import('vue').createApp
  const createEventHook: typeof import('@vueuse/core').createEventHook
  const createGlobalState: typeof import('@vueuse/core').createGlobalState
  const createInjectionState: typeof import('@vueuse/core').createInjectionState
  const createReactiveFn: typeof import('@vueuse/core').createReactiveFn
  const createRef: typeof import('@vueuse/core').createRef
  const createReusableTemplate: typeof import('@vueuse/core').createReusableTemplate
  const createSharedComposable: typeof import('@vueuse/core').createSharedComposable
  const createTemplatePromise: typeof import('@vueuse/core').createTemplatePromise
  const createUnrefFn: typeof import('@vueuse/core').createUnrefFn
  const customRef: typeof import('vue').customRef
  const debouncedRef: typeof import('@vueuse/core').debouncedRef
  const debouncedWatch: typeof import('@vueuse/core').debouncedWatch
  const defineAsyncComponent: typeof import('vue').defineAsyncComponent
  const defineComponent: typeof import('vue').defineComponent
  const definePage: typeof import('vue-router/experimental').definePage
  const eagerComputed: typeof import('@vueuse/core').eagerComputed
  const effectScope: typeof import('vue').effectScope
  const extendRef: typeof import('@vueuse/core').extendRef
  const getCurrentInstance: typeof import('vue').getCurrentInstance
  const getCurrentScope: typeof import('vue').getCurrentScope
  const getCurrentWatcher: typeof import('vue').getCurrentWatcher
  const h: typeof import('vue').h
  const ignorableWatch: typeof import('@vueuse/core').ignorableWatch
  const inject: typeof import('vue').inject
  const injectHead: typeof import('@unhead/vue').injectHead
  const injectLocal: typeof import('@vueuse/core').injectLocal
  const isDark: typeof import('./composables/dark').isDark
  const isDefined: typeof import('@vueuse/core').isDefined
  const isProxy: typeof import('vue').isProxy
  const isReactive: typeof import('vue').isReactive
  const isReadonly: typeof import('vue').isReadonly
  const isRef: typeof import('vue').isRef
  const isShallow: typeof import('vue').isShallow
  const makeDestructurable: typeof import('@vueuse/core').makeDestructurable
  const markRaw: typeof import('vue').markRaw
  const nextTick: typeof import('vue').nextTick
  const onActivated: typeof import('vue').onActivated
  const onBeforeMount: typeof import('vue').onBeforeMount
  const onBeforeRouteLeave: typeof import('vue-router').onBeforeRouteLeave
  const onBeforeRouteUpdate: typeof import('vue-router').onBeforeRouteUpdate
  const onBeforeUnmount: typeof import('vue').onBeforeUnmount
  const onBeforeUpdate: typeof import('vue').onBeforeUpdate
  const onClickOutside: typeof import('@vueuse/core').onClickOutside
  const onDeactivated: typeof import('vue').onDeactivated
  const onElementRemoval: typeof import('@vueuse/core').onElementRemoval
  const onErrorCaptured: typeof import('vue').onErrorCaptured
  const onKeyStroke: typeof import('@vueuse/core').onKeyStroke
  const onLongPress: typeof import('@vueuse/core').onLongPress
  const onMounted: typeof import('vue').onMounted
  const onRenderTracked: typeof import('vue').onRenderTracked
  const onRenderTriggered: typeof import('vue').onRenderTriggered
  const onScopeDispose: typeof import('vue').onScopeDispose
  const onServerPrefetch: typeof import('vue').onServerPrefetch
  const onStartTyping: typeof import('@vueuse/core').onStartTyping
  const onUnmounted: typeof import('vue').onUnmounted
  const onUpdated: typeof import('vue').onUpdated
  const onWatcherCleanup: typeof import('vue').onWatcherCleanup
  const pausableWatch: typeof import('@vueuse/core').pausableWatch
  const preferredDark: typeof import('./composables/dark').preferredDark
  const provide: typeof import('vue').provide
  const provideLocal: typeof import('@vueuse/core').provideLocal
  const reactify: typeof import('@vueuse/core').reactify
  const reactifyObject: typeof import('@vueuse/core').reactifyObject
  const reactive: typeof import('vue').reactive
  const reactiveComputed: typeof import('@vueuse/core').reactiveComputed
  const reactiveOmit: typeof import('@vueuse/core').reactiveOmit
  const reactivePick: typeof import('@vueuse/core').reactivePick
  const readonly: typeof import('vue').readonly
  const ref: typeof import('vue').ref
  const refAutoReset: typeof import('@vueuse/core').refAutoReset
  const refDebounced: typeof import('@vueuse/core').refDebounced
  const refDefault: typeof import('@vueuse/core').refDefault
  const refManualReset: typeof import('@vueuse/core').refManualReset
  const refThrottled: typeof import('@vueuse/core').refThrottled
  const refWithControl: typeof import('@vueuse/core').refWithControl
  const resolveComponent: typeof import('vue').resolveComponent
  const resolveRef: typeof import('@vueuse/core').resolveRef
  const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
  const shallowReactive: typeof import('vue').shallowReactive
  const shallowReadonly: typeof import('vue').shallowReadonly
  const shallowRef: typeof import('vue').shallowRef
  const syncRef: typeof import('@vueuse/core').syncRef
  const syncRefs: typeof import('@vueuse/core').syncRefs
  const templateRef: typeof import('@vueuse/core').templateRef
  const throttledRef: typeof import('@vueuse/core').throttledRef
  const throttledWatch: typeof import('@vueuse/core').throttledWatch
  const toRaw: typeof import('vue').toRaw
  const toReactive: typeof import('@vueuse/core').toReactive
  const toRef: typeof import('vue').toRef
  const toRefs: typeof import('vue').toRefs
  const toValue: typeof import('vue').toValue
  const toggleDark: typeof import('./composables/dark').toggleDark
  const triggerRef: typeof import('vue').triggerRef
  const tryOnBeforeMount: typeof import('@vueuse/core').tryOnBeforeMount
  const tryOnBeforeUnmount: typeof import('@vueuse/core').tryOnBeforeUnmount
  const tryOnMounted: typeof import('@vueuse/core').tryOnMounted
  const tryOnScopeDispose: typeof import('@vueuse/core').tryOnScopeDispose
  const tryOnUnmounted: typeof import('@vueuse/core').tryOnUnmounted
  const unref: typeof import('vue').unref
  const unrefElement: typeof import('@vueuse/core').unrefElement
  const until: typeof import('@vueuse/core').until
  const useActiveElement: typeof import('@vueuse/core').useActiveElement
  const useAnimate: typeof import('@vueuse/core').useAnimate
  const useArrayDifference: typeof import('@vueuse/core').useArrayDifference
  const useArrayEvery: typeof import('@vueuse/core').useArrayEvery
  const useArrayFilter: typeof import('@vueuse/core').useArrayFilter
  const useArrayFind: typeof import('@vueuse/core').useArrayFind
  const useArrayFindIndex: typeof import('@vueuse/core').useArrayFindIndex
  const useArrayFindLast: typeof import('@vueuse/core').useArrayFindLast
  const useArrayIncludes: typeof import('@vueuse/core').useArrayIncludes
  const useArrayJoin: typeof import('@vueuse/core').useArrayJoin
  const useArrayMap: typeof import('@vueuse/core').useArrayMap
  const useArrayReduce: typeof import('@vueuse/core').useArrayReduce
  const useArraySome: typeof import('@vueuse/core').useArraySome
  const useArrayUnique: typeof import('@vueuse/core').useArrayUnique
  const useAsyncQueue: typeof import('@vueuse/core').useAsyncQueue
  const useAsyncState: typeof import('@vueuse/core').useAsyncState
  const useAttrs: typeof import('vue').useAttrs
  const useBase64: typeof import('@vueuse/core').useBase64
  const useBattery: typeof import('@vueuse/core').useBattery
  const useBluetooth: typeof import('@vueuse/core').useBluetooth
  const useBreakpoints: typeof import('@vueuse/core').useBreakpoints
  const useBroadcastChannel: typeof import('@vueuse/core').useBroadcastChannel
  const useBrowserLocation: typeof import('@vueuse/core').useBrowserLocation
  const useCached: typeof import('@vueuse/core').useCached
  const useClipboard: typeof import('@vueuse/core').useClipboard
  const useClipboardItems: typeof import('@vueuse/core').useClipboardItems
  const useCloned: typeof import('@vueuse/core').useCloned
  const useColorMode: typeof import('@vueuse/core').useColorMode
  const useConfirmDialog: typeof import('@vueuse/core').useConfirmDialog
  const useCountdown: typeof import('@vueuse/core').useCountdown
  const useCounter: typeof import('@vueuse/core').useCounter
  const useCssModule: typeof import('vue').useCssModule
  const useCssSupports: typeof import('@vueuse/core').useCssSupports
  const useCssVar: typeof import('@vueuse/core').useCssVar
  const useCssVars: typeof import('vue').useCssVars
  const useCurrentElement: typeof import('@vueuse/core').useCurrentElement
  const useCycleList: typeof import('@vueuse/core').useCycleList
  const useDark: typeof import('@vueuse/core').useDark
  const useDateFormat: typeof import('@vueuse/core').useDateFormat
  const useDebounce: typeof import('@vueuse/core').useDebounce
  const useDebounceFn: typeof import('@vueuse/core').useDebounceFn
  const useDebouncedRefHistory: typeof import('@vueuse/core').useDebouncedRefHistory
  const useDeviceMotion: typeof import('@vueuse/core').useDeviceMotion
  const useDeviceOrientation: typeof import('@vueuse/core').useDeviceOrientation
  const useDevicePixelRatio: typeof import('@vueuse/core').useDevicePixelRatio
  const useDevicesList: typeof import('@vueuse/core').useDevicesList
  const useDisplayMedia: typeof import('@vueuse/core').useDisplayMedia
  const useDocumentVisibility: typeof import('@vueuse/core').useDocumentVisibility
  const useDraggable: typeof import('@vueuse/core').useDraggable
  const useDropZone: typeof import('@vueuse/core').useDropZone
  const useElementBounding: typeof import('@vueuse/core').useElementBounding
  const useElementByPoint: typeof import('@vueuse/core').useElementByPoint
  const useElementHover: typeof import('@vueuse/core').useElementHover
  const useElementSize: typeof import('@vueuse/core').useElementSize
  const useElementVisibility: typeof import('@vueuse/core').useElementVisibility
  const useEventBus: typeof import('@vueuse/core').useEventBus
  const useEventListener: typeof import('@vueuse/core').useEventListener
  const useEventSource: typeof import('@vueuse/core').useEventSource
  const useEyeDropper: typeof import('@vueuse/core').useEyeDropper
  const useFavicon: typeof import('@vueuse/core').useFavicon
  const useFetch: typeof import('@vueuse/core').useFetch
  const useFileDialog: typeof import('@vueuse/core').useFileDialog
  const useFileSystemAccess: typeof import('@vueuse/core').useFileSystemAccess
  const useFocus: typeof import('@vueuse/core').useFocus
  const useFocusWithin: typeof import('@vueuse/core').useFocusWithin
  const useFps: typeof import('@vueuse/core').useFps
  const useFullscreen: typeof import('@vueuse/core').useFullscreen
  const useGamepad: typeof import('@vueuse/core').useGamepad
  const useGeolocation: typeof import('@vueuse/core').useGeolocation
  const useHead: typeof import('@unhead/vue').useHead
  const useHeadSafe: typeof import('@unhead/vue').useHeadSafe
  const useI18n: typeof import('vue-i18n').useI18n
  const useId: typeof import('vue').useId
  const useIdle: typeof import('@vueuse/core').useIdle
  const useImage: typeof import('@vueuse/core').useImage
  const useInfiniteScroll: typeof import('@vueuse/core').useInfiniteScroll
  const useIntersectionObserver: typeof import('@vueuse/core').useIntersectionObserver
  const useInterval: typeof import('@vueuse/core').useInterval
  const useIntervalFn: typeof import('@vueuse/core').useIntervalFn
  const useKeyModifier: typeof import('@vueuse/core').useKeyModifier
  const useLastChanged: typeof import('@vueuse/core').useLastChanged
  const useLink: typeof import('vue-router/auto').useLink
  const useLocalStorage: typeof import('@vueuse/core').useLocalStorage
  const useMagicKeys: typeof import('@vueuse/core').useMagicKeys
  const useManualRefHistory: typeof import('@vueuse/core').useManualRefHistory
  const useMediaControls: typeof import('@vueuse/core').useMediaControls
  const useMediaQuery: typeof import('@vueuse/core').useMediaQuery
  const useMemoize: typeof import('@vueuse/core').useMemoize
  const useMemory: typeof import('@vueuse/core').useMemory
  const useModel: typeof import('vue').useModel
  const useMounted: typeof import('@vueuse/core').useMounted
  const useMouse: typeof import('@vueuse/core').useMouse
  const useMouseInElement: typeof import('@vueuse/core').useMouseInElement
  const useMousePressed: typeof import('@vueuse/core').useMousePressed
  const useMutationObserver: typeof import('@vueuse/core').useMutationObserver
  const useNavigatorLanguage: typeof import('@vueuse/core').useNavigatorLanguage
  const useNetwork: typeof import('@vueuse/core').useNetwork
  const useNow: typeof import('@vueuse/core').useNow
  const useObjectUrl: typeof import('@vueuse/core').useObjectUrl
  const useOffsetPagination: typeof import('@vueuse/core').useOffsetPagination
  const useOnline: typeof import('@vueuse/core').useOnline
  const usePageLeave: typeof import('@vueuse/core').usePageLeave
  const useParallax: typeof import('@vueuse/core').useParallax
  const useParentElement: typeof import('@vueuse/core').useParentElement
  const usePerformanceObserver: typeof import('@vueuse/core').usePerformanceObserver
  const usePermission: typeof import('@vueuse/core').usePermission
  const usePointer: typeof import('@vueuse/core').usePointer
  const usePointerLock: typeof import('@vueuse/core').usePointerLock
  const usePointerSwipe: typeof import('@vueuse/core').usePointerSwipe
  const usePreferredColorScheme: typeof import('@vueuse/core').usePreferredColorScheme
  const usePreferredContrast: typeof import('@vueuse/core').usePreferredContrast
  const usePreferredDark: typeof import('@vueuse/core').usePreferredDark
  const usePreferredLanguages: typeof import('@vueuse/core').usePreferredLanguages
  const usePreferredReducedMotion: typeof import('@vueuse/core').usePreferredReducedMotion
  const usePreferredReducedTransparency: typeof import('@vueuse/core').usePreferredReducedTransparency
  const usePrevious: typeof import('@vueuse/core').usePrevious
  const useRafFn: typeof import('@vueuse/core').useRafFn
  const useRefHistory: typeof import('@vueuse/core').useRefHistory
  const useResizeObserver: typeof import('@vueuse/core').useResizeObserver
  const useRoute: typeof import('vue-router').useRoute
  const useRouter: typeof import('vue-router').useRouter
  const useSSRWidth: typeof import('@vueuse/core').useSSRWidth
  const useScreenOrientation: typeof import('@vueuse/core').useScreenOrientation
  const useScreenSafeArea: typeof import('@vueuse/core').useScreenSafeArea
  const useScriptTag: typeof import('@vueuse/core').useScriptTag
  const useScroll: typeof import('@vueuse/core').useScroll
  const useScrollLock: typeof import('@vueuse/core').useScrollLock
  const useSeoMeta: typeof import('@unhead/vue').useSeoMeta
  const useServerHead: typeof import('@unhead/vue').useServerHead
  const useServerHeadSafe: typeof import('@unhead/vue').useServerHeadSafe
  const useServerSeoMeta: typeof import('@unhead/vue').useServerSeoMeta
  const useSessionStorage: typeof import('@vueuse/core').useSessionStorage
  const useShare: typeof import('@vueuse/core').useShare
  const useSlots: typeof import('vue').useSlots
  const useSorted: typeof import('@vueuse/core').useSorted
  const useSpeechRecognition: typeof import('@vueuse/core').useSpeechRecognition
  const useSpeechSynthesis: typeof import('@vueuse/core').useSpeechSynthesis
  const useStepper: typeof import('@vueuse/core').useStepper
  const useStorage: typeof import('@vueuse/core').useStorage
  const useStorageAsync: typeof import('@vueuse/core').useStorageAsync
  const useStyleTag: typeof import('@vueuse/core').useStyleTag
  const useSupported: typeof import('@vueuse/core').useSupported
  const useSwipe: typeof import('@vueuse/core').useSwipe
  const useTemplateRef: typeof import('vue').useTemplateRef
  const useTemplateRefsList: typeof import('@vueuse/core').useTemplateRefsList
  const useTextDirection: typeof import('@vueuse/core').useTextDirection
  const useTextSelection: typeof import('@vueuse/core').useTextSelection
  const useTextareaAutosize: typeof import('@vueuse/core').useTextareaAutosize
  const useThrottle: typeof import('@vueuse/core').useThrottle
  const useThrottleFn: typeof import('@vueuse/core').useThrottleFn
  const useThrottledRefHistory: typeof import('@vueuse/core').useThrottledRefHistory
  const useTimeAgo: typeof import('@vueuse/core').useTimeAgo
  const useTimeAgoIntl: typeof import('@vueuse/core').useTimeAgoIntl
  const useTimeout: typeof import('@vueuse/core').useTimeout
  const useTimeoutFn: typeof import('@vueuse/core').useTimeoutFn
  const useTimeoutPoll: typeof import('@vueuse/core').useTimeoutPoll
  const useTimestamp: typeof import('@vueuse/core').useTimestamp
  const useTitle: typeof import('@vueuse/core').useTitle
  const useToNumber: typeof import('@vueuse/core').useToNumber
  const useToString: typeof import('@vueuse/core').useToString
  const useToggle: typeof import('@vueuse/core').useToggle
  const useTransition: typeof import('@vueuse/core').useTransition
  const useUrlSearchParams: typeof import('@vueuse/core').useUrlSearchParams
  const useUserMedia: typeof import('@vueuse/core').useUserMedia
  const useUserStore: typeof import('./stores/user').useUserStore
  const useVModel: typeof import('@vueuse/core').useVModel
  const useVModels: typeof import('@vueuse/core').useVModels
  const useVibrate: typeof import('@vueuse/core').useVibrate
  const useVirtualList: typeof import('@vueuse/core').useVirtualList
  const useWakeLock: typeof import('@vueuse/core').useWakeLock
  const useWebNotification: typeof import('@vueuse/core').useWebNotification
  const useWebSocket: typeof import('@vueuse/core').useWebSocket
  const useWebWorker: typeof import('@vueuse/core').useWebWorker
  const useWebWorkerFn: typeof import('@vueuse/core').useWebWorkerFn
  const useWindowFocus: typeof import('@vueuse/core').useWindowFocus
  const useWindowScroll: typeof import('@vueuse/core').useWindowScroll
  const useWindowSize: typeof import('@vueuse/core').useWindowSize
  const watch: typeof import('vue').watch
  const watchArray: typeof import('@vueuse/core').watchArray
  const watchAtMost: typeof import('@vueuse/core').watchAtMost
  const watchDebounced: typeof import('@vueuse/core').watchDebounced
  const watchDeep: typeof import('@vueuse/core').watchDeep
  const watchEffect: typeof import('vue').watchEffect
  const watchIgnorable: typeof import('@vueuse/core').watchIgnorable
  const watchImmediate: typeof import('@vueuse/core').watchImmediate
  const watchOnce: typeof import('@vueuse/core').watchOnce
  const watchPausable: typeof import('@vueuse/core').watchPausable
  const watchPostEffect: typeof import('vue').watchPostEffect
  const watchSyncEffect: typeof import('vue').watchSyncEffect
  const watchThrottled: typeof import('@vueuse/core').watchThrottled
  const watchTriggerable: typeof import('@vueuse/core').watchTriggerable
  const watchWithFilter: typeof import('@vueuse/core').watchWithFilter
  const whenever: typeof import('@vueuse/core').whenever
}
// for type re-export
declare global {
  // @ts-ignore
  export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, ShallowRef, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
  import('vue')
}

// for vue template auto import
import { UnwrapRef } from 'vue'
declare module 'vue' {
  interface GlobalComponents {}
  interface ComponentCustomProperties {
    readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
    readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
    readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
    readonly computed: UnwrapRef<typeof import('vue')['computed']>
    readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']>
    readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']>
    readonly computedInject: UnwrapRef<typeof import('@vueuse/core')['computedInject']>
    readonly computedWithControl: UnwrapRef<typeof import('@vueuse/core')['computedWithControl']>
    readonly controlledComputed: UnwrapRef<typeof import('@vueuse/core')['controlledComputed']>
    readonly controlledRef: UnwrapRef<typeof import('@vueuse/core')['controlledRef']>
    readonly createApp: UnwrapRef<typeof import('vue')['createApp']>
    readonly createEventHook: UnwrapRef<typeof import('@vueuse/core')['createEventHook']>
    readonly createGlobalState: UnwrapRef<typeof import('@vueuse/core')['createGlobalState']>
    readonly createInjectionState: UnwrapRef<typeof import('@vueuse/core')['createInjectionState']>
    readonly createReactiveFn: UnwrapRef<typeof import('@vueuse/core')['createReactiveFn']>
    readonly createRef: UnwrapRef<typeof import('@vueuse/core')['createRef']>
    readonly createReusableTemplate: UnwrapRef<typeof import('@vueuse/core')['createReusableTemplate']>
    readonly createSharedComposable: UnwrapRef<typeof import('@vueuse/core')['createSharedComposable']>
    readonly createTemplatePromise: UnwrapRef<typeof import('@vueuse/core')['createTemplatePromise']>
    readonly createUnrefFn: UnwrapRef<typeof import('@vueuse/core')['createUnrefFn']>
    readonly customRef: UnwrapRef<typeof import('vue')['customRef']>
    readonly debouncedRef: UnwrapRef<typeof import('@vueuse/core')['debouncedRef']>
    readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']>
    readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
    readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
    readonly definePage: UnwrapRef<typeof import('vue-router/experimental')['definePage']>
    readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
    readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
    readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
    readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
    readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
    readonly getCurrentWatcher: UnwrapRef<typeof import('vue')['getCurrentWatcher']>
    readonly h: UnwrapRef<typeof import('vue')['h']>
    readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
    readonly inject: UnwrapRef<typeof import('vue')['inject']>
    readonly injectHead: UnwrapRef<typeof import('@unhead/vue')['injectHead']>
    readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
    readonly isDark: UnwrapRef<typeof import('./composables/dark')['isDark']>
    readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
    readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
    readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
    readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
    readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
    readonly isShallow: UnwrapRef<typeof import('vue')['isShallow']>
    readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
    readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
    readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
    readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
    readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
    readonly onBeforeRouteLeave: UnwrapRef<typeof import('vue-router')['onBeforeRouteLeave']>
    readonly onBeforeRouteUpdate: UnwrapRef<typeof import('vue-router')['onBeforeRouteUpdate']>
    readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']>
    readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
    readonly onClickOutside: UnwrapRef<typeof import('@vueuse/core')['onClickOutside']>
    readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']>
    readonly onElementRemoval: UnwrapRef<typeof import('@vueuse/core')['onElementRemoval']>
    readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']>
    readonly onKeyStroke: UnwrapRef<typeof import('@vueuse/core')['onKeyStroke']>
    readonly onLongPress: UnwrapRef<typeof import('@vueuse/core')['onLongPress']>
    readonly onMounted: UnwrapRef<typeof import('vue')['onMounted']>
    readonly onRenderTracked: UnwrapRef<typeof import('vue')['onRenderTracked']>
    readonly onRenderTriggered: UnwrapRef<typeof import('vue')['onRenderTriggered']>
    readonly onScopeDispose: UnwrapRef<typeof import('vue')['onScopeDispose']>
    readonly onServerPrefetch: UnwrapRef<typeof import('vue')['onServerPrefetch']>
    readonly onStartTyping: UnwrapRef<typeof import('@vueuse/core')['onStartTyping']>
    readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
    readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
    readonly onWatcherCleanup: UnwrapRef<typeof import('vue')['onWatcherCleanup']>
    readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
    readonly preferredDark: UnwrapRef<typeof import('./composables/dark')['preferredDark']>
    readonly provide: UnwrapRef<typeof import('vue')['provide']>
    readonly provideLocal: UnwrapRef<typeof import('@vueuse/core')['provideLocal']>
    readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']>
    readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']>
    readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
    readonly reactiveComputed: UnwrapRef<typeof import('@vueuse/core')['reactiveComputed']>
    readonly reactiveOmit: UnwrapRef<typeof import('@vueuse/core')['reactiveOmit']>
    readonly reactivePick: UnwrapRef<typeof import('@vueuse/core')['reactivePick']>
    readonly readonly: UnwrapRef<typeof import('vue')['readonly']>
    readonly ref: UnwrapRef<typeof import('vue')['ref']>
    readonly refAutoReset: UnwrapRef<typeof import('@vueuse/core')['refAutoReset']>
    readonly refDebounced: UnwrapRef<typeof import('@vueuse/core')['refDebounced']>
    readonly refDefault: UnwrapRef<typeof import('@vueuse/core')['refDefault']>
    readonly refManualReset: UnwrapRef<typeof import('@vueuse/core')['refManualReset']>
    readonly refThrottled: UnwrapRef<typeof import('@vueuse/core')['refThrottled']>
    readonly refWithControl: UnwrapRef<typeof import('@vueuse/core')['refWithControl']>
    readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
    readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
    readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
    readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
    readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
    readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
    readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']>
    readonly templateRef: UnwrapRef<typeof import('@vueuse/core')['templateRef']>
    readonly throttledRef: UnwrapRef<typeof import('@vueuse/core')['throttledRef']>
    readonly throttledWatch: UnwrapRef<typeof import('@vueuse/core')['throttledWatch']>
    readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']>
    readonly toReactive: UnwrapRef<typeof import('@vueuse/core')['toReactive']>
    readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
    readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
    readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
    readonly toggleDark: UnwrapRef<typeof import('./composables/dark')['toggleDark']>
    readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
    readonly tryOnBeforeMount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeMount']>
    readonly tryOnBeforeUnmount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeUnmount']>
    readonly tryOnMounted: UnwrapRef<typeof import('@vueuse/core')['tryOnMounted']>
    readonly tryOnScopeDispose: UnwrapRef<typeof import('@vueuse/core')['tryOnScopeDispose']>
    readonly tryOnUnmounted: UnwrapRef<typeof import('@vueuse/core')['tryOnUnmounted']>
    readonly unref: UnwrapRef<typeof import('vue')['unref']>
    readonly unrefElement: UnwrapRef<typeof import('@vueuse/core')['unrefElement']>
    readonly until: UnwrapRef<typeof import('@vueuse/core')['until']>
    readonly useActiveElement: UnwrapRef<typeof import('@vueuse/core')['useActiveElement']>
    readonly useAnimate: UnwrapRef<typeof import('@vueuse/core')['useAnimate']>
    readonly useArrayDifference: UnwrapRef<typeof import('@vueuse/core')['useArrayDifference']>
    readonly useArrayEvery: UnwrapRef<typeof import('@vueuse/core')['useArrayEvery']>
    readonly useArrayFilter: UnwrapRef<typeof import('@vueuse/core')['useArrayFilter']>
    readonly useArrayFind: UnwrapRef<typeof import('@vueuse/core')['useArrayFind']>
    readonly useArrayFindIndex: UnwrapRef<typeof import('@vueuse/core')['useArrayFindIndex']>
    readonly useArrayFindLast: UnwrapRef<typeof import('@vueuse/core')['useArrayFindLast']>
    readonly useArrayIncludes: UnwrapRef<typeof import('@vueuse/core')['useArrayIncludes']>
    readonly useArrayJoin: UnwrapRef<typeof import('@vueuse/core')['useArrayJoin']>
    readonly useArrayMap: UnwrapRef<typeof import('@vueuse/core')['useArrayMap']>
    readonly useArrayReduce: UnwrapRef<typeof import('@vueuse/core')['useArrayReduce']>
    readonly useArraySome: UnwrapRef<typeof import('@vueuse/core')['useArraySome']>
    readonly useArrayUnique: UnwrapRef<typeof import('@vueuse/core')['useArrayUnique']>
    readonly useAsyncQueue: UnwrapRef<typeof import('@vueuse/core')['useAsyncQueue']>
    readonly useAsyncState: UnwrapRef<typeof import('@vueuse/core')['useAsyncState']>
    readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']>
    readonly useBase64: UnwrapRef<typeof import('@vueuse/core')['useBase64']>
    readonly useBattery: UnwrapRef<typeof import('@vueuse/core')['useBattery']>
    readonly useBluetooth: UnwrapRef<typeof import('@vueuse/core')['useBluetooth']>
    readonly useBreakpoints: UnwrapRef<typeof import('@vueuse/core')['useBreakpoints']>
    readonly useBroadcastChannel: UnwrapRef<typeof import('@vueuse/core')['useBroadcastChannel']>
    readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']>
    readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']>
    readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
    readonly useClipboardItems: UnwrapRef<typeof import('@vueuse/core')['useClipboardItems']>
    readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
    readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
    readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
    readonly useCountdown: UnwrapRef<typeof import('@vueuse/core')['useCountdown']>
    readonly useCounter: UnwrapRef<typeof import('@vueuse/core')['useCounter']>
    readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
    readonly useCssSupports: UnwrapRef<typeof import('@vueuse/core')['useCssSupports']>
    readonly useCssVar: UnwrapRef<typeof import('@vueuse/core')['useCssVar']>
    readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
    readonly useCurrentElement: UnwrapRef<typeof import('@vueuse/core')['useCurrentElement']>
    readonly useCycleList: UnwrapRef<typeof import('@vueuse/core')['useCycleList']>
    readonly useDark: UnwrapRef<typeof import('@vueuse/core')['useDark']>
    readonly useDateFormat: UnwrapRef<typeof import('@vueuse/core')['useDateFormat']>
    readonly useDebounce: UnwrapRef<typeof import('@vueuse/core')['useDebounce']>
    readonly useDebounceFn: UnwrapRef<typeof import('@vueuse/core')['useDebounceFn']>
    readonly useDebouncedRefHistory: UnwrapRef<typeof import('@vueuse/core')['useDebouncedRefHistory']>
    readonly useDeviceMotion: UnwrapRef<typeof import('@vueuse/core')['useDeviceMotion']>
    readonly useDeviceOrientation: UnwrapRef<typeof import('@vueuse/core')['useDeviceOrientation']>
    readonly useDevicePixelRatio: UnwrapRef<typeof import('@vueuse/core')['useDevicePixelRatio']>
    readonly useDevicesList: UnwrapRef<typeof import('@vueuse/core')['useDevicesList']>
    readonly useDisplayMedia: UnwrapRef<typeof import('@vueuse/core')['useDisplayMedia']>
    readonly useDocumentVisibility: UnwrapRef<typeof import('@vueuse/core')['useDocumentVisibility']>
    readonly useDraggable: UnwrapRef<typeof import('@vueuse/core')['useDraggable']>
    readonly useDropZone: UnwrapRef<typeof import('@vueuse/core')['useDropZone']>
    readonly useElementBounding: UnwrapRef<typeof import('@vueuse/core')['useElementBounding']>
    readonly useElementByPoint: UnwrapRef<typeof import('@vueuse/core')['useElementByPoint']>
    readonly useElementHover: UnwrapRef<typeof import('@vueuse/core')['useElementHover']>
    readonly useElementSize: UnwrapRef<typeof import('@vueuse/core')['useElementSize']>
    readonly useElementVisibility: UnwrapRef<typeof import('@vueuse/core')['useElementVisibility']>
    readonly useEventBus: UnwrapRef<typeof import('@vueuse/core')['useEventBus']>
    readonly useEventListener: UnwrapRef<typeof import('@vueuse/core')['useEventListener']>
    readonly useEventSource: UnwrapRef<typeof import('@vueuse/core')['useEventSource']>
    readonly useEyeDropper: UnwrapRef<typeof import('@vueuse/core')['useEyeDropper']>
    readonly useFavicon: UnwrapRef<typeof import('@vueuse/core')['useFavicon']>
    readonly useFetch: UnwrapRef<typeof import('@vueuse/core')['useFetch']>
    readonly useFileDialog: UnwrapRef<typeof import('@vueuse/core')['useFileDialog']>
    readonly useFileSystemAccess: UnwrapRef<typeof import('@vueuse/core')['useFileSystemAccess']>
    readonly useFocus: UnwrapRef<typeof import('@vueuse/core')['useFocus']>
    readonly useFocusWithin: UnwrapRef<typeof import('@vueuse/core')['useFocusWithin']>
    readonly useFps: UnwrapRef<typeof import('@vueuse/core')['useFps']>
    readonly useFullscreen: UnwrapRef<typeof import('@vueuse/core')['useFullscreen']>
    readonly useGamepad: UnwrapRef<typeof import('@vueuse/core')['useGamepad']>
    readonly useGeolocation: UnwrapRef<typeof import('@vueuse/core')['useGeolocation']>
    readonly useHead: UnwrapRef<typeof import('@unhead/vue')['useHead']>
    readonly useHeadSafe: UnwrapRef<typeof import('@unhead/vue')['useHeadSafe']>
    readonly useI18n: UnwrapRef<typeof import('vue-i18n')['useI18n']>
    readonly useId: UnwrapRef<typeof import('vue')['useId']>
    readonly useIdle: UnwrapRef<typeof import('@vueuse/core')['useIdle']>
    readonly useImage: UnwrapRef<typeof import('@vueuse/core')['useImage']>
    readonly useInfiniteScroll: UnwrapRef<typeof import('@vueuse/core')['useInfiniteScroll']>
    readonly useIntersectionObserver: UnwrapRef<typeof import('@vueuse/core')['useIntersectionObserver']>
    readonly useInterval: UnwrapRef<typeof import('@vueuse/core')['useInterval']>
    readonly useIntervalFn: UnwrapRef<typeof import('@vueuse/core')['useIntervalFn']>
    readonly useKeyModifier: UnwrapRef<typeof import('@vueuse/core')['useKeyModifier']>
    readonly useLastChanged: UnwrapRef<typeof import('@vueuse/core')['useLastChanged']>
    readonly useLink: UnwrapRef<typeof import('vue-router/auto')['useLink']>
    readonly useLocalStorage: UnwrapRef<typeof import('@vueuse/core')['useLocalStorage']>
    readonly useMagicKeys: UnwrapRef<typeof import('@vueuse/core')['useMagicKeys']>
    readonly useManualRefHistory: UnwrapRef<typeof import('@vueuse/core')['useManualRefHistory']>
    readonly useMediaControls: UnwrapRef<typeof import('@vueuse/core')['useMediaControls']>
    readonly useMediaQuery: UnwrapRef<typeof import('@vueuse/core')['useMediaQuery']>
    readonly useMemoize: UnwrapRef<typeof import('@vueuse/core')['useMemoize']>
    readonly useMemory: UnwrapRef<typeof import('@vueuse/core')['useMemory']>
    readonly useModel: UnwrapRef<typeof import('vue')['useModel']>
    readonly useMounted: UnwrapRef<typeof import('@vueuse/core')['useMounted']>
    readonly useMouse: UnwrapRef<typeof import('@vueuse/core')['useMouse']>
    readonly useMouseInElement: UnwrapRef<typeof import('@vueuse/core')['useMouseInElement']>
    readonly useMousePressed: UnwrapRef<typeof import('@vueuse/core')['useMousePressed']>
    readonly useMutationObserver: UnwrapRef<typeof import('@vueuse/core')['useMutationObserver']>
    readonly useNavigatorLanguage: UnwrapRef<typeof import('@vueuse/core')['useNavigatorLanguage']>
    readonly useNetwork: UnwrapRef<typeof import('@vueuse/core')['useNetwork']>
    readonly useNow: UnwrapRef<typeof import('@vueuse/core')['useNow']>
    readonly useObjectUrl: UnwrapRef<typeof import('@vueuse/core')['useObjectUrl']>
    readonly useOffsetPagination: UnwrapRef<typeof import('@vueuse/core')['useOffsetPagination']>
    readonly useOnline: UnwrapRef<typeof import('@vueuse/core')['useOnline']>
    readonly usePageLeave: UnwrapRef<typeof import('@vueuse/core')['usePageLeave']>
    readonly useParallax: UnwrapRef<typeof import('@vueuse/core')['useParallax']>
    readonly useParentElement: UnwrapRef<typeof import('@vueuse/core')['useParentElement']>
    readonly usePerformanceObserver: UnwrapRef<typeof import('@vueuse/core')['usePerformanceObserver']>
    readonly usePermission: UnwrapRef<typeof import('@vueuse/core')['usePermission']>
    readonly usePointer: UnwrapRef<typeof import('@vueuse/core')['usePointer']>
    readonly usePointerLock: UnwrapRef<typeof import('@vueuse/core')['usePointerLock']>
    readonly usePointerSwipe: UnwrapRef<typeof import('@vueuse/core')['usePointerSwipe']>
    readonly usePreferredColorScheme: UnwrapRef<typeof import('@vueuse/core')['usePreferredColorScheme']>
    readonly usePreferredContrast: UnwrapRef<typeof import('@vueuse/core')['usePreferredContrast']>
    readonly usePreferredDark: UnwrapRef<typeof import('@vueuse/core')['usePreferredDark']>
    readonly usePreferredLanguages: UnwrapRef<typeof import('@vueuse/core')['usePreferredLanguages']>
    readonly usePreferredReducedMotion: UnwrapRef<typeof import('@vueuse/core')['usePreferredReducedMotion']>
    readonly usePreferredReducedTransparency: UnwrapRef<typeof import('@vueuse/core')['usePreferredReducedTransparency']>
    readonly usePrevious: UnwrapRef<typeof import('@vueuse/core')['usePrevious']>
    readonly useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']>
    readonly useRefHistory: UnwrapRef<typeof import('@vueuse/core')['useRefHistory']>
    readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']>
    readonly useRoute: UnwrapRef<typeof import('vue-router')['useRoute']>
    readonly useRouter: UnwrapRef<typeof import('vue-router')['useRouter']>
    readonly useSSRWidth: UnwrapRef<typeof import('@vueuse/core')['useSSRWidth']>
    readonly useScreenOrientation: UnwrapRef<typeof import('@vueuse/core')['useScreenOrientation']>
    readonly useScreenSafeArea: UnwrapRef<typeof import('@vueuse/core')['useScreenSafeArea']>
    readonly useScriptTag: UnwrapRef<typeof import('@vueuse/core')['useScriptTag']>
    readonly useScroll: UnwrapRef<typeof import('@vueuse/core')['useScroll']>
    readonly useScrollLock: UnwrapRef<typeof import('@vueuse/core')['useScrollLock']>
    readonly useSeoMeta: UnwrapRef<typeof import('@unhead/vue')['useSeoMeta']>
    readonly useServerHead: UnwrapRef<typeof import('@unhead/vue')['useServerHead']>
    readonly useServerHeadSafe: UnwrapRef<typeof import('@unhead/vue')['useServerHeadSafe']>
    readonly useServerSeoMeta: UnwrapRef<typeof import('@unhead/vue')['useServerSeoMeta']>
    readonly useSessionStorage: UnwrapRef<typeof import('@vueuse/core')['useSessionStorage']>
    readonly useShare: UnwrapRef<typeof import('@vueuse/core')['useShare']>
    readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
    readonly useSorted: UnwrapRef<typeof import('@vueuse/core')['useSorted']>
    readonly useSpeechRecognition: UnwrapRef<typeof import('@vueuse/core')['useSpeechRecognition']>
    readonly useSpeechSynthesis: UnwrapRef<typeof import('@vueuse/core')['useSpeechSynthesis']>
    readonly useStepper: UnwrapRef<typeof import('@vueuse/core')['useStepper']>
    readonly useStorage: UnwrapRef<typeof import('@vueuse/core')['useStorage']>
    readonly useStorageAsync: UnwrapRef<typeof import('@vueuse/core')['useStorageAsync']>
    readonly useStyleTag: UnwrapRef<typeof import('@vueuse/core')['useStyleTag']>
    readonly useSupported: UnwrapRef<typeof import('@vueuse/core')['useSupported']>
    readonly useSwipe: UnwrapRef<typeof import('@vueuse/core')['useSwipe']>
    readonly useTemplateRef: UnwrapRef<typeof import('vue')['useTemplateRef']>
    readonly useTemplateRefsList: UnwrapRef<typeof import('@vueuse/core')['useTemplateRefsList']>
    readonly useTextDirection: UnwrapRef<typeof import('@vueuse/core')['useTextDirection']>
    readonly useTextSelection: UnwrapRef<typeof import('@vueuse/core')['useTextSelection']>
    readonly useTextareaAutosize: UnwrapRef<typeof import('@vueuse/core')['useTextareaAutosize']>
    readonly useThrottle: UnwrapRef<typeof import('@vueuse/core')['useThrottle']>
    readonly useThrottleFn: UnwrapRef<typeof import('@vueuse/core')['useThrottleFn']>
    readonly useThrottledRefHistory: UnwrapRef<typeof import('@vueuse/core')['useThrottledRefHistory']>
    readonly useTimeAgo: UnwrapRef<typeof import('@vueuse/core')['useTimeAgo']>
    readonly useTimeAgoIntl: UnwrapRef<typeof import('@vueuse/core')['useTimeAgoIntl']>
    readonly useTimeout: UnwrapRef<typeof import('@vueuse/core')['useTimeout']>
    readonly useTimeoutFn: UnwrapRef<typeof import('@vueuse/core')['useTimeoutFn']>
    readonly useTimeoutPoll: UnwrapRef<typeof import('@vueuse/core')['useTimeoutPoll']>
    readonly useTimestamp: UnwrapRef<typeof import('@vueuse/core')['useTimestamp']>
    readonly useTitle: UnwrapRef<typeof import('@vueuse/core')['useTitle']>
    readonly useToNumber: UnwrapRef<typeof import('@vueuse/core')['useToNumber']>
    readonly useToString: UnwrapRef<typeof import('@vueuse/core')['useToString']>
    readonly useToggle: UnwrapRef<typeof import('@vueuse/core')['useToggle']>
    readonly useTransition: UnwrapRef<typeof import('@vueuse/core')['useTransition']>
    readonly useUrlSearchParams: UnwrapRef<typeof import('@vueuse/core')['useUrlSearchParams']>
    readonly useUserMedia: UnwrapRef<typeof import('@vueuse/core')['useUserMedia']>
    readonly useUserStore: UnwrapRef<typeof import('./stores/user')['useUserStore']>
    readonly useVModel: UnwrapRef<typeof import('@vueuse/core')['useVModel']>
    readonly useVModels: UnwrapRef<typeof import('@vueuse/core')['useVModels']>
    readonly useVibrate: UnwrapRef<typeof import('@vueuse/core')['useVibrate']>
    readonly useVirtualList: UnwrapRef<typeof import('@vueuse/core')['useVirtualList']>
    readonly useWakeLock: UnwrapRef<typeof import('@vueuse/core')['useWakeLock']>
    readonly useWebNotification: UnwrapRef<typeof import('@vueuse/core')['useWebNotification']>
    readonly useWebSocket: UnwrapRef<typeof import('@vueuse/core')['useWebSocket']>
    readonly useWebWorker: UnwrapRef<typeof import('@vueuse/core')['useWebWorker']>
    readonly useWebWorkerFn: UnwrapRef<typeof import('@vueuse/core')['useWebWorkerFn']>
    readonly useWindowFocus: UnwrapRef<typeof import('@vueuse/core')['useWindowFocus']>
    readonly useWindowScroll: UnwrapRef<typeof import('@vueuse/core')['useWindowScroll']>
    readonly useWindowSize: UnwrapRef<typeof import('@vueuse/core')['useWindowSize']>
    readonly watch: UnwrapRef<typeof import('vue')['watch']>
    readonly watchArray: UnwrapRef<typeof import('@vueuse/core')['watchArray']>
    readonly watchAtMost: UnwrapRef<typeof import('@vueuse/core')['watchAtMost']>
    readonly watchDebounced: UnwrapRef<typeof import('@vueuse/core')['watchDebounced']>
    readonly watchDeep: UnwrapRef<typeof import('@vueuse/core')['watchDeep']>
    readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
    readonly watchIgnorable: UnwrapRef<typeof import('@vueuse/core')['watchIgnorable']>
    readonly watchImmediate: UnwrapRef<typeof import('@vueuse/core')['watchImmediate']>
    readonly watchOnce: UnwrapRef<typeof import('@vueuse/core')['watchOnce']>
    readonly watchPausable: UnwrapRef<typeof import('@vueuse/core')['watchPausable']>
    readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
    readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']>
    readonly watchThrottled: UnwrapRef<typeof import('@vueuse/core')['watchThrottled']>
    readonly watchTriggerable: UnwrapRef<typeof import('@vueuse/core')['watchTriggerable']>
    readonly watchWithFilter: UnwrapRef<typeof import('@vueuse/core')['watchWithFilter']>
    readonly whenever: UnwrapRef<typeof import('@vueuse/core')['whenever']>
  }
}

================================================
FILE: src/components/README.md
================================================
## Components

Components in this dir will be auto-registered and on-demand, powered by [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components).

### Icons

You can use icons from almost any icon sets by the power of [Iconify](https://iconify.design/).

It will only bundle the icons you use. Check out [`unplugin-icons`](https://github.com/antfu/unplugin-icons) for more details.


================================================
FILE: src/components/TheCounter.vue
================================================
<script setup lang="ts">
const props = defineProps<{
  initial: number
}>()

const { count, inc, dec } = useCounter(props.initial)
</script>

<template>
  <div>
    {{ count }}
    <button class="inc" @click="inc()">
      +
    </button>
    <button class="dec" @click="dec()">
      -
    </button>
  </div>
</template>


================================================
FILE: src/components/TheFooter.vue
================================================
<script setup lang="ts">
import { availableLocales, loadLanguageAsync } from '~/modules/i18n'

const { t, locale } = useI18n()

async function toggleLocales() {
  // change to some real logic
  const locales = availableLocales
  const newLocale = locales[(locales.indexOf(locale.value) + 1) % locales.length]
  await loadLanguageAsync(newLocale)
  locale.value = newLocale
}
</script>

<template>
  <nav flex="~ gap-4" mt-6 justify-center text-xl>
    <RouterLink icon-btn to="/" :title="t('button.home')">
      <div i-carbon-campsite />
    </RouterLink>

    <button icon-btn :title="t('button.toggle_dark')" @click="toggleDark()">
      <div i="carbon-sun dark:carbon-moon" />
    </button>

    <a icon-btn :title="t('button.toggle_langs')" @click="toggleLocales()">
      <div i-carbon-language />
    </a>

    <RouterLink icon-btn to="/about" :title="t('button.about')" data-test-id="about">
      <div i-carbon-dicom-overlay />
    </RouterLink>

    <a icon-btn rel="noreferrer" href="https://github.com/antfu/vitesse" target="_blank" title="GitHub">
      <div i-carbon-logo-github />
    </a>
  </nav>
</template>


================================================
FILE: src/components/TheInput.vue
================================================
<script setup lang="ts">
const { modelValue } = defineModels<{
  modelValue: string
}>()
</script>

<template>
  <input
    id="input"
    v-model="modelValue"
    v-bind="$attrs"
    type="text"
    p="x-4 y-2"
    w="250px"
    text="center"
    bg="transparent"
    border="~ rounded gray-200 dark:gray-700"
    outline="none active:none"
  >
</template>


================================================
FILE: src/components.d.ts
================================================
/* eslint-disable */
// @ts-nocheck
// biome-ignore lint: disable
// oxlint-disable
// ------
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399

export {}

/* prettier-ignore */
declare module 'vue' {
  export interface GlobalComponents {
    README: typeof import('./components/README.md')['default']
    RouterLink: typeof import('vue-router')['RouterLink']
    RouterView: typeof import('vue-router')['RouterView']
    TheCounter: typeof import('./components/TheCounter.vue')['default']
    TheFooter: typeof import('./components/TheFooter.vue')['default']
    TheInput: typeof import('./components/TheInput.vue')['default']
  }
}


================================================
FILE: src/composables/dark.ts
================================================
// these APIs are auto-imported from @vueuse/core
export const isDark = useDark()
export const toggleDark = useToggle(isDark)
export const preferredDark = usePreferredDark()


================================================
FILE: src/layouts/404.vue
================================================
<script setup lang="ts">
const router = useRouter()
const { t } = useI18n()
useHead({
  title: () => t('not-found'),
})
</script>

<template>
  <main p="x4 y10" text="center teal-700 dark:gray-200">
    <div text-4xl>
      <div i-carbon-warning inline-block />
    </div>
    <RouterView />
    <div>
      <button btn text-sm m="3 t8" @click="router.back()">
        {{ t('button.back') }}
      </button>
    </div>
  </main>
</template>


================================================
FILE: src/layouts/README.md
================================================
## Layouts

Vue components in this dir are used as layouts.

By default, `default.vue` will be used unless an alternative is specified in the route meta.

With [`unplugin-vue-router`](https://github.com/posva/unplugin-vue-router) and [`vite-plugin-vue-layouts`](https://github.com/JohnCampionJr/vite-plugin-vue-layouts), you can specify the layout in the page's SFCs like this:

```vue
<route lang="yaml">
meta:
  layout: home
</route>
```


================================================
FILE: src/layouts/default.vue
================================================
<template>
  <main
    px-4 py-10
    text="center gray-700 dark:gray-200"
  >
    <RouterView />
    <TheFooter />
    <div mx-auto mt-5 text-center text-sm opacity-50>
      [Default Layout]
    </div>
  </main>
</template>


================================================
FILE: src/layouts/home.vue
================================================
<template>
  <main
    px-4 py-10
    text="center gray-700 dark:gray-200"
  >
    <RouterView />
    <TheFooter />
    <div mx-auto mt-5 text-center text-sm opacity-50>
      [Home Layout]
    </div>
  </main>
</template>


================================================
FILE: src/main.ts
================================================
import type { UserModule } from './types'

import { setupLayouts } from 'virtual:generated-layouts'
import { ViteSSG } from 'vite-ssg'
import { routes } from 'vue-router/auto-routes'
import App from './App.vue'

import '@unocss/reset/tailwind.css'
import './styles/main.css'
import 'uno.css'

// https://github.com/antfu/vite-ssg
export const createApp = ViteSSG(
  App,
  {
    routes: setupLayouts([...routes]),
    base: import.meta.env.BASE_URL,
  },
  (ctx) => {
    // install all modules under `modules/`
    Object.values(import.meta.glob<{ install: UserModule }>('./modules/*.ts', { eager: true }))
      .forEach(i => i.install?.(ctx))
    // ctx.app.use(Previewer)
  },
)


================================================
FILE: src/modules/README.md
================================================
## Modules

A custom user module system. Place a `.ts` file with the following template, it will be installed automatically.

```ts
import type { UserModule } from '~/types'

export const install: UserModule = ({ app, router, isClient }) => {
  // do something
}
```


================================================
FILE: src/modules/i18n.ts
================================================
import type { Locale } from 'vue-i18n'
import type { UserModule } from '~/types'
import { createI18n } from 'vue-i18n'

// Import i18n resources
// https://vitejs.dev/guide/features.html#glob-import
//
// Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite
const i18n = createI18n({
  legacy: false,
  locale: '',
  messages: {},
})

const localesMap = Object.fromEntries(
  Object.entries(import.meta.glob('../../locales/*.yml'))
    .map(([path, loadLocale]) => [path.match(/([\w-]*)\.yml$/)?.[1], loadLocale]),
) as Record<Locale, () => Promise<{ default: Record<string, string> }>>

export const availableLocales = Object.keys(localesMap)

const loadedLanguages: string[] = []

function setI18nLanguage(lang: Locale) {
  i18n.global.locale.value = lang as any
  if (typeof document !== 'undefined')
    document.querySelector('html')?.setAttribute('lang', lang)
  return lang
}

export async function loadLanguageAsync(lang: string): Promise<Locale> {
  // If the same language
  if (i18n.global.locale.value === lang)
    return setI18nLanguage(lang)

  // If the language was already loaded
  if (loadedLanguages.includes(lang))
    return setI18nLanguage(lang)

  // If the language hasn't been loaded yet
  const messages = await localesMap[lang]()
  i18n.global.setLocaleMessage(lang, messages.default)
  loadedLanguages.push(lang)
  return setI18nLanguage(lang)
}

export const install: UserModule = ({ app }) => {
  app.use(i18n)
  loadLanguageAsync('en')
}


================================================
FILE: src/modules/nprogress.ts
================================================
import type { UserModule } from '~/types'
import NProgress from 'nprogress'

export const install: UserModule = ({ isClient, router }) => {
  if (isClient) {
    router.beforeEach((to, from) => {
      if (to.path !== from.path)
        NProgress.start()
    })
    router.afterEach(() => {
      NProgress.done()
    })
  }
}


================================================
FILE: src/modules/pinia.ts
================================================
import type { UserModule } from '~/types'
import { createPinia } from 'pinia'

// Setup Pinia
// https://pinia.vuejs.org/
export const install: UserModule = ({ isClient, initialState, app }) => {
  const pinia = createPinia()
  app.use(pinia)
  // Refer to
  // https://github.com/antfu/vite-ssg/blob/main/README.md#state-serialization
  // for other serialization strategies.
  if (isClient)
    pinia.state.value = (initialState.pinia) || {}

  else
    initialState.pinia = pinia.state.value
}


================================================
FILE: src/modules/pwa.ts
================================================
import type { UserModule } from '~/types'

// https://github.com/antfu/vite-plugin-pwa#automatic-reload-when-new-content-available
export const install: UserModule = ({ isClient, router }) => {
  if (!isClient)
    return

  router.isReady()
    .then(async () => {
      const { registerSW } = await import('virtual:pwa-register')
      registerSW({ immediate: true })
    })
    .catch(() => {})
}


================================================
FILE: src/pages/README.md
================================================
## File-based Routing

Routes will be auto-generated for Vue files in this dir with the same file structure.
Check out [`unplugin-vue-router`](https://github.com/posva/unplugin-vue-router) for more details.

### Path Aliasing

`~/` is aliased to `./src/` folder.

For example, instead of having

```ts
import { isDark } from '../../../../composables'
```

now, you can use

```ts
import { isDark } from '~/composables'
```


================================================
FILE: src/pages/[...all].vue
================================================
<script setup lang="ts">
const { t } = useI18n()
</script>

<template>
  <div>
    {{ t('not-found') }}
  </div>
</template>

<route lang="yaml">
meta:
  layout: 404
</route>


================================================
FILE: src/pages/about.md
================================================
---
title: About
---

<script setup>
const { t } = useI18n()
useHead({ title: () => t('button.about') })
</script>

<div class="text-center">
  <!-- You can use Vue components inside markdown -->
  <div i-carbon-dicom-overlay class="text-4xl -mb-6 m-auto" />
  <h3>{{ t('button.about') }}</h3>
</div>

[Vitesse](https://github.com/antfu/vitesse) is an opinionated [Vite](https://github.com/vitejs/vite) starter template made by [@antfu](https://github.com/antfu) for mocking apps swiftly. With **file-based routing**, **components auto importing**, **markdown support**, I18n, PWA and uses **UnoCSS** for styling and icons.

```js
// syntax highlighting example
function vitesse() {
  const foo = 'bar'
  console.log(foo)
}
```

Check out the [GitHub repo](https://github.com/antfu/vitesse) for more details.


================================================
FILE: src/pages/hi/[name].vue
================================================
<script setup lang="ts">
const router = useRouter()
const route = useRoute('/hi/[name]')
const user = useUserStore()
const { t } = useI18n()

watchEffect(() => {
  user.setNewName(route.params.name)
})
useHead({
  title: () => t('intro.hi', { name: user.savedName }),
})
</script>

<template>
  <div>
    <div text-4xl>
      <div i-carbon-pedestrian inline-block />
    </div>
    <p>
      {{ t('intro.hi', { name: user.savedName }) }}
    </p>

    <p text-sm opacity-75>
      <em>{{ t('intro.dynamic-route') }}</em>
    </p>

    <template v-if="user.otherNames.length">
      <div mt-4 text-sm>
        <span opacity-75>{{ t('intro.aka') }}:</span>
        <ul>
          <li v-for="otherName in user.otherNames" :key="otherName">
            <RouterLink :to="`/hi/${otherName}`" replace>
              {{ otherName }}
            </RouterLink>
          </li>
        </ul>
      </div>
    </template>

    <div>
      <button
        m="3 t6" btn text-sm
        @click="router.back()"
      >
        {{ t('button.back') }}
      </button>
    </div>
  </div>
</template>


================================================
FILE: src/pages/index.vue
================================================
<script setup lang="ts">
defineOptions({
  name: 'IndexPage',
})
const user = useUserStore()
const name = ref(user.savedName)

const router = useRouter()
function go() {
  if (name.value)
    router.push(`/hi/${encodeURIComponent(name.value)}`)
}

const { t } = useI18n()
useHead({
  title: () => t('button.home'),
})
</script>

<template>
  <div>
    <div text-4xl>
      <div i-carbon-campsite inline-block />
    </div>
    <p>
      <a rel="noreferrer" href="https://github.com/antfu/vitesse" target="_blank">
        Vitesse
      </a>
    </p>
    <p>
      <em text-sm opacity-75>{{ t('intro.desc') }}</em>
    </p>

    <div py-4 />

    <TheInput
      v-model="name"
      :placeholder="t('intro.whats-your-name')"
      autocomplete="false"
      @keydown.enter="go"
    />
    <label class="hidden" for="input">{{ t('intro.whats-your-name') }}</label>

    <div>
      <button
        m-3 btn text-sm
        :disabled="!name"
        @click="go"
      >
        {{ t('button.go') }}
      </button>
    </div>
  </div>
</template>

<route lang="yaml">
meta:
  layout: home
</route>


================================================
FILE: src/route-map.d.ts
================================================
/* eslint-disable */
/* prettier-ignore */
// oxfmt-ignore
// @ts-nocheck
// noinspection ES6UnusedImports
// Generated by vue-router. !! DO NOT MODIFY THIS FILE !!
// It's recommended to commit this file.
// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry.

import type {
  RouteRecordInfo,
  ParamValue,
  ParamValueOneOrMore,
  ParamValueZeroOrMore,
  ParamValueZeroOrOne,
} from 'vue-router'

declare module 'vue-router' {
  interface TypesConfig {
    ParamParsers: never
  }
}

declare module 'vue-router/auto-routes' {
  /**
   * Route name map generated by vue-router
   */
  export interface RouteNamedMap {
    '/': RouteRecordInfo<
      '/',
      '/',
      Record<never, never>,
      Record<never, never>,
      | never
    >,
    '/[...all]': RouteRecordInfo<
      '/[...all]',
      '/:all(.*)',
      { all: ParamValue<true> },
      { all: ParamValue<false> },
      | never
    >,
    '/about': RouteRecordInfo<
      '/about',
      '/about',
      Record<never, never>,
      Record<never, never>,
      | never
    >,
    '/hi/[name]': RouteRecordInfo<
      '/hi/[name]',
      '/hi/:name',
      { name: ParamValue<true> },
      { name: ParamValue<false> },
      | never
    >,
    '/README': RouteRecordInfo<
      '/README',
      '/README',
      Record<never, never>,
      Record<never, never>,
      | never
    >,
  }

  /**
   * Route file to route info map by vue-router.
   * Used by the \`sfc-typed-router\` Volar plugin to automatically type \`useRoute()\`.
   *
   * Each key is a file path relative to the project root with 2 properties:
   * - routes: union of route names of the possible routes when in this page (passed to useRoute<...>())
   * - views: names of nested views (can be passed to <RouterView name="...">)
   *
   * @internal
   */
  export interface _RouteFileInfoMap {
    'src/pages/index.vue': {
      routes:
        | '/'
      views:
        | never
    }
    'src/pages/[...all].vue': {
      routes:
        | '/[...all]'
      views:
        | never
    }
    'src/pages/about.md': {
      routes:
        | '/about'
      views:
        | never
    }
    'src/pages/hi/[name].vue': {
      routes:
        | '/hi/[name]'
      views:
        | never
    }
    'src/pages/README.md': {
      routes:
        | '/README'
      views:
        | never
    }
  }

  /**
   * Get a union of possible route names in a certain route component file.
   * Used by the \`sfc-typed-router\` Volar plugin to automatically type \`useRoute()\`.
   *
   * @internal
   */
  export type _RouteNamesForFilePath<FilePath extends string> =
    _RouteFileInfoMap extends Record<FilePath, infer Info>
      ? Info['routes']
      : keyof RouteNamedMap
}

export {}


================================================
FILE: src/shims.d.ts
================================================
declare interface Window {
  // extend the window
}

// with unplugin-vue-markdown, markdown files can be treated as Vue components
declare module '*.md' {
  import type { DefineComponent } from 'vue'

  const component: DefineComponent<object, object, any>
  export default component
}

declare module '*.vue' {
  import type { DefineComponent } from 'vue'

  const component: DefineComponent<object, object, any>
  export default component
}


================================================
FILE: src/stores/user.ts
================================================
import { acceptHMRUpdate, defineStore } from 'pinia'

export const useUserStore = defineStore('user', () => {
  /**
   * Current name of the user.
   */
  const savedName = ref('')
  const previousNames = ref(new Set<string>())

  const usedNames = computed(() => Array.from(previousNames.value))
  const otherNames = computed(() => usedNames.value.filter(name => name !== savedName.value))

  /**
   * Changes the current name of the user and saves the one that was used
   * before.
   *
   * @param name - new name to set
   */
  function setNewName(name: string) {
    if (savedName.value)
      previousNames.value.add(savedName.value)

    savedName.value = name
  }

  return {
    setNewName,
    otherNames,
    savedName,
  }
})

if (import.meta.hot)
  import.meta.hot.accept(acceptHMRUpdate(useUserStore as any, import.meta.hot))


================================================
FILE: src/styles/main.css
================================================
@import './markdown.css';

html,
body,
#app {
  height: 100%;
  margin: 0;
  padding: 0;
}

html.dark {
  background: #121212;
  color-scheme: dark;
}

#nprogress {
  pointer-events: none;
}

#nprogress .bar {
  background: rgb(13, 148, 136);
  opacity: 0.75;
  position: fixed;
  z-index: 1031;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
}


================================================
FILE: src/styles/markdown.css
================================================
.prose pre:not(.shiki) {
  padding: 0;
}

.prose .shiki {
  font-family: 'DM Mono', monospace;
  font-size: 1.2em;
  line-height: 1.4;
}

.prose img {
  width: 100%;
}

.shiki,
.shiki span {
  color: var(--shiki-light);
  background: var(--shiki-light-bg);
}

html.dark .shiki,
html.dark .shiki span {
  color: var(--shiki-dark);
  background: var(--shiki-dark-bg);
}


================================================
FILE: src/types.ts
================================================
import type { ViteSSGContext } from 'vite-ssg'

export type UserModule = (ctx: ViteSSGContext) => void


================================================
FILE: test/__snapshots__/component.test.ts.snap
================================================
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`component TheCounter.vue > should render 1`] = `"<div>10 <button class="inc"> + </button><button class="dec"> - </button></div>"`;


================================================
FILE: test/basic.test.ts
================================================
import { describe, expect, it } from 'vitest'

describe('tests', () => {
  it('should works', () => {
    expect(1 + 1).toEqual(2)
  })
})


================================================
FILE: test/component.test.ts
================================================
import { mount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import TheCounter from '../src/components/TheCounter.vue'

describe('component TheCounter.vue', () => {
  it('should render', () => {
    const wrapper = mount(TheCounter, { props: { initial: 10 } })
    expect(wrapper.text()).toContain('10')
    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should be interactive', async () => {
    const wrapper = mount(TheCounter, { props: { initial: 0 } })
    expect(wrapper.text()).toContain('0')

    expect(wrapper.find('.inc').exists()).toBe(true)

    expect(wrapper.find('.dec').exists()).toBe(true)

    await wrapper.get('.inc').trigger('click')

    expect(wrapper.text()).toContain('1')

    await wrapper.get('.dec').trigger('click')

    expect(wrapper.text()).toContain('0')
  })
})


================================================
FILE: tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "ESNext",
    "jsx": "preserve",
    "lib": ["DOM", "ESNext"],
    "baseUrl": ".",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "paths": {
      "~/*": ["src/*"]
    },
    "resolveJsonModule": true,
    "types": [
      "vitest",
      "vite/client",
      "vite-plugin-vue-layouts/client",
      "vite-plugin-pwa/client",
      "unplugin-vue-macros/macros-global"
    ],
    "allowJs": true,
    "strict": true,
    "strictNullChecks": true,
    "noUnusedLocals": true,
    "noEmit": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "isolatedModules": true,
    "skipLibCheck": true
  },
  "vueCompilerOptions": {
    "plugins": [
      "@vue-macros/volar/define-models",
      "@vue-macros/volar/define-slots"
    ]
  },
  "exclude": ["dist", "node_modules", "cypress"]
}


================================================
FILE: uno.config.ts
================================================
import {
  createLocalFontProcessor,
} from '@unocss/preset-web-fonts/local'
import {
  defineConfig,
  presetAttributify,
  presetIcons,
  presetTypography,
  presetUno,
  presetWebFonts,
  transformerDirectives,
  transformerVariantGroup,
} from 'unocss'

export default defineConfig({
  shortcuts: [
    ['btn', 'px-4 py-1 rounded inline-block bg-teal-700 text-white cursor-pointer !outline-none hover:bg-teal-800 disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50'],
    ['icon-btn', 'inline-block cursor-pointer select-none opacity-75 transition duration-200 ease-in-out hover:opacity-100 hover:text-teal-600'],
  ],
  presets: [
    presetUno(),
    presetAttributify(),
    presetIcons({
      scale: 1.2,
    }),
    presetTypography(),
    presetWebFonts({
      fonts: {
        sans: 'DM Sans',
        serif: 'DM Serif Display',
        mono: 'DM Mono',
      },
      processors: createLocalFontProcessor(),
    }),
  ],
  transformers: [
    transformerDirectives(),
    transformerVariantGroup(),
  ],
  safelist: 'prose prose-sm m-auto text-left'.split(' '),
})


================================================
FILE: vite.config.ts
================================================
import path from 'node:path'
import VueI18n from '@intlify/unplugin-vue-i18n/vite'
import Shiki from '@shikijs/markdown-it'
import { unheadVueComposablesImports } from '@unhead/vue'
import Vue from '@vitejs/plugin-vue'
import LinkAttributes from 'markdown-it-link-attributes'
import Unocss from 'unocss/vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import VueMacros from 'unplugin-vue-macros/vite'
import Markdown from 'unplugin-vue-markdown/vite'
import { defineConfig } from 'vite'
import { VitePWA } from 'vite-plugin-pwa'
import VueDevTools from 'vite-plugin-vue-devtools'
import Layouts from 'vite-plugin-vue-layouts'
import generateSitemap from 'vite-ssg-sitemap'
import { VueRouterAutoImports } from 'vue-router/unplugin'
import VueRouter from 'vue-router/vite'
import 'vitest/config'

export default defineConfig({
  resolve: {
    alias: {
      '~/': `${path.resolve(__dirname, 'src')}/`,
    },
  },

  plugins: [
    // https://github.com/vuejs/router
    VueRouter({
      extensions: ['.vue', '.md'],
      dts: 'src/route-map.d.ts',
    }),

    VueMacros({
      plugins: {
        vue: Vue({
          include: [/\.vue$/, /\.md$/],
        }),
      },
    }),

    // https://github.com/JohnCampionJr/vite-plugin-vue-layouts
    Layouts(),

    // https://github.com/antfu/unplugin-auto-import
    AutoImport({
      include: [/\.[jt]sx?$/, /\.vue$/, /\.vue\?vue/, /\.md$/],
      imports: [
        'vue',
        'vue-i18n',
        '@vueuse/core',
        unheadVueComposablesImports,
        VueRouterAutoImports,
        {
          // add any other imports you were relying on
          'vue-router/auto': ['useLink'],
        },
      ],
      dts: 'src/auto-imports.d.ts',
      dirs: [
        'src/composables',
        'src/stores',
      ],
      vueTemplate: true,
    }),

    // https://github.com/antfu/unplugin-vue-components
    Components({
      // allow auto load markdown components under `./src/components/`
      extensions: ['vue', 'md'],
      // allow auto import and register components used in markdown
      include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
      dts: 'src/components.d.ts',
    }),

    // https://github.com/antfu/unocss
    // see uno.config.ts for config
    Unocss(),

    // https://github.com/unplugin/unplugin-vue-markdown
    // Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite
    Markdown({
      wrapperClasses: 'prose prose-sm m-auto text-left',
      headEnabled: true,
      async markdownItSetup(md) {
        md.use(LinkAttributes, {
          matcher: (link: string) => /^https?:\/\//.test(link),
          attrs: {
            target: '_blank',
            rel: 'noopener',
          },
        })
        md.use(await Shiki({
          defaultColor: false,
          themes: {
            light: 'vitesse-light',
            dark: 'vitesse-dark',
          },
        }))
      },
    }),

    // https://github.com/antfu/vite-plugin-pwa
    VitePWA({
      registerType: 'autoUpdate',
      includeAssets: ['favicon.svg', 'safari-pinned-tab.svg'],
      manifest: {
        name: 'Vitesse',
        short_name: 'Vitesse',
        theme_color: '#ffffff',
        icons: [
          {
            src: '/pwa-192x192.png',
            sizes: '192x192',
            type: 'image/png',
          },
          {
            src: '/pwa-512x512.png',
            sizes: '512x512',
            type: 'image/png',
          },
          {
            src: '/pwa-512x512.png',
            sizes: '512x512',
            type: 'image/png',
            purpose: 'any maskable',
          },
        ],
      },
    }),

    // https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n
    VueI18n({
      runtimeOnly: true,
      compositionOnly: true,
      fullInstall: true,
      include: [path.resolve(__dirname, 'locales/**')],
    }),

    // https://github.com/webfansplz/vite-plugin-vue-devtools
    VueDevTools(),
  ],

  // https://github.com/vitest-dev/vitest
  test: {
    include: ['test/**/*.test.ts'],
    environment: 'jsdom',
  },

  // https://github.com/antfu/vite-ssg
  ssgOptions: {
    script: 'async',
    formatting: 'minify',
    beastiesOptions: {
      reduceInlineStyles: false,
    },
    onFinished() {
      generateSitemap()
    },
  },

  ssr: {
    // TODO: workaround until they support native ESM
    noExternal: ['workbox-window', /vue-i18n/],
  },
})
Download .txt
gitextract_7rc8tos6/

├── .dockerignore
├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       └── ci.yml
├── .gitignore
├── .npmrc
├── .vscode/
│   ├── extensions.json
│   └── settings.json
├── Dockerfile
├── LICENSE
├── README.md
├── README.zh-CN.md
├── cypress/
│   ├── e2e/
│   │   └── basic.spec.ts
│   └── tsconfig.json
├── cypress.config.ts
├── eslint.config.js
├── index.html
├── locales/
│   ├── README.md
│   ├── ar.yml
│   ├── de.yml
│   ├── en.yml
│   ├── es.yml
│   ├── fr.yml
│   ├── id.yml
│   ├── it.yml
│   ├── ja.yml
│   ├── ka.yml
│   ├── ko.yml
│   ├── pl.yml
│   ├── pt-BR.yml
│   ├── ru.yml
│   ├── tr.yml
│   ├── uk.yml
│   ├── uz.yml
│   ├── vi.yml
│   └── zh-CN.yml
├── netlify.toml
├── package.json
├── pnpm-workspace.yaml
├── public/
│   └── _headers
├── src/
│   ├── App.vue
│   ├── auto-imports.d.ts
│   ├── components/
│   │   ├── README.md
│   │   ├── TheCounter.vue
│   │   ├── TheFooter.vue
│   │   └── TheInput.vue
│   ├── components.d.ts
│   ├── composables/
│   │   └── dark.ts
│   ├── layouts/
│   │   ├── 404.vue
│   │   ├── README.md
│   │   ├── default.vue
│   │   └── home.vue
│   ├── main.ts
│   ├── modules/
│   │   ├── README.md
│   │   ├── i18n.ts
│   │   ├── nprogress.ts
│   │   ├── pinia.ts
│   │   └── pwa.ts
│   ├── pages/
│   │   ├── README.md
│   │   ├── [...all].vue
│   │   ├── about.md
│   │   ├── hi/
│   │   │   └── [name].vue
│   │   └── index.vue
│   ├── route-map.d.ts
│   ├── shims.d.ts
│   ├── stores/
│   │   └── user.ts
│   ├── styles/
│   │   ├── main.css
│   │   └── markdown.css
│   └── types.ts
├── test/
│   ├── __snapshots__/
│   │   └── component.test.ts.snap
│   ├── basic.test.ts
│   └── component.test.ts
├── tsconfig.json
├── uno.config.ts
└── vite.config.ts
Download .txt
SYMBOL INDEX (15 symbols across 9 files)

FILE: cypress.config.ts
  method setupNodeEvents (line 10) | setupNodeEvents(on) {

FILE: src/auto-imports.d.ts
  type GlobalComponents (line 325) | interface GlobalComponents {}
  type ComponentCustomProperties (line 326) | interface ComponentCustomProperties {

FILE: src/components.d.ts
  type GlobalComponents (line 13) | interface GlobalComponents {

FILE: src/modules/i18n.ts
  function setI18nLanguage (line 24) | function setI18nLanguage(lang: Locale) {
  function loadLanguageAsync (line 31) | async function loadLanguageAsync(lang: string): Promise<Locale> {

FILE: src/route-map.d.ts
  type TypesConfig (line 19) | interface TypesConfig {
  type RouteNamedMap (line 28) | interface RouteNamedMap {
  type _RouteFileInfoMap (line 76) | interface _RouteFileInfoMap {
  type _RouteNamesForFilePath (line 115) | type _RouteNamesForFilePath<FilePath extends string> =

FILE: src/shims.d.ts
  type Window (line 1) | interface Window {

FILE: src/stores/user.ts
  function setNewName (line 19) | function setNewName(name: string) {

FILE: src/types.ts
  type UserModule (line 3) | type UserModule = (ctx: ViteSSGContext) => void

FILE: vite.config.ts
  method markdownItSetup (line 86) | async markdownItSetup(md) {
  method onFinished (line 158) | onFinished() {
Condensed preview — 75 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (112K chars).
[
  {
    "path": ".dockerignore",
    "chars": 18,
    "preview": "node_modules\ndist\n"
  },
  {
    "path": ".editorconfig",
    "chars": 147,
    "preview": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 39,
    "preview": "open_collective: antfu\ngithub: [antfu]\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 2030,
    "preview": "name: CI\n\non:\n  push:\n    branches:\n      - main\n\n  pull_request:\n    branches:\n      - main\n\njobs:\n  lint:\n    runs-on:"
  },
  {
    "path": ".gitignore",
    "chars": 126,
    "preview": ".DS_Store\n.vite-ssg-dist\n.vite-ssg-temp\n*.local\ndist\ndist-ssr\nnode_modules\n.idea/\n*.log\ncypress/downloads\npublic/assets/"
  },
  {
    "path": ".npmrc",
    "chars": 22,
    "preview": "shamefully-hoist=true\n"
  },
  {
    "path": ".vscode/extensions.json",
    "chars": 255,
    "preview": "{\n  \"recommendations\": [\n    \"antfu.iconify\",\n    \"antfu.unocss\",\n    \"antfu.vite\",\n    \"antfu.goto-alias\",\n    \"csstool"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 1484,
    "preview": "{\n  \"cSpell.words\": [\"Vitesse\", \"Vite\", \"unocss\", \"vitest\", \"vueuse\", \"pinia\", \"demi\", \"antfu\", \"iconify\", \"intlify\", \"v"
  },
  {
    "path": "Dockerfile",
    "chars": 406,
    "preview": "FROM node:20-alpine AS build-stage\n\nWORKDIR /app\nRUN corepack enable\n\nCOPY .npmrc package.json pnpm-lock.yaml pnpm-works"
  },
  {
    "path": "LICENSE",
    "chars": 1075,
    "preview": "MIT License\n\nCopyright (c) 2020-PRESENT Anthony Fu\n\nPermission is hereby granted, free of charge, to any person obtainin"
  },
  {
    "path": "README.md",
    "chars": 10027,
    "preview": "<p align='center'>\n  <img src='https://user-images.githubusercontent.com/11247099/154486817-f86b8f20-5463-4122-b6e9-9306"
  },
  {
    "path": "README.zh-CN.md",
    "chars": 5857,
    "preview": "<p align='center'>\n  <img src='https://user-images.githubusercontent.com/11247099/154486817-f86b8f20-5463-4122-b6e9-9306"
  },
  {
    "path": "cypress/e2e/basic.spec.ts",
    "chars": 688,
    "preview": "context('Basic', () => {\n  beforeEach(() => {\n    cy.visit('/')\n  })\n\n  it('basic nav', () => {\n    cy.url()\n      .shou"
  },
  {
    "path": "cypress/tsconfig.json",
    "chars": 152,
    "preview": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"types\": [\n      \"cypress\"\n    ]\n  },\n  \"include\": [\n    \""
  },
  {
    "path": "cypress.config.ts",
    "chars": 350,
    "preview": "import { defineConfig } from 'cypress'\nimport vitePreprocessor from 'cypress-vite'\n\nexport default defineConfig({\n  e2e:"
  },
  {
    "path": "eslint.config.js",
    "chars": 261,
    "preview": "// @ts-check\nimport antfu from '@antfu/eslint-config'\n\nexport default antfu(\n  {\n    unocss: true,\n    formatters: true,"
  },
  {
    "path": "index.html",
    "chars": 983,
    "preview": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-w"
  },
  {
    "path": "locales/README.md",
    "chars": 385,
    "preview": "## i18n\n\nThis directory is to serve your locale translation files. YAML under this folder would be loaded automatically "
  },
  {
    "path": "locales/ar.yml",
    "chars": 304,
    "preview": "button:\n  about: حول\n  back: رجوع\n  go: تجربة\n  home: الرئيسية\n  toggle_dark: التغيير إلى الوضع المظلم\n  toggle_langs: ت"
  },
  {
    "path": "locales/de.yml",
    "chars": 330,
    "preview": "button:\n  about: Über\n  back: Zurück\n  go: Los\n  home: Startseite\n  toggle_dark: Dunkelmodus umschalten\n  toggle_langs: "
  },
  {
    "path": "locales/en.yml",
    "chars": 308,
    "preview": "button:\n  about: About\n  back: Back\n  go: GO\n  home: Home\n  toggle_dark: Toggle dark mode\n  toggle_langs: Change languag"
  },
  {
    "path": "locales/es.yml",
    "chars": 342,
    "preview": "button:\n  about: Acerca de\n  back: Atrás\n  go: Ir\n  home: Inicio\n  toggle_dark: Alternar modo oscuro\n  toggle_langs: Cam"
  },
  {
    "path": "locales/fr.yml",
    "chars": 353,
    "preview": "button:\n  about: À propos\n  back: Retour\n  go: Essayer\n  home: Accueil\n  toggle_dark: Basculer en mode sombre\n  toggle_l"
  },
  {
    "path": "locales/id.yml",
    "chars": 315,
    "preview": "button:\n  about: Tentang\n  back: Kembali\n  go: Pergi\n  home: Beranda\n  toggle_dark: Ubah ke mode gelap\n  toggle_langs: U"
  },
  {
    "path": "locales/it.yml",
    "chars": 310,
    "preview": "button:\n  about: Su di me\n  back: Indietro\n  go: Vai\n  home: Home\n  toggle_dark: Attiva/disattiva modalità scura\n  toggl"
  },
  {
    "path": "locales/ja.yml",
    "chars": 234,
    "preview": "button:\n  about: これは?\n  back: 戻る\n  go: 進む\n  home: ホーム\n  toggle_dark: ダークモード切り替え\n  toggle_langs: 言語切り替え\nintro:\n  desc: 固執"
  },
  {
    "path": "locales/ka.yml",
    "chars": 328,
    "preview": "button:\n  about: შესახებ\n  back: უკან\n  go: დაწყება\n  home: მთავარი\n  toggle_dark: გადართე მუქი რეჟიმი\n  toggle_langs: ე"
  },
  {
    "path": "locales/ko.yml",
    "chars": 224,
    "preview": "button:\n  about: 소개\n  back: 뒤로가기\n  go: 이동\n  home: 홈\n  toggle_dark: 다크모드 토글\n  toggle_langs: 언어 변경\nintro:\n  desc: Vite 애플리"
  },
  {
    "path": "locales/pl.yml",
    "chars": 333,
    "preview": "button:\n  about: O nas\n  back: Wróć\n  go: WEJDŹ\n  home: Strona główna\n  toggle_dark: Ustaw tryb nocny\n  toggle_langs: Zm"
  },
  {
    "path": "locales/pt-BR.yml",
    "chars": 340,
    "preview": "button:\n  about: Sobre\n  back: Voltar\n  go: Ir\n  home: Início\n  toggle_dark: Alternar modo escuro\n  toggle_langs: Mudar "
  },
  {
    "path": "locales/ru.yml",
    "chars": 313,
    "preview": "button:\n  about: О шаблоне\n  back: Назад\n  go: Перейти\n  home: Главная\n  toggle_dark: Включить темный режим\n  toggle_lan"
  },
  {
    "path": "locales/tr.yml",
    "chars": 328,
    "preview": "button:\n  about: Hakkımda\n  back: Geri\n  go: İLERİ\n  home: Anasayfa\n  toggle_dark: Karanlık modu değiştir\n  toggle_langs"
  },
  {
    "path": "locales/uk.yml",
    "chars": 313,
    "preview": "button:\n  about: Про шаблон\n  back: Назад\n  go: Перейти\n  home: Головна\n  toggle_dark: Переключити темний режим\n  toggle"
  },
  {
    "path": "locales/uz.yml",
    "chars": 342,
    "preview": "button:\n  about: Haqida\n  back: Orqaga\n  go: Kettik\n  home: Bosh sahifa\n  toggle_dark: Qorong‘i rejimga o‘tish\n  toggle_"
  },
  {
    "path": "locales/vi.yml",
    "chars": 316,
    "preview": "button:\n  about: Về\n  back: Quay lại\n  go: Đi\n  home: Khởi đầu\n  toggle_dark: Chuyển đổi chế độ tối\n  toggle_langs: Thay"
  },
  {
    "path": "locales/zh-CN.yml",
    "chars": 218,
    "preview": "button:\n  about: 关于\n  back: 返回\n  go: 确定\n  home: 首页\n  toggle_dark: 切换深色模式\n  toggle_langs: 切换语言\nintro:\n  desc: 固执己见的 Vite "
  },
  {
    "path": "netlify.toml",
    "chars": 256,
    "preview": "[build]\npublish = \"dist\"\ncommand = \"pnpm run build\"\n\n[build.environment]\nNODE_VERSION = \"22\"\n\n[[redirects]]\nfrom = \"/*\"\n"
  },
  {
    "path": "package.json",
    "chars": 2631,
    "preview": "{\n  \"type\": \"module\",\n  \"private\": true,\n  \"packageManager\": \"pnpm@10.30.2\",\n  \"scripts\": {\n    \"build\": \"vite-ssg build"
  },
  {
    "path": "pnpm-workspace.yaml",
    "chars": 1546,
    "preview": "shellEmulator: true\n\ntrustPolicy: no-downgrade\n\npackages: []\n\ncatalogs:\n\n  build:\n    '@intlify/unplugin-vue-i18n': ^11."
  },
  {
    "path": "public/_headers",
    "chars": 71,
    "preview": "/assets/*\n  cache-control: max-age=31536000\n  cache-control: immutable\n"
  },
  {
    "path": "src/App.vue",
    "chars": 643,
    "preview": "<script setup lang=\"ts\">\n// https://github.com/vueuse/head\n// you can use this to manipulate the document head in any co"
  },
  {
    "path": "src/auto-imports.d.ts",
    "chars": 46102,
    "preview": "/* eslint-disable */\n/* prettier-ignore */\n// @ts-nocheck\n// noinspection JSUnusedGlobalSymbols\n// Generated by unplugin"
  },
  {
    "path": "src/components/README.md",
    "chars": 403,
    "preview": "## Components\n\nComponents in this dir will be auto-registered and on-demand, powered by [`unplugin-vue-components`](http"
  },
  {
    "path": "src/components/TheCounter.vue",
    "chars": 322,
    "preview": "<script setup lang=\"ts\">\nconst props = defineProps<{\n  initial: number\n}>()\n\nconst { count, inc, dec } = useCounter(prop"
  },
  {
    "path": "src/components/TheFooter.vue",
    "chars": 1126,
    "preview": "<script setup lang=\"ts\">\nimport { availableLocales, loadLanguageAsync } from '~/modules/i18n'\n\nconst { t, locale } = use"
  },
  {
    "path": "src/components/TheInput.vue",
    "chars": 358,
    "preview": "<script setup lang=\"ts\">\nconst { modelValue } = defineModels<{\n  modelValue: string\n}>()\n</script>\n\n<template>\n  <input\n"
  },
  {
    "path": "src/components.d.ts",
    "chars": 678,
    "preview": "/* eslint-disable */\n// @ts-nocheck\n// biome-ignore lint: disable\n// oxlint-disable\n// ------\n// Generated by unplugin-v"
  },
  {
    "path": "src/composables/dark.ts",
    "chars": 174,
    "preview": "// these APIs are auto-imported from @vueuse/core\nexport const isDark = useDark()\nexport const toggleDark = useToggle(is"
  },
  {
    "path": "src/layouts/404.vue",
    "chars": 441,
    "preview": "<script setup lang=\"ts\">\nconst router = useRouter()\nconst { t } = useI18n()\nuseHead({\n  title: () => t('not-found'),\n})\n"
  },
  {
    "path": "src/layouts/README.md",
    "chars": 440,
    "preview": "## Layouts\n\nVue components in this dir are used as layouts.\n\nBy default, `default.vue` will be used unless an alternativ"
  },
  {
    "path": "src/layouts/default.vue",
    "chars": 226,
    "preview": "<template>\n  <main\n    px-4 py-10\n    text=\"center gray-700 dark:gray-200\"\n  >\n    <RouterView />\n    <TheFooter />\n    "
  },
  {
    "path": "src/layouts/home.vue",
    "chars": 223,
    "preview": "<template>\n  <main\n    px-4 py-10\n    text=\"center gray-700 dark:gray-200\"\n  >\n    <RouterView />\n    <TheFooter />\n    "
  },
  {
    "path": "src/main.ts",
    "chars": 683,
    "preview": "import type { UserModule } from './types'\n\nimport { setupLayouts } from 'virtual:generated-layouts'\nimport { ViteSSG } f"
  },
  {
    "path": "src/modules/README.md",
    "chars": 267,
    "preview": "## Modules\n\nA custom user module system. Place a `.ts` file with the following template, it will be installed automatica"
  },
  {
    "path": "src/modules/i18n.ts",
    "chars": 1490,
    "preview": "import type { Locale } from 'vue-i18n'\nimport type { UserModule } from '~/types'\nimport { createI18n } from 'vue-i18n'\n\n"
  },
  {
    "path": "src/modules/nprogress.ts",
    "chars": 327,
    "preview": "import type { UserModule } from '~/types'\nimport NProgress from 'nprogress'\n\nexport const install: UserModule = ({ isCli"
  },
  {
    "path": "src/modules/pinia.ts",
    "chars": 497,
    "preview": "import type { UserModule } from '~/types'\nimport { createPinia } from 'pinia'\n\n// Setup Pinia\n// https://pinia.vuejs.org"
  },
  {
    "path": "src/modules/pwa.ts",
    "chars": 400,
    "preview": "import type { UserModule } from '~/types'\n\n// https://github.com/antfu/vite-plugin-pwa#automatic-reload-when-new-content"
  },
  {
    "path": "src/pages/README.md",
    "chars": 423,
    "preview": "## File-based Routing\n\nRoutes will be auto-generated for Vue files in this dir with the same file structure.\nCheck out ["
  },
  {
    "path": "src/pages/[...all].vue",
    "chars": 175,
    "preview": "<script setup lang=\"ts\">\nconst { t } = useI18n()\n</script>\n\n<template>\n  <div>\n    {{ t('not-found') }}\n  </div>\n</templ"
  },
  {
    "path": "src/pages/about.md",
    "chars": 809,
    "preview": "---\ntitle: About\n---\n\n<script setup>\nconst { t } = useI18n()\nuseHead({ title: () => t('button.about') })\n</script>\n\n<div"
  },
  {
    "path": "src/pages/hi/[name].vue",
    "chars": 1082,
    "preview": "<script setup lang=\"ts\">\nconst router = useRouter()\nconst route = useRoute('/hi/[name]')\nconst user = useUserStore()\ncon"
  },
  {
    "path": "src/pages/index.vue",
    "chars": 1095,
    "preview": "<script setup lang=\"ts\">\ndefineOptions({\n  name: 'IndexPage',\n})\nconst user = useUserStore()\nconst name = ref(user.saved"
  },
  {
    "path": "src/route-map.d.ts",
    "chars": 2752,
    "preview": "/* eslint-disable */\n/* prettier-ignore */\n// oxfmt-ignore\n// @ts-nocheck\n// noinspection ES6UnusedImports\n// Generated "
  },
  {
    "path": "src/shims.d.ts",
    "chars": 444,
    "preview": "declare interface Window {\n  // extend the window\n}\n\n// with unplugin-vue-markdown, markdown files can be treated as Vue"
  },
  {
    "path": "src/stores/user.ts",
    "chars": 841,
    "preview": "import { acceptHMRUpdate, defineStore } from 'pinia'\n\nexport const useUserStore = defineStore('user', () => {\n  /**\n   *"
  },
  {
    "path": "src/styles/main.css",
    "chars": 349,
    "preview": "@import './markdown.css';\n\nhtml,\nbody,\n#app {\n  height: 100%;\n  margin: 0;\n  padding: 0;\n}\n\nhtml.dark {\n  background: #1"
  },
  {
    "path": "src/styles/markdown.css",
    "chars": 368,
    "preview": ".prose pre:not(.shiki) {\n  padding: 0;\n}\n\n.prose .shiki {\n  font-family: 'DM Mono', monospace;\n  font-size: 1.2em;\n  lin"
  },
  {
    "path": "src/types.ts",
    "chars": 103,
    "preview": "import type { ViteSSGContext } from 'vite-ssg'\n\nexport type UserModule = (ctx: ViteSSGContext) => void\n"
  },
  {
    "path": "test/__snapshots__/component.test.ts.snap",
    "chars": 203,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`component TheCounter.vue > should render 1`] = `"
  },
  {
    "path": "test/basic.test.ts",
    "chars": 139,
    "preview": "import { describe, expect, it } from 'vitest'\n\ndescribe('tests', () => {\n  it('should works', () => {\n    expect(1 + 1)."
  },
  {
    "path": "test/component.test.ts",
    "chars": 829,
    "preview": "import { mount } from '@vue/test-utils'\nimport { describe, expect, it } from 'vitest'\nimport TheCounter from '../src/com"
  },
  {
    "path": "tsconfig.json",
    "chars": 868,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"jsx\": \"preserve\",\n    \"lib\": [\"DOM\", \"ESNext\"],\n    \"baseUrl\": \".\""
  },
  {
    "path": "uno.config.ts",
    "chars": 1092,
    "preview": "import {\n  createLocalFontProcessor,\n} from '@unocss/preset-web-fonts/local'\nimport {\n  defineConfig,\n  presetAttributif"
  },
  {
    "path": "vite.config.ts",
    "chars": 4464,
    "preview": "import path from 'node:path'\nimport VueI18n from '@intlify/unplugin-vue-i18n/vite'\nimport Shiki from '@shikijs/markdown-"
  }
]

About this extraction

This page contains the full source code of the antfu-collective/vitesse GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 75 files (102.7 KB), approximately 30.6k tokens, and a symbol index with 15 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!