Initial commit

This commit is contained in:
2025-12-20 15:41:03 +01:00
committed by GitHub
commit 9475478c17
19 changed files with 7109 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
+47
View File
@@ -0,0 +1,47 @@
name: CI
on: [push]
jobs:
eslint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install modules
run: bun ci
- name: Run ESLint
run: bun run lint
build:
runs-on: ubuntu-latest
needs: eslint
steps:
- uses: actions/checkout@v2
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install modules
run: bun ci
- name: Build site
run: bun run build
- name: Upload static files as artifact
uses: actions/upload-pages-artifact@v3
with:
path: dist/
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
permissions:
pages: write
id-token: write
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
+5
View File
@@ -0,0 +1,5 @@
.idea
.vscode
node_modules
.eslintcache
dist
+32
View File
@@ -0,0 +1,32 @@
# Vue-boilerplate
*Minimal static Vue project*
<!-- TODO: 1. rename app (and tool URL) -->
### [Tool link](https://klemek.github.io/vue-boilerplate/)
## Use this template
<!-- TODO: 3. remove this part -->
```bash
git clone git@github.com/klemek/vue-boilerplate.git {PROJECT}
cd {PROJECT}
git remote rename origin template
git remote add origin {PROJECT REMOTE}
# everytime you want to update your fork
git fetch --all
git merge template/master
```
> Every task is indicated with a TODO
1. [ ] Rename app in [README.md](./README.md), [index.html](./index.html), [App.vue](./src/App.vue) and [package.json](./package.json)
2. [ ] Change app hue and saturation in [style.css](./style.css)
3. [ ] Remove this part and all TODO
## Tips
* [Material design colors](https://materialui.co/colors/) are available, you can use `class="red-500"` on your HTML
* [Lucide icons](https://lucide.dev/icons) are available, you can use `<LucideIcon name=house/>` on your Vue template
Vendored
+1
View File
@@ -0,0 +1 @@
/// <reference types="vite/client" />
+24
View File
@@ -0,0 +1,24 @@
import { globalIgnores } from "eslint/config";
import {
defineConfigWithVueTs,
vueTsConfigs,
} from "@vue/eslint-config-typescript";
import pluginVue from "eslint-plugin-vue";
import skipFormatting from "@vue/eslint-config-prettier/skip-formatting";
import { configureVueProject } from "@vue/eslint-config-typescript";
configureVueProject({ scriptLangs: ["ts", "tsx"] });
export default defineConfigWithVueTs(
{
name: "app/files-to-lint",
files: ["**/*.{ts,mts,tsx,vue}"],
},
globalIgnores(["**/dist/**"]),
pluginVue.configs["flat/recommended"],
vueTsConfigs.strictTypeChecked,
vueTsConfigs.stylisticTypeChecked,
skipFormatting,
);
+24
View File
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- TODO: 1. rename app -->
<title>Change this you moron</title>
<link rel="stylesheet" href="/style.css" />
<link rel="stylesheet" href="/material-colors.css" />
<!-- <link rel="icon" href="/favicon.ico"> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="UTF-8">
<!-- card related -->
<!--
<meta name="twitter:card" content="summary_large_image">
<meta property="og:title" content="">
<meta property="og:description" content="">
<meta property="og:image" content="https://.../preview_640x320.jpg">
<meta property="org:url" content="https://...">
-->
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
+4860
View File
File diff suppressed because it is too large Load Diff
+40
View File
@@ -0,0 +1,40 @@
{
"name": "vue-boilerplate",
"version": "0.0.0",
"private": true,
"type": "module",
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"scripts": {
"dev": "vite",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --build",
"lint": "eslint . --cache",
"fix": "eslint . --fix --cache",
"format": "prettier --write --experimental-cli src/"
},
"dependencies": {
"lucide-vue-next": "^0.562.0",
"vue": "^3.5.25"
},
"devDependencies": {
"@tsconfig/node24": "^24.0.3",
"@types/node": "^24.10.1",
"@vitejs/plugin-vue": "^6.0.2",
"@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.6.0",
"@vue/tsconfig": "^0.8.1",
"eslint": "^9.39.1",
"eslint-plugin-vue": "~10.5.1",
"jiti": "^2.6.1",
"npm-run-all2": "^8.0.4",
"prettier": "3.6.2",
"typescript": "~5.9.0",
"vite": "^7.2.4",
"vite-plugin-vue-devtools": "^8.0.5",
"vue-tsc": "^3.1.5"
}
}
File diff suppressed because it is too large Load Diff
+202
View File
@@ -0,0 +1,202 @@
/*
=================================================
https://www.joshwcomeau.com/css/custom-css-reset/
=================================================
*/
/*
1. Use a more-intuitive box-sizing model.
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
/*
2. Remove default margin
*/
* {
margin: 0;
}
/*
3. Allow percentage-based heights in the application
*/
html,
body, div#app {
height: 100%;
}
/*
Typographic tweaks!
4. Add accessible line-height
5. Improve text rendering
*/
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
/*
6. Improve media defaults
*/
img,
picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
}
/*
7. Remove built-in form typography styles
*/
input,
button,
textarea,
select {
font: inherit;
}
/*
8. Avoid text overflows
*/
p,
h1,
h2,
h3,
h4,
h5,
h6 {
overflow-wrap: break-word;
}
/*
9. Create a root stacking context
*/
#root,
#__next {
isolation: isolate;
}
/*
=================================================
CUSTOM STYLE
=================================================
*/
@import url("https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap");
:root {
/* https://materialui.co/colors/ */
/* TODO: 2. change hue and saturation */
--hue-primary: 65.52;
--sat-primary: 20%;
--background: hsl(var(--hue-primary), var(--sat-primary), 96.08%);
--background-primary: hsl(var(--hue-primary), var(--sat-primary), 93.33%);
--background-secondary: hsl(var(--hue-primary), var(--sat-primary), 90%);
--color-primary: hsl(var(--hue-primary), var(--sat-primary), 50%);
--text-primary: hsl(var(--hue-primary), var(--sat-primary), 25%);
--text-secondary: hsl(var(--hue-primary), var(--sat-primary), 30%);
}
/*
=================================================
https://blog.koley.in/2019/339-bytes-of-responsive-css
https://www.swyx.io/css-100-bytes
https://gist.github.com/JoeyBurzynski/617fb6201335779f8424ad9528b72c41
=================================================
*/
html,
body {
padding: 0;
max-width: 100%;
color: var(--text-primary);
font-family: "Roboto", Verdana, serif;
}
body {
background-color: var(--background);
}
main {
padding: 1.5rem;
margin: auto;
background-color: var(--background-primary);
min-height: 100%;
}
table {
border-collapse: collapse;
width: 100%;
font-size: 0.9em;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 1em 0 0.5em;
}
p,
ul,
ol {
margin-bottom: 2em;
color: var(--text-secondary);
}
hr {
opacity: 25%;
border-bottom: 0;
margin-bottom: 0.5em;
}
textarea,
input,
select,
.mono {
font-family: "Roboto Mono", monospace;
}
textarea {
width: 100%;
min-width: 100%;
max-width: 100%;
}
a {
color: inherit;
}
@media only screen and (min-width: 768px) {
main {
max-width: 42rem;
}
table {
font-size: inherit;
}
}
/*
* LUCIDE ICONS
*/
.lucide {
width: 1.1em;
height: 1.1em;
}
svg.lucide {
display: inline-block;
vertical-align: text-top;
}
b .lucide,
h1 .lucide,
h2 .lucide,
h3 .lucide,
h4 .lucide,
h5 .lucide,
h6 .lucide {
stroke-width: 3;
}
+70
View File
@@ -0,0 +1,70 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import LucideIcon from "./components/LucideIcon.vue";
import CustomButton from "./components/CustomButton.vue"
const visible = ref<boolean>(false);
onMounted(() => {
setTimeout(() => {
visible.value = true;
});
});
</script>
<template>
<main :style="{ display: visible ? 'inherit' : 'none' }">
<!-- TODO: 1. rename app -->
<h1>
<LucideIcon name="package" />
Vue-Boilerplate
</h1>
<br />
<p>
Fill this page with <i>whatever</i> you're going to develop.
<br>
<b>Then enjoy!</b>
</p>
<CustomButton>
<LucideIcon name="square-arrow-right"/> This is a sample button yay
</CustomButton>
<br />
<hr />
<small class="footer">
<LucideIcon name="at-sign" />
&nbsp;
<a href="https://github.com/klemek" target="_blank">klemek</a>
-
<!-- TODO: 1. rename app -->
<LucideIcon name="github" />
&nbsp;
<a href="https://github.com/klemek/vue-boilerplate" target="_blank">
Repository
</a>
- 2025
</small>
</main>
</template>
<style scoped>
.button {
display: block;
width: 100%;
text-decoration: none;
padding: 1em;
margin-bottom: 0.75em;
border: 1px solid var(--color-primary);
border-radius: 0.5em;
background-color: var(--background);
cursor: pointer;
font-size: 1.333em;
}
.button:hover {
background-color: var(--background-secondary);
}
.footer {
opacity: 50%;
}
</style>
+36
View File
@@ -0,0 +1,36 @@
<script setup lang="ts">
interface Props {
href?: string;
color?: string;
}
defineProps<Props>();
</script>
<template>
<component
:is="href ? 'a' : 'div'"
:class="`button ${color ? 'b-' + color + ' ' + color : ''}`"
>
<slot></slot>
</component>
</template>
<style scoped>
.button {
display: block;
width: 100%;
text-decoration: none;
padding: 1em;
margin-bottom: 0.75em;
border: 1px solid var(--color-primary);
border-radius: 0.5em;
background-color: var(--background);
cursor: pointer;
font-size: 1.333em;
}
.button:hover {
background-color: var(--background-secondary);
}
</style>
+40
View File
@@ -0,0 +1,40 @@
<script setup lang="ts">
import { computed, onMounted } from "vue";
import * as icons from "lucide-vue-next";
interface Props {
name: string;
color?: string;
strokeWidth?: string;
defaultClass?: string;
}
const props = withDefaults(defineProps<Props>(), {
color: "currentColor",
strokeWidth: "2",
defaultClass: "lucide",
});
function kebab2camel(kebab: string): string {
return kebab
.split("-")
.map((item) => item.charAt(0).toUpperCase() + item.slice(1).toLowerCase())
.join("");
}
onMounted(() => {
console.log(kebab2camel(props.name));
});
// @ts-expect-error: cannot infer type of all exported data
const icon = computed(() => icons[kebab2camel(props.name)]);
</script>
<template>
<component
:is="icon"
:color="color"
:stroke-width="strokeWidth"
:default-class="defaultClass"
/>
</template>
+4
View File
@@ -0,0 +1,4 @@
import { createApp } from "vue";
import App from "./App.vue";
createApp(App).mount("#app");
+12
View File
@@ -0,0 +1,12 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"paths": {
"@/*": ["./src/*"]
}
}
}
+11
View File
@@ -0,0 +1,11 @@
{
"files": [],
"references": [
{
"path": "./tsconfig.node.json"
},
{
"path": "./tsconfig.app.json"
}
]
}
+19
View File
@@ -0,0 +1,19 @@
{
"extends": "@tsconfig/node24/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*",
"eslint.config.*"
],
"compilerOptions": {
"noEmit": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}
+20
View File
@@ -0,0 +1,20 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
base: '',
plugins: [
vue(),
vueDevTools(),
],
publicDir: "public",
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
}
})