create-m2m-bo-template-vue 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 leemheeje
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,212 @@
1
+ # create-m2m-bo-template-vue
2
+
3
+ M2M 백오피스 vue 템플릿을 생성하는 스캐폴딩 CLI입니다.
4
+
5
+ 사용자가 아래 명령을 실행하면 이 저장소의 `template/` 폴더 내용이 대상 디렉토리로 복사됩니다.
6
+
7
+ ```bash
8
+ npm create m2m-bo-template-vue@latest my-app
9
+ # 또는
10
+ npx create-m2m-bo-template-vue my-app
11
+ ```
12
+
13
+ - npm 패키지: https://www.npmjs.com/package/create-m2m-bo-template-vue
14
+ - 버전 관리 / 배포: **완전 자동** (아래 [배포](#배포-cicd) 참고). 수동 `npm publish`·태그 생성 금지.
15
+
16
+ ---
17
+
18
+ ## 저장소 구조
19
+
20
+ ```
21
+ .
22
+ ├─ index.js # CLI 본체. template/ 를 대상 폴더로 복사하고 _파일 → .파일 로 rename
23
+ ├─ template/ # ★ 실제로 배포되는 프로젝트 원본. 여기에 소스/설정을 채운다
24
+ │ ├─ package.json # 생성될 프로젝트의 package.json (현재는 placeholder)
25
+ │ └─ _gitignore # 생성 시 .gitignore 로 변환됨
26
+ ├─ smoke-test.mjs # CI 테스트: 스캐폴드 실행 → 결과물 검증
27
+ ├─ .gitlab-ci.yml # 파이프라인 정의 (test / release)
28
+ ├─ .releaserc.json # semantic-release 설정
29
+ ├─ package.json # CLI 패키지 메타. version 은 semantic-release 가 관리
30
+ └─ .nvmrc # Node 버전 (22)
31
+ ```
32
+
33
+ ### `index.js` 동작
34
+
35
+ 1. 대상 디렉토리가 비어 있는지 확인 (비어있지 않으면 종료)
36
+ 2. `template/` 전체를 대상 디렉토리로 복사
37
+ 3. 대상 디렉토리 최상위에서 `_` 로 시작하는 **파일**을 `.` 로 시작하도록 rename
38
+ (`_gitignore` → `.gitignore`, `_npmrc` → `.npmrc` 등)
39
+
40
+ ---
41
+
42
+ ## 로컬 개발
43
+
44
+ Node.js 22 이상 필요 (`.nvmrc` 참고).
45
+
46
+ ```bash
47
+ npm install
48
+
49
+ npm test # smoke-test.mjs 실행. ./__smoke 에 스캐폴드 후 결과 검증, 끝나면 삭제
50
+ npm run lint # eslint (템플릿 폴더는 검사 대상 아님)
51
+ npm run format # prettier --check
52
+ npm start -- my-app # CLI 를 직접 실행해서 결과물 눈으로 확인
53
+ ```
54
+
55
+ ---
56
+
57
+ ## `template/` 작업 규칙
58
+
59
+ `template/` 안의 내용이 **그대로 최종 사용자에게 전달**됩니다. 배포하려는 실제 vue 프로젝트(소스, 설정 파일, 디렉토리 구조)를 이 폴더에 구성하세요.
60
+
61
+ | 규칙 | 이유 |
62
+ | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
63
+ | 점(`.`)으로 시작하는 파일은 `_` 접두사로 저장 (`_gitignore`, `_env.example` 등) | npm 은 배포 시 `.gitignore`·`.npmrc` 등 일부 점파일을 **자동으로 제외**함. `index.js` 가 복사 시 다시 `.` 로 바꿔줌 |
64
+ | `template/node_modules`, 빌드 산출물 커밋 금지 | 루트 `.gitignore` 에 이미 포함 |
65
+ | 템플릿 전용 lint/prettier 설정은 `template/` 안에 자체적으로 둔다 | 루트 도구가 `template/` 를 무시하도록 설정돼 있음 |
66
+ | `template/` 내용을 바꾸면 `smoke-test.mjs` 의 검증도 같이 보강한다 | 깨진 스캐폴드가 배포되는 것을 막기 위함 |
67
+
68
+ > 새 점파일을 추가할 때는 `index.js` 의 rename 로직이 최상위 파일만 처리한다는 점에 유의. 하위 디렉토리의 점파일이 필요하면 `index.js` 를 확장해야 합니다.
69
+
70
+ ---
71
+
72
+ ## 배포 (CI/CD)
73
+
74
+ ### 인프라
75
+
76
+ - **GitLab CI** (`.gitlab-ci.yml`) 로 동작
77
+ - 실행 주체: 사내 **Windows self-hosted runner** (shell executor, pwsh)
78
+ - 러너 호스트에 `node`(22+), `npm`, `git` 이 PATH 에 있어야 함
79
+ - 러너가 태그 제한 + "Run untagged jobs" 꺼짐 상태면 `.gitlab-ci.yml` 의 `default:` 에 `tags: [<러너태그>]` 추가 필요
80
+ - 릴리스 자동화: **[semantic-release](https://semantic-release.gitbook.io/)** (`.releaserc.json`)
81
+
82
+ ### 파이프라인 잡
83
+
84
+ | Job | 실행 시점 | 내용 |
85
+ | --------- | --------------------------------- | -------------------------------------------------------------------------------------------- |
86
+ | `test` | Merge Request 이벤트, `main` push | `node smoke-test.mjs` — 스캐폴드가 정상 동작하는지 검증 |
87
+ | `release` | **`main` push 만** | `npx semantic-release` — 버전 결정 → npm publish → GitLab Release/태그 생성 → 버전 반영 커밋 |
88
+
89
+ ### 배포 트리거
90
+
91
+ > **`main` 브랜치에 커밋이 올라가야만 배포 파이프라인(`release`)이 돕니다.**
92
+ > feature 브랜치 push 나 MR 단계에서는 `test` 만 돌고 배포되지 않습니다.
93
+
94
+ `release` 잡에서 semantic-release 가 하는 일:
95
+
96
+ 1. 마지막 릴리스 태그 이후의 커밋 메시지를 분석해 다음 버전을 계산
97
+ 2. 릴리스할 변경이 없으면(예: `chore:` 커밋만 있음) **아무것도 하지 않고 종료**
98
+ 3. `package.json` 의 `version` 을 새 버전으로 갱신
99
+ 4. `npm publish` 로 npmjs.com 에 배포
100
+ 5. GitLab Release 와 `vX.Y.Z` 태그 생성, 릴리스 노트 자동 작성
101
+ 6. 갱신된 `package.json` 을 `main` 에 `chore(release): X.Y.Z [skip ci]` 커밋으로 되돌림
102
+
103
+ ---
104
+
105
+ ## 커밋 메시지 규칙 (필수)
106
+
107
+ 버전과 릴리스 여부는 **커밋 메시지로 결정**됩니다. [Conventional Commits](https://www.conventionalcommits.org/) 형식을 반드시 지키세요.
108
+
109
+ ```
110
+ <type>(<scope>): <제목>
111
+
112
+ <본문 - 선택>
113
+
114
+ <footer - 선택>
115
+ ```
116
+
117
+ ### type 별 동작
118
+
119
+ | type | 버전 변화 | 예시 |
120
+ | ------------------------------------------------------------------- | ------------------------- | ------------------------------------------ |
121
+ | `fix` | patch (1.0.0 → 1.0.**1**) | `fix: 스캐폴드 시 빈 폴더 검사 누락 수정` |
122
+ | `feat` | minor (1.0.0 → 1.**1**.0) | `feat: vite + vue + ts 기본 템플릿 추가` |
123
+ | `feat` / `fix` + **BREAKING CHANGE** | major (1.0.0 → **2**.0.0) | 아래 참고 |
124
+ | `chore`, `docs`, `ci`, `refactor`, `test`, `style`, `perf`, `build` | **릴리스 없음** | `docs: README 배포 절차 보강` |
125
+
126
+ > `perf` 는 설정에 따라 patch 가 될 수 있으나 현재 설정에서는 릴리스되지 않습니다. 성능 개선이 사용자에게 영향 있으면 `fix` 로 커밋하세요.
127
+
128
+ ### BREAKING CHANGE (major)
129
+
130
+ 두 가지 방법 중 하나:
131
+
132
+ ```
133
+ feat!: 템플릿 최소 Node 버전을 20 → 22 로 상향
134
+ ```
135
+
136
+ 또는 footer 에 명시:
137
+
138
+ ```
139
+ feat: 라우팅 구조 전면 개편
140
+
141
+ BREAKING CHANGE: pages 디렉토리 규칙이 바뀌어 기존 생성물과 호환되지 않음
142
+ ```
143
+
144
+ ### scope (선택, 권장)
145
+
146
+ 변경 범위를 괄호로 표기하면 릴리스 노트 가독성이 좋아집니다.
147
+
148
+ ```
149
+ feat(template): 공통 레이아웃 컴포넌트 추가
150
+ fix(cli): 대상 경로에 공백이 있을 때 처리
151
+ ci: 러너 태그 설정 추가
152
+ ```
153
+
154
+ ### 규칙 위반 시
155
+
156
+ - type 없이 커밋(`템플릿 수정함`)하면 semantic-release 가 무시 → **배포 안 됨**
157
+ - 여러 변경을 한 커밋에 섞지 말 것. 가장 큰 영향의 type 으로 집계됩니다.
158
+
159
+ ---
160
+
161
+ ## 작업 → 배포 흐름
162
+
163
+ ```
164
+ 1. 브랜치 생성 git switch -c feat/base-template
165
+ 2. template/ 작업 + smoke-test 보강
166
+ 3. 커밋 git commit -m "feat(template): vite vue ts 기본 구조 추가"
167
+ 4. push & MR 생성 → 파이프라인에서 test 잡 통과 확인
168
+ 5. MR 을 main 으로 머지 (Squash 시 커밋 메시지도 Conventional Commits 형식 유지)
169
+ 6. main 파이프라인 release 잡이 semantic-release 실행 → npm 자동 배포
170
+ 7. 결과 확인 GitLab → Deployments/Releases, npmjs.com 버전
171
+ ```
172
+
173
+ ### 주의
174
+
175
+ - **`package.json` 의 `version` 을 직접 수정하지 마세요.** semantic-release 가 관리합니다.
176
+ - **수동으로 `git tag` 를 만들거나 `npm publish` 하지 마세요.**
177
+ - MR Squash 머지를 쓴다면, 머지 커밋 제목이 최종 커밋 메시지가 되므로 형식을 지켜야 합니다.
178
+
179
+ ---
180
+
181
+ ## 필수 CI/CD 변수
182
+
183
+ **Settings → CI/CD → Variables** 에 등록 (프로젝트 관리자 작업).
184
+
185
+ | Key | 값 | 플래그 |
186
+ | -------------- | ---------------------------------------------------------------------- | ----------------- |
187
+ | `NPM_TOKEN` | npm **Automation** 액세스 토큰 (npmjs.com → Access Tokens) | Masked |
188
+ | `GITLAB_TOKEN` | GitLab 액세스 토큰, scope: `api`, `write_repository`, role: Maintainer | Masked, Protected |
189
+
190
+ - `@semantic-release/npm` 이 `NPM_TOKEN` 을 `.npmrc` 에 자동으로 씁니다.
191
+ - `GITLAB_TOKEN` 은 Release 생성(`api`)과 버전 커밋 push(`write_repository`)에 사용됩니다.
192
+ - `main` 이 protected 브랜치면 해당 토큰 사용자가 push 가능해야 합니다
193
+ (Settings → Repository → Protected branches → Allowed to push).
194
+
195
+ ---
196
+
197
+ ## 트러블슈팅
198
+
199
+ | 증상 | 원인 / 조치 |
200
+ | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
201
+ | 파이프라인이 계속 `pending` | 프로젝트에 러너 미할당. Settings → CI/CD → Runners 에서 러너 활성화. 태그 불일치면 `.gitlab-ci.yml` 의 `tags:` 조정 |
202
+ | `node: command not found` / `npm ci` 실패 | 러너 호스트에 Node 22+ / npm / git 미설치 |
203
+ | semantic-release `shallow clone` 경고 후 실패 | CI/CD Variables 에 `GIT_DEPTH = 0` 추가 |
204
+ | `@semantic-release/git` push 거부 | protected `main` 에 토큰 사용자 push 권한 부여, 또는 `.releaserc.json` 에서 해당 플러그인 제거 |
205
+ | npm publish `403` | `NPM_TOKEN` 이 Automation 타입인지, 패키지명 소유권/2FA 정책 확인 |
206
+ | `main` 에 push 했는데 버전이 안 오름 | 커밋에 `feat`/`fix` 가 없음 (`chore` 등만 있으면 정상적으로 릴리스 생략됨) |
207
+
208
+ ---
209
+
210
+ ## License
211
+
212
+ MIT
package/index.js ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ // Scaffolding CLI for the M2M back-office vue template.
3
+ //
4
+ // Usage:
5
+ // npm create m2m-bo-template-vue@latest <target-dir>
6
+ // npx create-m2m-bo-template-vue <target-dir>
7
+ //
8
+ // Copies everything under ./template into <target-dir>. Files named `_gitignore`
9
+ // (etc.) are written with the leading underscore replaced by a dot, because npm
10
+ // strips real dotfiles from published packages.
11
+
12
+ import { cpSync, existsSync, readdirSync, renameSync, statSync } from "node:fs";
13
+ import { join } from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+
16
+ const templateDir = fileURLToPath(new URL("./template", import.meta.url));
17
+ const targetDir = process.argv[2] ?? ".";
18
+
19
+ if (!existsSync(templateDir)) {
20
+ console.error(`template directory not found: ${templateDir}`);
21
+ process.exit(1);
22
+ }
23
+
24
+ if (existsSync(targetDir) && readdirSync(targetDir).length > 0) {
25
+ console.error(`target directory is not empty: ${targetDir}`);
26
+ process.exit(1);
27
+ }
28
+
29
+ cpSync(templateDir, targetDir, { recursive: true });
30
+
31
+ // _gitignore -> .gitignore, _npmrc -> .npmrc, ...
32
+ for (const entry of readdirSync(targetDir)) {
33
+ if (entry.startsWith("_") && statSync(join(targetDir, entry)).isFile()) {
34
+ renameSync(join(targetDir, entry), join(targetDir, `.${entry.slice(1)}`));
35
+ }
36
+ }
37
+
38
+ console.log(`Scaffolded M2M BO vue template into: ${targetDir}`);
39
+ console.log("Next steps:");
40
+ console.log(` cd ${targetDir}`);
41
+ console.log(" npm install");
42
+ console.log(" npm run dev");
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "create-m2m-bo-template-vue",
3
+ "version": "1.0.1",
4
+ "description": "Scaffolding CLI for the M2M back-office vue template.",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-m2m-bo-template-vue": "index.js"
8
+ },
9
+ "files": [
10
+ "index.js",
11
+ "template"
12
+ ],
13
+ "engines": {
14
+ "node": ">=20"
15
+ },
16
+ "scripts": {
17
+ "lint": "eslint .",
18
+ "format": "prettier --check .",
19
+ "test": "node smoke-test.mjs",
20
+ "start": "node index.js",
21
+ "release": "semantic-release"
22
+ },
23
+ "keywords": [
24
+ "create",
25
+ "template",
26
+ "vue",
27
+ "back-office",
28
+ "boilerplate",
29
+ "scaffold"
30
+ ],
31
+ "license": "MIT",
32
+ "author": "leemheeje",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "http://192.168.0.87/ux/bo-template-vue.git"
36
+ },
37
+ "publishConfig": {
38
+ "registry": "https://registry.npmjs.org/",
39
+ "access": "public"
40
+ },
41
+ "devDependencies": {
42
+ "@eslint/js": "^9.13.0",
43
+ "@semantic-release/git": "^11.0.1",
44
+ "@semantic-release/gitlab": "^13.3.3",
45
+ "eslint": "^9.13.0",
46
+ "prettier": "^3.3.3",
47
+ "semantic-release": "^25.0.9"
48
+ },
49
+ "dependencies": {
50
+ "vite": "^8.2.2"
51
+ }
52
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["Vue.volar"]
3
+ }
@@ -0,0 +1,5 @@
1
+ # Vue 3 + TypeScript + Vite
2
+
3
+ This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
4
+
5
+ Learn more about the recommended Project Setup and IDE Support in the [Vue Docs TypeScript Guide](https://vuejs.org/guide/typescript/overview.html#project-setup).
@@ -0,0 +1,24 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
+
15
+ # Editor directories and files
16
+ .vscode/*
17
+ !.vscode/extensions.json
18
+ .idea
19
+ .DS_Store
20
+ *.suo
21
+ *.ntvs*
22
+ *.njsproj
23
+ *.sln
24
+ *.sw?
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>template</title>
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="/src/main.ts"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "template",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vue-tsc -b && vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "vue": "^3.5.41"
13
+ },
14
+ "devDependencies": {
15
+ "@types/node": "^24.13.3",
16
+ "@vitejs/plugin-vue": "^6.0.8",
17
+ "@vue/tsconfig": "^0.9.1",
18
+ "typescript": "~6.0.2",
19
+ "vite": "^8.2.2",
20
+ "vue-tsc": "^3.3.11"
21
+ }
22
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="48" height="46" fill="none" viewBox="0 0 48 46"><path fill="#863bff" d="M25.946 44.938c-.664.845-2.021.375-2.021-.698V33.937a2.26 2.26 0 0 0-2.262-2.262H10.287c-.92 0-1.456-1.04-.92-1.788l7.48-10.471c1.07-1.497 0-3.578-1.842-3.578H1.237c-.92 0-1.456-1.04-.92-1.788L10.013.474c.214-.297.556-.474.92-.474h28.894c.92 0 1.456 1.04.92 1.788l-7.48 10.471c-1.07 1.498 0 3.579 1.842 3.579h11.377c.943 0 1.473 1.088.89 1.83L25.947 44.94z" style="fill:#863bff;fill:color(display-p3 .5252 .23 1);fill-opacity:1"/><mask id="a" width="48" height="46" x="0" y="0" maskUnits="userSpaceOnUse" style="mask-type:alpha"><path fill="#000" d="M25.842 44.938c-.664.844-2.021.375-2.021-.698V33.937a2.26 2.26 0 0 0-2.262-2.262H10.183c-.92 0-1.456-1.04-.92-1.788l7.48-10.471c1.07-1.498 0-3.579-1.842-3.579H1.133c-.92 0-1.456-1.04-.92-1.787L9.91.473c.214-.297.556-.474.92-.474h28.894c.92 0 1.456 1.04.92 1.788l-7.48 10.471c-1.07 1.498 0 3.578 1.842 3.578h11.377c.943 0 1.473 1.088.89 1.832L25.843 44.94z" style="fill:#000;fill-opacity:1"/></mask><g mask="url(#a)"><g filter="url(#b)"><ellipse cx="5.508" cy="14.704" fill="#ede6ff" rx="5.508" ry="14.704" style="fill:#ede6ff;fill:color(display-p3 .9275 .9033 1);fill-opacity:1" transform="matrix(.00324 1 1 -.00324 -4.47 31.516)"/></g><g filter="url(#c)"><ellipse cx="10.399" cy="29.851" fill="#ede6ff" rx="10.399" ry="29.851" style="fill:#ede6ff;fill:color(display-p3 .9275 .9033 1);fill-opacity:1" transform="matrix(.00324 1 1 -.00324 -39.328 7.883)"/></g><g filter="url(#d)"><ellipse cx="5.508" cy="30.487" fill="#7e14ff" rx="5.508" ry="30.487" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.814 -25.913 -14.639)scale(1 -1)"/></g><g filter="url(#e)"><ellipse cx="5.508" cy="30.599" fill="#7e14ff" rx="5.508" ry="30.599" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.814 -32.644 -3.334)scale(1 -1)"/></g><g filter="url(#f)"><ellipse cx="5.508" cy="30.599" fill="#7e14ff" rx="5.508" ry="30.599" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="matrix(.00324 1 1 -.00324 -34.34 30.47)"/></g><g filter="url(#g)"><ellipse cx="14.072" cy="22.078" fill="#ede6ff" rx="14.072" ry="22.078" style="fill:#ede6ff;fill:color(display-p3 .9275 .9033 1);fill-opacity:1" transform="rotate(93.35 24.506 48.493)scale(-1 1)"/></g><g filter="url(#h)"><ellipse cx="3.47" cy="21.501" fill="#7e14ff" rx="3.47" ry="21.501" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.009 28.708 47.59)scale(-1 1)"/></g><g filter="url(#i)"><ellipse cx="3.47" cy="21.501" fill="#7e14ff" rx="3.47" ry="21.501" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.009 28.708 47.59)scale(-1 1)"/></g><g filter="url(#j)"><ellipse cx=".387" cy="8.972" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(39.51 .387 8.972)"/></g><g filter="url(#k)"><ellipse cx="47.523" cy="-6.092" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 47.523 -6.092)"/></g><g filter="url(#l)"><ellipse cx="41.412" cy="6.333" fill="#47bfff" rx="5.971" ry="9.665" style="fill:#47bfff;fill:color(display-p3 .2799 .748 1);fill-opacity:1" transform="rotate(37.892 41.412 6.333)"/></g><g filter="url(#m)"><ellipse cx="-1.879" cy="38.332" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 -1.88 38.332)"/></g><g filter="url(#n)"><ellipse cx="-1.879" cy="38.332" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 -1.88 38.332)"/></g><g filter="url(#o)"><ellipse cx="35.651" cy="29.907" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 35.651 29.907)"/></g><g filter="url(#p)"><ellipse cx="38.418" cy="32.4" fill="#47bfff" rx="5.971" ry="15.297" style="fill:#47bfff;fill:color(display-p3 .2799 .748 1);fill-opacity:1" transform="rotate(37.892 38.418 32.4)"/></g></g><defs><filter id="b" width="60.045" height="41.654" x="-19.77" y="16.149" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="7.659"/></filter><filter id="c" width="90.34" height="51.437" x="-54.613" y="-7.533" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="7.659"/></filter><filter id="d" width="79.355" height="29.4" x="-49.64" y="2.03" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="e" width="79.579" height="29.4" x="-45.045" y="20.029" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="f" width="79.579" height="29.4" x="-43.513" y="21.178" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="g" width="74.749" height="58.852" x="15.756" y="-17.901" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="7.659"/></filter><filter id="h" width="61.377" height="25.362" x="23.548" y="2.284" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="i" width="61.377" height="25.362" x="23.548" y="2.284" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="j" width="56.045" height="63.649" x="-27.636" y="-22.853" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="k" width="54.814" height="64.646" x="20.116" y="-38.415" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="l" width="33.541" height="35.313" x="24.641" y="-11.323" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="m" width="54.814" height="64.646" x="-29.286" y="6.009" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="n" width="54.814" height="64.646" x="-29.286" y="6.009" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="o" width="54.814" height="64.646" x="8.244" y="-2.416" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="p" width="39.409" height="43.623" x="18.713" y="10.588" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter></defs></svg>
@@ -0,0 +1,24 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg">
2
+ <symbol id="bluesky-icon" viewBox="0 0 16 17">
3
+ <g clip-path="url(#bluesky-clip)"><path fill="#08060d" d="M7.75 7.735c-.693-1.348-2.58-3.86-4.334-5.097-1.68-1.187-2.32-.981-2.74-.79C.188 2.065.1 2.812.1 3.251s.241 3.602.398 4.13c.52 1.744 2.367 2.333 4.07 2.145-2.495.37-4.71 1.278-1.805 4.512 3.196 3.309 4.38-.71 4.987-2.746.608 2.036 1.307 5.91 4.93 2.746 2.72-2.746.747-4.143-1.747-4.512 1.702.189 3.55-.4 4.07-2.145.156-.528.397-3.691.397-4.13s-.088-1.186-.575-1.406c-.42-.19-1.06-.395-2.741.79-1.755 1.24-3.64 3.752-4.334 5.099"/></g>
4
+ <defs><clipPath id="bluesky-clip"><path fill="#fff" d="M.1.85h15.3v15.3H.1z"/></clipPath></defs>
5
+ </symbol>
6
+ <symbol id="discord-icon" viewBox="0 0 20 19">
7
+ <path fill="#08060d" d="M16.224 3.768a14.5 14.5 0 0 0-3.67-1.153c-.158.286-.343.67-.47.976a13.5 13.5 0 0 0-4.067 0c-.128-.306-.317-.69-.476-.976A14.4 14.4 0 0 0 3.868 3.77C1.546 7.28.916 10.703 1.231 14.077a14.7 14.7 0 0 0 4.5 2.306q.545-.748.965-1.587a9.5 9.5 0 0 1-1.518-.74q.191-.14.372-.293c2.927 1.369 6.107 1.369 8.999 0q.183.152.372.294-.723.437-1.52.74.418.838.963 1.588a14.6 14.6 0 0 0 4.504-2.308c.37-3.911-.63-7.302-2.644-10.309m-9.13 8.234c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.894 0 1.614.82 1.599 1.82.001 1-.705 1.82-1.6 1.82m5.91 0c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.893 0 1.614.82 1.599 1.82 0 1-.706 1.82-1.6 1.82"/>
8
+ </symbol>
9
+ <symbol id="documentation-icon" viewBox="0 0 21 20">
10
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="m15.5 13.333 1.533 1.322c.645.555.967.833.967 1.178s-.322.623-.967 1.179L15.5 18.333m-3.333-5-1.534 1.322c-.644.555-.966.833-.966 1.178s.322.623.966 1.179l1.534 1.321"/>
11
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M17.167 10.836v-4.32c0-1.41 0-2.117-.224-2.68-.359-.906-1.118-1.621-2.08-1.96-.599-.21-1.349-.21-2.848-.21-2.623 0-3.935 0-4.983.369-1.684.591-3.013 1.842-3.641 3.428C3 6.449 3 7.684 3 10.154v2.122c0 2.558 0 3.838.706 4.726q.306.383.713.671c.76.536 1.79.64 3.581.66"/>
12
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M3 10a2.78 2.78 0 0 1 2.778-2.778c.555 0 1.209.097 1.748-.047.48-.129.854-.503.982-.982.145-.54.048-1.194.048-1.749a2.78 2.78 0 0 1 2.777-2.777"/>
13
+ </symbol>
14
+ <symbol id="github-icon" viewBox="0 0 19 19">
15
+ <path fill="#08060d" fill-rule="evenodd" d="M9.356 1.85C5.05 1.85 1.57 5.356 1.57 9.694a7.84 7.84 0 0 0 5.324 7.44c.387.079.528-.168.528-.376 0-.182-.013-.805-.013-1.454-2.165.467-2.616-.935-2.616-.935-.349-.91-.864-1.143-.864-1.143-.71-.48.051-.48.051-.48.787.051 1.2.805 1.2.805.695 1.194 1.817.857 2.268.649.064-.507.27-.857.49-1.052-1.728-.182-3.545-.857-3.545-3.87 0-.857.31-1.558.8-2.104-.078-.195-.349-1 .077-2.078 0 0 .657-.208 2.14.805a7.5 7.5 0 0 1 1.946-.26c.657 0 1.328.092 1.946.26 1.483-1.013 2.14-.805 2.14-.805.426 1.078.155 1.883.078 2.078.502.546.799 1.247.799 2.104 0 3.013-1.818 3.675-3.558 3.87.284.247.528.714.528 1.454 0 1.052-.012 1.896-.012 2.156 0 .208.142.455.528.377a7.84 7.84 0 0 0 5.324-7.441c.013-4.338-3.48-7.844-7.773-7.844" clip-rule="evenodd"/>
16
+ </symbol>
17
+ <symbol id="social-icon" viewBox="0 0 20 20">
18
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M12.5 6.667a4.167 4.167 0 1 0-8.334 0 4.167 4.167 0 0 0 8.334 0"/>
19
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M2.5 16.667a5.833 5.833 0 0 1 8.75-5.053m3.837.474.513 1.035c.07.144.257.282.414.309l.93.155c.596.1.736.536.307.965l-.723.73a.64.64 0 0 0-.152.531l.207.903c.164.715-.213.991-.84.618l-.872-.52a.63.63 0 0 0-.577 0l-.872.52c-.624.373-1.003.094-.84-.618l.207-.903a.64.64 0 0 0-.152-.532l-.723-.729c-.426-.43-.289-.864.306-.964l.93-.156a.64.64 0 0 0 .412-.31l.513-1.034c.28-.562.735-.562 1.012 0"/>
20
+ </symbol>
21
+ <symbol id="x-icon" viewBox="0 0 19 19">
22
+ <path fill="#08060d" fill-rule="evenodd" d="M1.893 1.98c.052.072 1.245 1.769 2.653 3.77l2.892 4.114c.183.261.333.48.333.486s-.068.089-.152.183l-.522.593-.765.867-3.597 4.087c-.375.426-.734.834-.798.905a1 1 0 0 0-.118.148c0 .01.236.017.664.017h.663l.729-.83c.4-.457.796-.906.879-.999a692 692 0 0 0 1.794-2.038c.034-.037.301-.34.594-.675l.551-.624.345-.392a7 7 0 0 1 .34-.374c.006 0 .93 1.306 2.052 2.903l2.084 2.965.045.063h2.275c1.87 0 2.273-.003 2.266-.021-.008-.02-1.098-1.572-3.894-5.547-2.013-2.862-2.28-3.246-2.273-3.266.008-.019.282-.332 2.085-2.38l2-2.274 1.567-1.782c.022-.028-.016-.03-.65-.03h-.674l-.3.342a871 871 0 0 1-1.782 2.025c-.067.075-.405.458-.75.852a100 100 0 0 1-.803.91c-.148.172-.299.344-.99 1.127-.304.343-.32.358-.345.327-.015-.019-.904-1.282-1.976-2.808L6.365 1.85H1.8zm1.782.91 8.078 11.294c.772 1.08 1.413 1.973 1.425 1.984.016.017.241.02 1.05.017l1.03-.004-2.694-3.766L7.796 5.75 5.722 2.852l-1.039-.004-1.039-.004z" clip-rule="evenodd"/>
23
+ </symbol>
24
+ </svg>
@@ -0,0 +1,7 @@
1
+ <script setup lang="ts">
2
+ import HelloWorld from './components/HelloWorld.vue'
3
+ </script>
4
+
5
+ <template>
6
+ <HelloWorld />
7
+ </template>
Binary file
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="77" height="47" fill="none" aria-labelledby="vite-logo-title" viewBox="0 0 77 47"><title id="vite-logo-title">Vite</title><style>.parenthesis{fill:#000}@media (prefers-color-scheme:dark){.parenthesis{fill:#fff}}</style><path fill="#9135ff" d="M40.151 45.71c-.663.844-2.02.374-2.02-.699V34.708a2.26 2.26 0 0 0-2.262-2.262H24.493c-.92 0-1.457-1.04-.92-1.788l7.479-10.471c1.07-1.498 0-3.578-1.842-3.578H15.443c-.92 0-1.456-1.04-.92-1.788l9.696-13.576c.213-.297.556-.474.92-.474h28.894c.92 0 1.456 1.04.92 1.788l-7.48 10.472c-1.07 1.497 0 3.578 1.842 3.578h11.376c.944 0 1.474 1.087.89 1.83L40.153 45.712z"/><mask id="a" width="48" height="47" x="14" y="0" maskUnits="userSpaceOnUse" style="mask-type:alpha"><path fill="#000" d="M40.047 45.71c-.663.843-2.02.374-2.02-.699V34.708a2.26 2.26 0 0 0-2.262-2.262H24.389c-.92 0-1.457-1.04-.92-1.788l7.479-10.472c1.07-1.497 0-3.578-1.842-3.578H15.34c-.92 0-1.456-1.04-.92-1.788l9.696-13.575c.213-.297.556-.474.92-.474H53.93c.92 0 1.456 1.04.92 1.788L47.37 13.03c-1.07 1.498 0 3.578 1.842 3.578h11.376c.944 0 1.474 1.088.89 1.831L40.049 45.712z"/></mask><g mask="url(#a)"><g filter="url(#b)"><ellipse cx="5.508" cy="14.704" fill="#eee6ff" rx="5.508" ry="14.704" transform="rotate(269.814 20.96 11.29)scale(-1 1)"/></g><g filter="url(#c)"><ellipse cx="10.399" cy="29.851" fill="#eee6ff" rx="10.399" ry="29.851" transform="rotate(89.814 -16.902 -8.275)scale(1 -1)"/></g><g filter="url(#d)"><ellipse cx="5.508" cy="30.487" fill="#8900ff" rx="5.508" ry="30.487" transform="rotate(89.814 -19.197 -7.127)scale(1 -1)"/></g><g filter="url(#e)"><ellipse cx="5.508" cy="30.599" fill="#8900ff" rx="5.508" ry="30.599" transform="rotate(89.814 -25.928 4.177)scale(1 -1)"/></g><g filter="url(#f)"><ellipse cx="5.508" cy="30.599" fill="#8900ff" rx="5.508" ry="30.599" transform="rotate(89.814 -25.738 5.52)scale(1 -1)"/></g><g filter="url(#g)"><ellipse cx="14.072" cy="22.078" fill="#eee6ff" rx="14.072" ry="22.078" transform="rotate(93.35 31.245 55.578)scale(-1 1)"/></g><g filter="url(#h)"><ellipse cx="3.47" cy="21.501" fill="#8900ff" rx="3.47" ry="21.501" transform="rotate(89.009 35.419 55.202)scale(-1 1)"/></g><g filter="url(#i)"><ellipse cx="3.47" cy="21.501" fill="#8900ff" rx="3.47" ry="21.501" transform="rotate(89.009 35.419 55.202)scale(-1 1)"/></g><g filter="url(#j)"><ellipse cx="14.592" cy="9.743" fill="#8900ff" rx="4.407" ry="29.108" transform="rotate(39.51 14.592 9.743)"/></g><g filter="url(#k)"><ellipse cx="61.728" cy="-5.321" fill="#8900ff" rx="4.407" ry="29.108" transform="rotate(37.892 61.728 -5.32)"/></g><g filter="url(#l)"><ellipse cx="55.618" cy="7.104" fill="#00c2ff" rx="5.971" ry="9.665" transform="rotate(37.892 55.618 7.104)"/></g><g filter="url(#m)"><ellipse cx="12.326" cy="39.103" fill="#8900ff" rx="4.407" ry="29.108" transform="rotate(37.892 12.326 39.103)"/></g><g filter="url(#n)"><ellipse cx="12.326" cy="39.103" fill="#8900ff" rx="4.407" ry="29.108" transform="rotate(37.892 12.326 39.103)"/></g><g filter="url(#o)"><ellipse cx="49.857" cy="30.678" fill="#8900ff" rx="4.407" ry="29.108" transform="rotate(37.892 49.857 30.678)"/></g><g filter="url(#p)"><ellipse cx="52.623" cy="33.171" fill="#00c2ff" rx="5.971" ry="15.297" transform="rotate(37.892 52.623 33.17)"/></g></g><path d="M6.919 0c-9.198 13.166-9.252 33.575 0 46.789h6.215c-9.25-13.214-9.196-33.623 0-46.789zm62.424 0h-6.215c9.198 13.166 9.252 33.575 0 46.789h6.215c9.25-13.214 9.196-33.623 0-46.789" class="parenthesis"/><defs><filter id="b" width="60.045" height="41.654" x="-5.564" y="16.92" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="7.659"/></filter><filter id="c" width="90.34" height="51.437" x="-40.407" y="-6.762" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="7.659"/></filter><filter id="d" width="79.355" height="29.4" x="-35.435" y="2.801" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="e" width="79.579" height="29.4" x="-30.84" y="20.8" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="f" width="79.579" height="29.4" x="-29.307" y="21.949" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="g" width="74.749" height="58.852" x="29.961" y="-17.13" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="7.659"/></filter><filter id="h" width="61.377" height="25.362" x="37.754" y="3.055" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="i" width="61.377" height="25.362" x="37.754" y="3.055" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="j" width="56.045" height="63.649" x="-13.43" y="-22.082" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="k" width="54.814" height="64.646" x="34.321" y="-37.644" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="l" width="33.541" height="35.313" x="38.847" y="-10.552" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="m" width="54.814" height="64.646" x="-15.081" y="6.78" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="n" width="54.814" height="64.646" x="-15.081" y="6.78" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="o" width="54.814" height="64.646" x="22.45" y="-1.645" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="p" width="39.409" height="43.623" x="32.919" y="11.36" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter></defs></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
@@ -0,0 +1,95 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ import heroImg from '../assets/hero.png'
4
+ import viteLogo from '../assets/vite.svg'
5
+ import vueLogo from '../assets/vue.svg'
6
+
7
+ const count = ref(0)
8
+ </script>
9
+
10
+ <template>
11
+ <section id="center">
12
+ <div class="hero">
13
+ <img :src="heroImg" class="base" width="170" height="179" alt="" />
14
+ <img :src="vueLogo" class="framework" alt="Vue logo" />
15
+ <img :src="viteLogo" class="vite" alt="Vite logo" />
16
+ </div>
17
+ <div>
18
+ <h1>Get started</h1>
19
+ <p>Edit <code>src/App.vue</code> and save to test <code>HMR</code></p>
20
+ </div>
21
+ <button type="button" class="counter" @click="count++">
22
+ Count is {{ count }}
23
+ </button>
24
+ </section>
25
+
26
+ <div class="ticks"></div>
27
+
28
+ <section id="next-steps">
29
+ <div id="docs">
30
+ <svg class="icon" role="presentation" aria-hidden="true">
31
+ <use href="/icons.svg#documentation-icon"></use>
32
+ </svg>
33
+ <h2>Documentation</h2>
34
+ <p>Your questions, answered</p>
35
+ <ul>
36
+ <li>
37
+ <a href="https://vite.dev/" target="_blank">
38
+ <img class="logo" :src="viteLogo" alt="" />
39
+ Explore Vite
40
+ </a>
41
+ </li>
42
+ <li>
43
+ <a href="https://vuejs.org/" target="_blank">
44
+ <img class="button-icon" :src="vueLogo" alt="" />
45
+ Learn more
46
+ </a>
47
+ </li>
48
+ </ul>
49
+ </div>
50
+ <div id="social">
51
+ <svg class="icon" role="presentation" aria-hidden="true">
52
+ <use href="/icons.svg#social-icon"></use>
53
+ </svg>
54
+ <h2>Connect with us</h2>
55
+ <p>Join the Vite community</p>
56
+ <ul>
57
+ <li>
58
+ <a href="https://github.com/vitejs/vite" target="_blank">
59
+ <svg class="button-icon" role="presentation" aria-hidden="true">
60
+ <use href="/icons.svg#github-icon"></use>
61
+ </svg>
62
+ GitHub
63
+ </a>
64
+ </li>
65
+ <li>
66
+ <a href="https://chat.vite.dev/" target="_blank">
67
+ <svg class="button-icon" role="presentation" aria-hidden="true">
68
+ <use href="/icons.svg#discord-icon"></use>
69
+ </svg>
70
+ Discord
71
+ </a>
72
+ </li>
73
+ <li>
74
+ <a href="https://x.com/vite_js" target="_blank">
75
+ <svg class="button-icon" role="presentation" aria-hidden="true">
76
+ <use href="/icons.svg#x-icon"></use>
77
+ </svg>
78
+ X.com
79
+ </a>
80
+ </li>
81
+ <li>
82
+ <a href="https://bsky.app/profile/vite.dev" target="_blank">
83
+ <svg class="button-icon" role="presentation" aria-hidden="true">
84
+ <use href="/icons.svg#bluesky-icon"></use>
85
+ </svg>
86
+ Bluesky
87
+ </a>
88
+ </li>
89
+ </ul>
90
+ </div>
91
+ </section>
92
+
93
+ <div class="ticks"></div>
94
+ <section id="spacer"></section>
95
+ </template>
@@ -0,0 +1,5 @@
1
+ import { createApp } from 'vue'
2
+ import './style.css'
3
+ import App from './App.vue'
4
+
5
+ createApp(App).mount('#app')
@@ -0,0 +1,296 @@
1
+ :root {
2
+ --text: #6b6375;
3
+ --text-h: #08060d;
4
+ --bg: #fff;
5
+ --border: #e5e4e7;
6
+ --code-bg: #f4f3ec;
7
+ --accent: #aa3bff;
8
+ --accent-bg: rgba(170, 59, 255, 0.1);
9
+ --accent-border: rgba(170, 59, 255, 0.5);
10
+ --social-bg: rgba(244, 243, 236, 0.5);
11
+ --shadow:
12
+ rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;
13
+
14
+ --sans: system-ui, 'Segoe UI', Roboto, sans-serif;
15
+ --heading: system-ui, 'Segoe UI', Roboto, sans-serif;
16
+ --mono: ui-monospace, Consolas, monospace;
17
+
18
+ font: 18px/145% var(--sans);
19
+ letter-spacing: 0.18px;
20
+ color-scheme: light dark;
21
+ color: var(--text);
22
+ background: var(--bg);
23
+ font-synthesis: none;
24
+ text-rendering: optimizeLegibility;
25
+ -webkit-font-smoothing: antialiased;
26
+ -moz-osx-font-smoothing: grayscale;
27
+
28
+ @media (max-width: 1024px) {
29
+ font-size: 16px;
30
+ }
31
+ }
32
+
33
+ @media (prefers-color-scheme: dark) {
34
+ :root {
35
+ --text: #9ca3af;
36
+ --text-h: #f3f4f6;
37
+ --bg: #16171d;
38
+ --border: #2e303a;
39
+ --code-bg: #1f2028;
40
+ --accent: #c084fc;
41
+ --accent-bg: rgba(192, 132, 252, 0.15);
42
+ --accent-border: rgba(192, 132, 252, 0.5);
43
+ --social-bg: rgba(47, 48, 58, 0.5);
44
+ --shadow:
45
+ rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
46
+ }
47
+
48
+ #social .button-icon {
49
+ filter: invert(1) brightness(2);
50
+ }
51
+ }
52
+
53
+ body {
54
+ margin: 0;
55
+ }
56
+
57
+ h1,
58
+ h2 {
59
+ font-family: var(--heading);
60
+ font-weight: 500;
61
+ color: var(--text-h);
62
+ }
63
+
64
+ h1 {
65
+ font-size: 56px;
66
+ letter-spacing: -1.68px;
67
+ margin: 32px 0;
68
+ @media (max-width: 1024px) {
69
+ font-size: 36px;
70
+ margin: 20px 0;
71
+ }
72
+ }
73
+ h2 {
74
+ font-size: 24px;
75
+ line-height: 118%;
76
+ letter-spacing: -0.24px;
77
+ margin: 0 0 8px;
78
+ @media (max-width: 1024px) {
79
+ font-size: 20px;
80
+ }
81
+ }
82
+ p {
83
+ margin: 0;
84
+ }
85
+
86
+ code,
87
+ .counter {
88
+ font-family: var(--mono);
89
+ display: inline-flex;
90
+ border-radius: 4px;
91
+ color: var(--text-h);
92
+ }
93
+
94
+ code {
95
+ font-size: 15px;
96
+ line-height: 135%;
97
+ padding: 4px 8px;
98
+ background: var(--code-bg);
99
+ }
100
+
101
+ .counter {
102
+ font-size: 16px;
103
+ padding: 5px 10px;
104
+ border-radius: 5px;
105
+ color: var(--accent);
106
+ background: var(--accent-bg);
107
+ border: 2px solid transparent;
108
+ transition: border-color 0.3s;
109
+ margin-bottom: 24px;
110
+
111
+ &:hover {
112
+ border-color: var(--accent-border);
113
+ }
114
+ &:focus-visible {
115
+ outline: 2px solid var(--accent);
116
+ outline-offset: 2px;
117
+ }
118
+ }
119
+
120
+ .hero {
121
+ position: relative;
122
+
123
+ .base,
124
+ .framework,
125
+ .vite {
126
+ inset-inline: 0;
127
+ margin: 0 auto;
128
+ }
129
+
130
+ .base {
131
+ width: 170px;
132
+ position: relative;
133
+ z-index: 0;
134
+ }
135
+
136
+ .framework,
137
+ .vite {
138
+ position: absolute;
139
+ }
140
+
141
+ .framework {
142
+ z-index: 1;
143
+ top: 34px;
144
+ height: 28px;
145
+ transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
146
+ scale(1.4);
147
+ }
148
+
149
+ .vite {
150
+ z-index: 0;
151
+ top: 107px;
152
+ height: 26px;
153
+ width: auto;
154
+ transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
155
+ scale(0.8);
156
+ }
157
+ }
158
+
159
+ #app {
160
+ width: 1126px;
161
+ max-width: 100%;
162
+ margin: 0 auto;
163
+ text-align: center;
164
+ border-inline: 1px solid var(--border);
165
+ min-height: 100svh;
166
+ display: flex;
167
+ flex-direction: column;
168
+ box-sizing: border-box;
169
+ }
170
+
171
+ #center {
172
+ display: flex;
173
+ flex-direction: column;
174
+ gap: 25px;
175
+ place-content: center;
176
+ place-items: center;
177
+ flex-grow: 1;
178
+
179
+ @media (max-width: 1024px) {
180
+ padding: 32px 20px 24px;
181
+ gap: 18px;
182
+ }
183
+ }
184
+
185
+ #next-steps {
186
+ display: flex;
187
+ border-top: 1px solid var(--border);
188
+ text-align: left;
189
+
190
+ & > div {
191
+ flex: 1 1 0;
192
+ padding: 32px;
193
+ @media (max-width: 1024px) {
194
+ padding: 24px 20px;
195
+ }
196
+ }
197
+
198
+ .icon {
199
+ margin-bottom: 16px;
200
+ width: 22px;
201
+ height: 22px;
202
+ }
203
+
204
+ @media (max-width: 1024px) {
205
+ flex-direction: column;
206
+ text-align: center;
207
+ }
208
+ }
209
+
210
+ #docs {
211
+ border-right: 1px solid var(--border);
212
+
213
+ @media (max-width: 1024px) {
214
+ border-right: none;
215
+ border-bottom: 1px solid var(--border);
216
+ }
217
+ }
218
+
219
+ #next-steps ul {
220
+ list-style: none;
221
+ padding: 0;
222
+ display: flex;
223
+ gap: 8px;
224
+ margin: 32px 0 0;
225
+
226
+ .logo {
227
+ height: 18px;
228
+ }
229
+
230
+ a {
231
+ color: var(--text-h);
232
+ font-size: 16px;
233
+ border-radius: 6px;
234
+ background: var(--social-bg);
235
+ display: flex;
236
+ padding: 6px 12px;
237
+ align-items: center;
238
+ gap: 8px;
239
+ text-decoration: none;
240
+ transition: box-shadow 0.3s;
241
+
242
+ &:hover {
243
+ box-shadow: var(--shadow);
244
+ }
245
+ .button-icon {
246
+ height: 18px;
247
+ width: 18px;
248
+ }
249
+ }
250
+
251
+ @media (max-width: 1024px) {
252
+ margin-top: 20px;
253
+ flex-wrap: wrap;
254
+ justify-content: center;
255
+
256
+ li {
257
+ flex: 1 1 calc(50% - 8px);
258
+ }
259
+
260
+ a {
261
+ width: 100%;
262
+ justify-content: center;
263
+ box-sizing: border-box;
264
+ }
265
+ }
266
+ }
267
+
268
+ #spacer {
269
+ height: 88px;
270
+ border-top: 1px solid var(--border);
271
+ @media (max-width: 1024px) {
272
+ height: 48px;
273
+ }
274
+ }
275
+
276
+ .ticks {
277
+ position: relative;
278
+ width: 100%;
279
+
280
+ &::before,
281
+ &::after {
282
+ content: '';
283
+ position: absolute;
284
+ top: -4.5px;
285
+ border: 5px solid transparent;
286
+ }
287
+
288
+ &::before {
289
+ left: 0;
290
+ border-left-color: var(--border);
291
+ }
292
+ &::after {
293
+ right: 0;
294
+ border-right-color: var(--border);
295
+ }
296
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "@vue/tsconfig/tsconfig.dom.json",
3
+ "compilerOptions": {
4
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5
+ "types": ["vite/client"],
6
+ "allowArbitraryExtensions": true,
7
+
8
+ /* Linting */
9
+ "noUnusedLocals": true,
10
+ "noUnusedParameters": true,
11
+ "erasableSyntaxOnly": true,
12
+ "noFallthroughCasesInSwitch": true
13
+ },
14
+ "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
15
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ]
7
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "es2023",
5
+ "lib": ["ES2023"],
6
+ "types": ["node"],
7
+ "skipLibCheck": true,
8
+
9
+ /* Bundler mode */
10
+ "module": "nodenext",
11
+ "allowImportingTsExtensions": true,
12
+ "verbatimModuleSyntax": true,
13
+ "moduleDetection": "force",
14
+ "noEmit": true,
15
+
16
+ /* Linting */
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "erasableSyntaxOnly": true,
20
+ "noFallthroughCasesInSwitch": true
21
+ },
22
+ "include": ["vite.config.ts"]
23
+ }
@@ -0,0 +1,7 @@
1
+ import vue from '@vitejs/plugin-vue'
2
+ import { defineConfig } from 'vite'
3
+
4
+ // https://vite.dev/config/
5
+ export default defineConfig({
6
+ plugins: [vue()],
7
+ })