Add /legal-notice and /contact; Improve styling
This commit is contained in:
parent
fffd7e2025
commit
086eefcefa
18 changed files with 576 additions and 80 deletions
|
@ -2,6 +2,11 @@
|
|||
"root": true,
|
||||
"extends": "awzzm-vue/v3",
|
||||
"rules": {
|
||||
"vue/no-static-inline-styles": "off"
|
||||
"vue/no-static-inline-styles": "off",
|
||||
"unicorn/prevent-abbreviations": ["warn", {
|
||||
"replacements": {
|
||||
"i": false
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>Moritz Ruth</title>
|
||||
<link rel="preload" as="font" href="/node_modules/@fontsource/plus-jakarta-sans/files/plus-jakarta-sans-latin-400-normal.woff2">
|
||||
<link rel="preload" as="font" href="/node_modules/@fontsource/syne/files/syne-latin-800-normal.woff2">
|
||||
<link rel="stylesheet" href="/node_modules/@fontsource/plus-jakarta-sans/400.css">
|
||||
<link rel="stylesheet" href="/node_modules/@fontsource/plus-jakarta-sans/800.css">
|
||||
<link rel="stylesheet" href="/node_modules/@fontsource/syne/800.css">
|
||||
|
@ -11,7 +13,7 @@
|
|||
<meta name="keywords" content="web, dev, development, coding, moritz, ruth, development, design">
|
||||
<link rel="shortcut icon" type="image/png" href="/icon.png">
|
||||
</head>
|
||||
<body class="bg-[#fefefe]">
|
||||
<body class="bg-[#fefefe] overflow-x-hidden">
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
<script
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview",
|
||||
"start": "vite preview",
|
||||
"lint": "eslint . --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -14,9 +14,11 @@
|
|||
"blobs": "^2.2.1-beta.1",
|
||||
"kute.js": "^2.1.2",
|
||||
"vue": "^3.1.1",
|
||||
"vue-i18n": "^9.1.6",
|
||||
"vue-router": "4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@intlify/vite-plugin-vue-i18n": "^2.2.1",
|
||||
"@vitejs/plugin-vue": "^1.2.3",
|
||||
"@vue/compiler-sfc": "^3.1.1",
|
||||
"eslint": "^7.28.0",
|
||||
|
|
193
pnpm-lock.yaml
generated
193
pnpm-lock.yaml
generated
|
@ -3,6 +3,7 @@ lockfileVersion: 5.3
|
|||
specifiers:
|
||||
'@fontsource/plus-jakarta-sans': ^4.4.5
|
||||
'@fontsource/syne': ^4.4.5
|
||||
'@intlify/vite-plugin-vue-i18n': ^2.2.1
|
||||
'@vitejs/plugin-vue': ^1.2.3
|
||||
'@vue/compiler-sfc': ^3.1.1
|
||||
'@vueuse/core': ^5.0.3
|
||||
|
@ -14,6 +15,7 @@ specifiers:
|
|||
vite-plugin-pages: ^0.13.1
|
||||
vite-plugin-windicss: ^1.0.4
|
||||
vue: ^3.1.1
|
||||
vue-i18n: ^9.1.6
|
||||
vue-router: '4'
|
||||
windicss: ^3.1.3
|
||||
|
||||
|
@ -24,9 +26,11 @@ dependencies:
|
|||
blobs: 2.2.1-beta.1
|
||||
kute.js: 2.1.2
|
||||
vue: 3.1.1
|
||||
vue-i18n: 9.1.6_vue@3.1.1
|
||||
vue-router: 4.0.9_vue@3.1.1
|
||||
|
||||
devDependencies:
|
||||
'@intlify/vite-plugin-vue-i18n': 2.2.1_vite@2.3.7+vue-i18n@9.1.6
|
||||
'@vitejs/plugin-vue': 1.2.3_@vue+compiler-sfc@3.1.1
|
||||
'@vue/compiler-sfc': 3.1.1_vue@3.1.1
|
||||
eslint: 7.28.0
|
||||
|
@ -295,6 +299,101 @@ packages:
|
|||
resolution: {integrity: sha512-YK1dF3I+HVmqnLARwq1pptG420jjhtS6xzFLAO6/8ap8XDIfp2wiCpenkkVenXMGzKBto0S7+D3pzvVCQ/q77Q==}
|
||||
dev: false
|
||||
|
||||
/@intlify/cli/0.5.0:
|
||||
resolution: {integrity: sha512-FKPL2Avs+X7+Poer+XHbXBMNYVdFCYvTpuMr8OqnCkHlLtKgCrskeUzLyryelT4G8JG9ZZXOE9AZkiqo/AWYyg==}
|
||||
engines: {node: '>= 10'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@intlify/core': 9.1.6
|
||||
'@intlify/core-base': 9.1.6
|
||||
'@intlify/message-compiler': 9.1.6
|
||||
'@intlify/shared': 9.1.6
|
||||
chalk: 4.1.1
|
||||
debug: 4.3.1
|
||||
glob: 7.1.7
|
||||
jsonc-eslint-parser: 1.0.1
|
||||
source-map: 0.6.1
|
||||
yaml-eslint-parser: 0.3.2
|
||||
yargs: 16.2.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@intlify/core-base/9.1.6:
|
||||
resolution: {integrity: sha512-d5GDPpsQbqPkisSJA5b6nJFEkalY/IHAd7vOLNd/Sj4YaNRzXtInu2FoqKiOv8e/lQnXGTpurdCZg5Jxq1Gsxw==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/devtools-if': 9.1.6
|
||||
'@intlify/message-compiler': 9.1.6
|
||||
'@intlify/message-resolver': 9.1.6
|
||||
'@intlify/runtime': 9.1.6
|
||||
'@intlify/shared': 9.1.6
|
||||
'@intlify/vue-devtools': 9.1.6
|
||||
|
||||
/@intlify/core/9.1.6:
|
||||
resolution: {integrity: sha512-/B/2mRUqiNByKI+M13zRotiCecFHrlSg+V9HLSsIDW9xVWIn/NXucfCD4CUHzIPPGcCtzNjxixKTojGnWcsLSg==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/core-base': 9.1.6
|
||||
dev: true
|
||||
|
||||
/@intlify/devtools-if/9.1.6:
|
||||
resolution: {integrity: sha512-m8Api+kh+BtFa2FZ/JjIdr1ibsGGqBjdKCzWo5BZecEUxBquIeOQZwpokPh/0K5j+/PZleFXkVAMC5mNt+9WdA==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/shared': 9.1.6
|
||||
|
||||
/@intlify/message-compiler/9.1.6:
|
||||
resolution: {integrity: sha512-DR8645VOrVK6x/8tkaCpHnckMAIcoOgeNS5j0wB12RfZoXYQp7vAXMaOP511KMll2mXCREgIB0ojpajiof7yzQ==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/message-resolver': 9.1.6
|
||||
'@intlify/shared': 9.1.6
|
||||
source-map: 0.6.1
|
||||
|
||||
/@intlify/message-resolver/9.1.6:
|
||||
resolution: {integrity: sha512-UUnbawQa5U9sffd5wRIscqtyY1xWlwJbyfwCLPEWLvBhyAnCwPYlvaHGnnO0CSi0fzJTVwlV9DYzobh3agDeMA==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
/@intlify/runtime/9.1.6:
|
||||
resolution: {integrity: sha512-U1QZ+TPf3kQQvWo4BA2mj3cHAxMRHXNTBhu2u+deh6ubTqXdZ19XGBTMSasrXG6RE+zSio9oM+ndoLja7JGtPg==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/message-compiler': 9.1.6
|
||||
'@intlify/message-resolver': 9.1.6
|
||||
'@intlify/shared': 9.1.6
|
||||
|
||||
/@intlify/shared/9.1.6:
|
||||
resolution: {integrity: sha512-6MtsKulyfZxdD7OuxjaODjj8QWoHCnLFAk4wkWiHqBCa6UCTC0qXjtEeZ1MxpQihvFmmJZauBUu25EvtngW5qQ==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
/@intlify/vite-plugin-vue-i18n/2.2.1_vite@2.3.7+vue-i18n@9.1.6:
|
||||
resolution: {integrity: sha512-TUmuXhj2VIyyRzGhY9OtiXXEqaibtfV61oj0RDHbvpURd7B3Fukw/X7kzorz/dtSzo3DWNTcUgBElJrzeuGJGA==}
|
||||
engines: {node: '>= 12'}
|
||||
peerDependencies:
|
||||
vite: ^2.3.6
|
||||
vue-i18n: ^9.1.6
|
||||
dependencies:
|
||||
'@intlify/cli': 0.5.0
|
||||
'@intlify/shared': 9.1.6
|
||||
'@rollup/pluginutils': 4.1.0
|
||||
debug: 4.3.1
|
||||
fast-glob: 3.2.5
|
||||
vite: 2.3.7
|
||||
vue-i18n: 9.1.6_vue@3.1.1
|
||||
transitivePeerDependencies:
|
||||
- rollup
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@intlify/vue-devtools/9.1.6:
|
||||
resolution: {integrity: sha512-UdNovg4OML9rIr1sOGZzTfNr1nUy4UQpDf5ni4dNC93T6FIkVJz0n1Np7Vp7e6gDjcmufRYcV99tEwjQSN9+5A==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/message-resolver': 9.1.6
|
||||
'@intlify/runtime': 9.1.6
|
||||
'@intlify/shared': 9.1.6
|
||||
|
||||
/@nodelib/fs.scandir/2.1.5:
|
||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||
engines: {node: '>= 8'}
|
||||
|
@ -346,6 +445,16 @@ packages:
|
|||
picomatch: 2.3.0
|
||||
dev: false
|
||||
|
||||
/@rollup/pluginutils/4.1.0:
|
||||
resolution: {integrity: sha512-TrBhfJkFxA+ER+ew2U2/fHbebhLT/l/2pRk0hfj9KusXUuRXd2v0R58AfaZK9VXDQ4TogOSEmICVrQAA3zFnHQ==}
|
||||
engines: {node: '>= 8.0.0'}
|
||||
peerDependencies:
|
||||
rollup: ^1.20.0||^2.0.0
|
||||
dependencies:
|
||||
estree-walker: 2.0.2
|
||||
picomatch: 2.3.0
|
||||
dev: true
|
||||
|
||||
/@types/buble/0.19.2:
|
||||
resolution: {integrity: sha512-uUD8zIfXMKThmFkahTXDGI3CthFH1kMg2dOm3KLi4GlC5cbARA64bEcUMbbWdWdE73eoc/iBB9PiTMqH0dNS2Q==}
|
||||
dependencies:
|
||||
|
@ -695,6 +804,14 @@ packages:
|
|||
escape-string-regexp: 1.0.5
|
||||
dev: true
|
||||
|
||||
/cliui/7.0.4:
|
||||
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
|
||||
dependencies:
|
||||
string-width: 4.2.2
|
||||
strip-ansi: 6.0.0
|
||||
wrap-ansi: 7.0.0
|
||||
dev: true
|
||||
|
||||
/color-convert/1.9.3:
|
||||
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
|
||||
dependencies:
|
||||
|
@ -1299,6 +1416,11 @@ packages:
|
|||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/get-caller-file/2.0.5:
|
||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||
engines: {node: 6.* || 8.* || >= 10.*}
|
||||
dev: true
|
||||
|
||||
/get-intrinsic/1.1.1:
|
||||
resolution: {integrity: sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==}
|
||||
dependencies:
|
||||
|
@ -1616,6 +1738,14 @@ packages:
|
|||
minimist: 1.2.5
|
||||
dev: true
|
||||
|
||||
/jsonc-eslint-parser/1.0.1:
|
||||
resolution: {integrity: sha512-mh5LY5byThmc692EqJS3Ss9sViNoNeCLNG5VQUgJLoAFFM3FzdIetd99qEiiQ+NXBVAIUgX5sWeK9leniS8RbQ==}
|
||||
dependencies:
|
||||
eslint-utils: 2.1.0
|
||||
eslint-visitor-keys: 2.1.0
|
||||
espree: 7.3.1
|
||||
dev: true
|
||||
|
||||
/kute.js/2.1.2:
|
||||
resolution: {integrity: sha512-UlQr6Rlu/vaXUacSrspkMO6hhr5p+VyX/9/r2+YFWooTOzb9hZGWoOC8FsP4UT+IwYMLunFx7sj8HwEl0LTTUg==}
|
||||
dependencies:
|
||||
|
@ -2163,6 +2293,11 @@ packages:
|
|||
jsesc: 0.5.0
|
||||
dev: false
|
||||
|
||||
/require-directory/2.1.1:
|
||||
resolution: {integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I=}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/require-from-string/2.0.2:
|
||||
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
@ -2619,6 +2754,19 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/vue-i18n/9.1.6_vue@3.1.1:
|
||||
resolution: {integrity: sha512-FEC4HZkTH6QRIu/A0wlo0VS/GH3w/fuCC6xfvoC8IyhhtbG9A+go9NfW+HZ1ZXdAcO4EWcVQi04M+iSwuxgixw==}
|
||||
engines: {node: '>= 10'}
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
dependencies:
|
||||
'@intlify/core-base': 9.1.6
|
||||
'@intlify/shared': 9.1.6
|
||||
'@intlify/vue-devtools': 9.1.6
|
||||
'@vue/devtools-api': 6.0.0-beta.14
|
||||
vue: 3.1.1
|
||||
dev: false
|
||||
|
||||
/vue-router/4.0.9_vue@3.1.1:
|
||||
resolution: {integrity: sha512-i3IaZJ57YeMbRHQlqKyXdUMr5NzTCcJkn3f8u38TsZjYWtGcd3IX2zRd3389SCOwuRf11mgfHAyngR6FVDE9og==}
|
||||
peerDependencies:
|
||||
|
@ -2687,10 +2835,24 @@ packages:
|
|||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/wrap-ansi/7.0.0:
|
||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
string-width: 4.2.2
|
||||
strip-ansi: 6.0.0
|
||||
dev: true
|
||||
|
||||
/wrappy/1.0.2:
|
||||
resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=}
|
||||
dev: true
|
||||
|
||||
/y18n/5.0.8:
|
||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/yallist/3.1.1:
|
||||
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
|
||||
dev: true
|
||||
|
@ -2699,7 +2861,38 @@ packages:
|
|||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||
dev: true
|
||||
|
||||
/yaml-eslint-parser/0.3.2:
|
||||
resolution: {integrity: sha512-32kYO6kJUuZzqte82t4M/gB6/+11WAuHiEnK7FreMo20xsCKPeFH5tDBU7iWxR7zeJpNnMXfJyXwne48D0hGrg==}
|
||||
dependencies:
|
||||
eslint-visitor-keys: 1.3.0
|
||||
lodash: 4.17.21
|
||||
yaml: 1.10.2
|
||||
dev: true
|
||||
|
||||
/yaml/1.10.2:
|
||||
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
|
||||
engines: {node: '>= 6'}
|
||||
dev: true
|
||||
|
||||
/yaml/2.0.0-6:
|
||||
resolution: {integrity: sha512-YPUm0Z0sei53zauT7HWkkxyIBJhb9Gnf5jv4w4ahw5/v3PjFGhZOt4paXH6g9hzcMJqmNxZwoGfF1JzE2jvSgg==}
|
||||
engines: {node: '>= 12'}
|
||||
dev: true
|
||||
|
||||
/yargs-parser/20.2.7:
|
||||
resolution: {integrity: sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/yargs/16.2.0:
|
||||
resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
cliui: 7.0.4
|
||||
escalade: 3.1.1
|
||||
get-caller-file: 2.0.5
|
||||
require-directory: 2.1.1
|
||||
string-width: 4.2.2
|
||||
y18n: 5.0.8
|
||||
yargs-parser: 20.2.7
|
||||
dev: true
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
https://moritz-ruth.de/* https://moritzruth.de/:splat 301!
|
||||
https://moritz-ruth.de/* https://moritzruth.de/:splat 308!
|
||||
/agb /terms-and-conditions 308
|
||||
/* /index.html 200
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
Betreffend moritzruth.de und alle Seiten unter Subdomains von moritzruth.de:
|
||||
|
||||
Angaben gemäß § 5 TMG
|
||||
|
||||
Moritz Ruth
|
||||
Zum Galgenberg 19
|
||||
66539 Neunkirchen
|
||||
|
||||
E-Mail: hey@m0.is
|
||||
|
||||
Haftung für Links:
|
||||
Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.
|
65
src/App.vue
65
src/App.vue
|
@ -1,9 +1,17 @@
|
|||
<template>
|
||||
<NavigationMenu/>
|
||||
<div class="overflow-x-hidden">
|
||||
<div class="bg-white text-black max-w-1200px mx-auto px-6 sm:px-10">
|
||||
<router-view/>
|
||||
</div>
|
||||
<div class="bg-white text-black max-w-1200px w-full mx-auto px-6 sm:px-10" style="min-height: calc(100vh - 160px)">
|
||||
<router-view/>
|
||||
</div>
|
||||
<div class="w-full h-20 space-x-10 flex items-center justify-center">
|
||||
<router-link
|
||||
v-for="item in items"
|
||||
:key="item.to"
|
||||
class="uppercase tracking-wide text-sm"
|
||||
:to="item.to"
|
||||
>
|
||||
{{ t(item.labelKey) }}
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -11,13 +19,60 @@
|
|||
body {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
::selection {
|
||||
@apply bg-blue-900 bg-opacity-80 text-white;
|
||||
}
|
||||
|
||||
.asterisk-list > li {
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
&::before {
|
||||
@apply text-blue-900;
|
||||
content: "*";
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en:
|
||||
footer:
|
||||
tac: Terms & Conditions
|
||||
legal: Legal Notice
|
||||
|
||||
de:
|
||||
footer:
|
||||
tac: AGB
|
||||
legal: Impressum
|
||||
</i18n>
|
||||
|
||||
<script>
|
||||
import { useI18n } from "vue-i18n"
|
||||
import NavigationMenu from "./components/NavigationMenu.vue"
|
||||
|
||||
const FOOTER_LINKS = [
|
||||
// {
|
||||
// labelKey: "footer.tac",
|
||||
// to: "/terms-and-conditions"
|
||||
// },
|
||||
{
|
||||
labelKey: "footer.legal",
|
||||
to: "/legal-notice"
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
components: { NavigationMenu }
|
||||
components: { NavigationMenu },
|
||||
setup() {
|
||||
const { t } = useI18n()
|
||||
return {
|
||||
t,
|
||||
items: FOOTER_LINKS
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<svg :style="{ width: size, height: size, filter: `blur(${blur}px)` }">
|
||||
<svg :style="{ width: size + 'px', height: size + 'px', filter: `blur(${blur}px)` }">
|
||||
<path
|
||||
v-for="(blob, index) in blobs"
|
||||
:key="index"
|
||||
|
@ -14,7 +14,7 @@
|
|||
import * as blobs2 from "blobs/v2"
|
||||
import KUTE from "kute.js"
|
||||
import { ref } from "vue"
|
||||
import { getListOfIndexes } from "../getListOfIndexes.js"
|
||||
import { getListOfIndexes } from "../utils/getListOfIndexes.js"
|
||||
|
||||
const BLOB_OPTIONS = {
|
||||
extraPoints: 6,
|
||||
|
|
|
@ -1,24 +1,29 @@
|
|||
<template>
|
||||
<div class="sm:hidden fixed z-101 bottom-3 right-3 rounded-full backdrop-filter backdrop-blur-20 bg-white bg-opacity-20 w-20 h-20 flex justify-center items-center shadow-lg">
|
||||
<div role="button" class="flex flex-col justify-evenly items-center h-10" @click="active = !active">
|
||||
<div class="sm:hidden fixed z-101 bottom-2 right-2 rounded-full backdrop-filter bg-white w-18 h-18 flex justify-center items-center shadow-lg _blur-backdrop-or-hide">
|
||||
<div
|
||||
role="button"
|
||||
aria-label="Toggle navigation menu"
|
||||
class="flex flex-col justify-evenly items-center h-10"
|
||||
@click="active = !active"
|
||||
>
|
||||
<div class="w-10 h-2px bg-black transition duration-200 transform" :style="`transform: ${active ? 'translateY(350%)' : ''} rotate(${active ? 45 : 0}deg)`"/>
|
||||
<div class="w-10 h-2px bg-black transition duration-200 transform" :style="`transform: ${active ? 'translateY(-350%)' : ''} rotate(${active ? -45 : 0}deg)`"/>
|
||||
</div>
|
||||
</div>
|
||||
<nav
|
||||
class="fixed sm:sticky top-0 z-100 w-screen h-screen sm:h-20 backdrop-filter backdrop-blur-40 bg-white bg-opacity-40 transition duration-200"
|
||||
class="fixed sm:sticky top-0 z-100 w-full h-screen sm:h-20 backdrop-filter bg-white transition duration-200 _blur-backdrop-or-hide"
|
||||
:class="[scrolled && 'shadow-lg', active ? 'opacity-100' : '-sm:opacity-0 -sm:pointer-events-none']"
|
||||
>
|
||||
<div class="flex items-center justify-between h-full max-w-1200px mx-auto flex-grow -sm:flex-col px-6 sm:px-10">
|
||||
<div class="fixed transition-all duration-500" :style="{ left: blobState.x + 'px', top: blobState.y + 'px', opacity: blobState.show ? 1 : 0 }">
|
||||
<BlurredBlobCanvas
|
||||
:colors="['#eb34cf', '#79faff']"
|
||||
:colors="['#eb34cf', '#818cff']"
|
||||
:opacity-variation="0"
|
||||
:minimum-opacity="0.9"
|
||||
:minimum-duration="1000"
|
||||
:duration-variation="500"
|
||||
:blur="10"
|
||||
:size="100"
|
||||
:size="80"
|
||||
/>
|
||||
</div>
|
||||
<router-link class="uppercase font-special relative top-1 -sm:mt-20" to="/" @click="active = false">
|
||||
|
@ -33,27 +38,51 @@
|
|||
:to="item.to"
|
||||
@click="active = false"
|
||||
>
|
||||
{{ item.label }}
|
||||
{{ t(item.labelKey) }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en:
|
||||
projects: Projects
|
||||
contact: Contact
|
||||
|
||||
de:
|
||||
projects: Projekte
|
||||
contact: Kontakt
|
||||
</i18n>
|
||||
|
||||
<style scoped>
|
||||
._blur-backdrop-or-hide {
|
||||
@apply bg-opacity-90;
|
||||
backdrop-filter: blur(20px);
|
||||
}
|
||||
|
||||
@supports (backdrop-filter: blur(20px)) {
|
||||
._blur-backdrop-or-hide {
|
||||
@apply bg-opacity-40;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { useWindowScroll, useWindowSize } from "@vueuse/core"
|
||||
import { computed, ref, watch, reactive } from "vue"
|
||||
import { useRoute } from "vue-router"
|
||||
import { useI18n } from "vue-i18n"
|
||||
import { useWindowScrollLock } from "../utils/useWindowScrollLock.js"
|
||||
import BlurredBlobCanvas from "./BlurredBlobCanvas.vue"
|
||||
|
||||
const ITEMS = [
|
||||
// {
|
||||
// labelKey: "projects",
|
||||
// to: "/projects"
|
||||
// },
|
||||
{
|
||||
label: "Projects",
|
||||
to: "/projects"
|
||||
},
|
||||
{
|
||||
label: "Contact",
|
||||
labelKey: "contact",
|
||||
to: "/contact"
|
||||
}
|
||||
]
|
||||
|
@ -77,7 +106,7 @@
|
|||
const activeItem = computed(() => items.find(item => item.to === route.path) ?? null)
|
||||
const blobState = reactive({
|
||||
x: windowWidth / 2,
|
||||
y: 20,
|
||||
y: 10,
|
||||
show: false
|
||||
})
|
||||
|
||||
|
@ -88,16 +117,19 @@
|
|||
const { x, width, y } = activeItem.value.element.value.$el.getBoundingClientRect()
|
||||
|
||||
blobState.x = x + (width / 2) - 20
|
||||
blobState.y = y - 20
|
||||
blobState.y = y - 30
|
||||
blobState.show = true
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
return {
|
||||
scrolled: computed(() => windowScroll.value > 0),
|
||||
blobState,
|
||||
items,
|
||||
active
|
||||
active,
|
||||
t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
27
src/main.css
Normal file
27
src/main.css
Normal file
|
@ -0,0 +1,27 @@
|
|||
@layer base {
|
||||
.prose {
|
||||
& > * {
|
||||
@apply mt-6;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@apply font-bold text-3xl sm:text-5xl text-gray-900;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@apply font-bold text-2xl sm:text-4xl text-blue-700;
|
||||
|
||||
h1 ~ & {
|
||||
@apply mt-4;
|
||||
}
|
||||
|
||||
p ~ & {
|
||||
@apply mt-10;
|
||||
}
|
||||
}
|
||||
|
||||
address, p {
|
||||
@apply not-italic text-lg max-w-240;
|
||||
}
|
||||
}
|
||||
}
|
18
src/main.js
18
src/main.js
|
@ -1,14 +1,30 @@
|
|||
import "./main.css"
|
||||
import "virtual:windi.css"
|
||||
import routes from "virtual:generated-pages"
|
||||
import { createApp } from "vue"
|
||||
import { createRouter, createWebHistory } from "vue-router"
|
||||
import { createI18n } from "vue-i18n"
|
||||
import App from "./App.vue"
|
||||
|
||||
const i18n = createI18n({
|
||||
legacy: false,
|
||||
fallbackLocale: "en",
|
||||
locale: navigator.language
|
||||
})
|
||||
|
||||
document.documentElement.lang = navigator.language.startsWith("de") ? "de" : "en"
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes
|
||||
routes,
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
if (savedPosition) return savedPosition
|
||||
if (to.hash) return { el: to.hash }
|
||||
return { top: 0 }
|
||||
}
|
||||
})
|
||||
|
||||
createApp(App)
|
||||
.use(router)
|
||||
.use(i18n)
|
||||
.mount("#app")
|
||||
|
|
|
@ -1,11 +1,87 @@
|
|||
<template>
|
||||
<div>
|
||||
contact
|
||||
</div>
|
||||
<main class="text-2xl sm:text-3xl pt-26">
|
||||
<h1 class="font-bold text-3xl sm:text-5xl text-gray-900 mb-10">{{ t("heading") }}</h1>
|
||||
<p>
|
||||
{{ t("you_want") }}
|
||||
</p>
|
||||
<ul class="asterisk-list mt-5">
|
||||
<li>{{ t("develop_website") }}</li>
|
||||
<li>{{ t("program_tool") }}</li>
|
||||
<li>{{ t("design_print") }}</li>
|
||||
<li>{{ t("help_server") }}</li>
|
||||
</ul>
|
||||
<p class="mt-10 mb-10">
|
||||
{{ t("twitter") }}
|
||||
<a
|
||||
class="text-blue-900"
|
||||
href="https://twitter.com/moritz_ruth"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
@moritz_ruth
|
||||
</a>
|
||||
{{ t("or_email") }}
|
||||
</p>
|
||||
<div class="relative text-4xl group inline-block">
|
||||
<BlurredBlobCanvas
|
||||
class="absolute -top-10 left-22 pointer-events-none transition duration-400 opacity-0 group-hover:opacity-80"
|
||||
:colors="['#818cff']"
|
||||
:size="120"
|
||||
:blur="20"
|
||||
:minimum-duration="500"
|
||||
:minimum-opacity="0.6"
|
||||
:opacity-variation="0.4"
|
||||
/>
|
||||
→
|
||||
<a class="text-blue-900 relative ml-2" href="mailto:hey@m0.is">
|
||||
hey@m0.is
|
||||
</a>
|
||||
</div>
|
||||
<p class="mt-10 mb-10">
|
||||
{{ t("happy_to_hear") }}
|
||||
</p>
|
||||
<p class="mt-10 text-lg">
|
||||
{{ t("disclaimer") }}
|
||||
</p>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en:
|
||||
heading: Contact
|
||||
you_want: Want me to …
|
||||
develop_website: develop your website (€ 1000),
|
||||
program_tool: program a tool (€ 500),
|
||||
design_print: design a poster, brochure or business card (€ 500),
|
||||
help_server: help you with your server or domain (€ 300)?
|
||||
twitter: Hit me up on Twitter
|
||||
or_email: "or send me an email (en/de):"
|
||||
happy_to_hear: I’m always happy to hear from you.
|
||||
disclaimer: The prices listed above are not meant to be understood as a binding offer.
|
||||
|
||||
de:
|
||||
heading: Kontakt
|
||||
you_want: Willst du, dass ich …
|
||||
develop_website: deine Webseite entwickle (€ 1000),
|
||||
program_tool: ein Tool programmiere (€ 500),
|
||||
design_print: ein Poster, eine Broschüre oder eine Visitenkarte designe (€ 500),
|
||||
help_server: dir mit deinem Server oder deiner Domain helfe (€ 300)?
|
||||
twitter: Schreib mir auf Twitter
|
||||
or_email: "oder sende mir eine Email:"
|
||||
happy_to_hear: Ich freue mich auf deine Nachricht.
|
||||
disclaimer: Die genannten Preise stellen kein verbindliches Angebot dar.
|
||||
</i18n>
|
||||
|
||||
<script>
|
||||
import { useI18n } from "vue-i18n"
|
||||
import BlurredBlobCanvas from "../components/BlurredBlobCanvas.vue"
|
||||
|
||||
export default {
|
||||
name: "ContactPage"
|
||||
name: "ContactPage",
|
||||
components: { BlurredBlobCanvas },
|
||||
setup() {
|
||||
const { t } = useI18n()
|
||||
return { t }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<main class="flex -md:flex-col justify-between items-start md:items-center min-h-80vh">
|
||||
<div class="font-bold relative -md:pt-20vh -md:pb-20 transform skew-x-7 -skew-y-7 rotate-7">
|
||||
<div class="relative -md:pt-20vh -md:pb-20">
|
||||
<div class="_fade-2">
|
||||
<div class="_pattern transform rotate-179 absolute w-full h-40 -left-4 md:-left-10 top-20vh -md:-mt-10 md:-top-10 opacity-3 md:opacity-5"/>
|
||||
<div class="_pattern transform rotate-179.5 absolute w-full h-40 -left-4 md:-left-10 top-20vh -md:-mt-10 md:-top-10 opacity-3 md:opacity-5"/>
|
||||
</div>
|
||||
<div class="_slide">
|
||||
<ClickToBounce v-slot="{ setTrigger }" class="text-6xl md:text-7xl -md:-mt-2 mb-30 font-special" style="--delay: 0">
|
||||
|
@ -10,49 +10,61 @@
|
|||
</ClickToBounce>
|
||||
</div>
|
||||
<div class="font-special text-3xl sm:text-5xl mb-5 _slide" style="--delay: 200">
|
||||
I’m<br>
|
||||
{{ t("i_am") }}<br>
|
||||
<span class="text-1.1em text-transparent bg-clip-text bg-gradient-to-b from-blue-500 to-blue-900">Moritz Ruth</span>
|
||||
</div>
|
||||
<div class="text-gray-800 text-2xl sm:text-3xl">
|
||||
<ul class="_list">
|
||||
<ul class="asterisk-list">
|
||||
<li class="_slide" style="--delay: 400">
|
||||
software developer
|
||||
{{ t("software_developer") }}
|
||||
</li>
|
||||
<li class="_slide" style="--delay: 600">
|
||||
graphic designer
|
||||
{{ t("designer") }}
|
||||
</li>
|
||||
<li class="_slide" style="--delay: 800">
|
||||
typography enthusiast
|
||||
{{ t("typography_enthusiast") }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<router-link class="mt-10 text-2xl sm:text-3xl block text-blue-900 _slide" style="--delay: 1000" to="/contact">
|
||||
→ {{ t("contact_me") }}
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="self-center">
|
||||
<BlurredBlobCanvas
|
||||
class="_fade-1"
|
||||
:colors="['#6577fc', '#eb34cf', '#6577fc', '#eb34cf']"
|
||||
:size="300"
|
||||
:blur="30"
|
||||
:minimum-duration="2000"
|
||||
:duration-variation="500"
|
||||
:minimum-opacity="0.2"
|
||||
:opacity-variation="0.4"
|
||||
/>
|
||||
</div>
|
||||
<BlurredBlobCanvas
|
||||
class="_fade-1 self-center"
|
||||
:colors="['#6577fc', '#eb34cf', '#6577fc', '#eb34cf']"
|
||||
:size="300"
|
||||
:blur="30"
|
||||
:minimum-duration="2000"
|
||||
:duration-variation="500"
|
||||
:minimum-opacity="0.2"
|
||||
:opacity-variation="0.4"
|
||||
/>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en:
|
||||
i_am: I’m
|
||||
software_developer: software developer
|
||||
designer: web and print designer
|
||||
typography_enthusiast: typography enthusiast
|
||||
contact_me: Drop me a message!
|
||||
|
||||
de:
|
||||
i_am: ""
|
||||
software_developer: Software-Entwickler
|
||||
designer: Web– und Print-Designer
|
||||
typography_enthusiast: Typography-Enthusiast
|
||||
contact_me: Schreib mir!
|
||||
</i18n>
|
||||
|
||||
<style scoped>
|
||||
._pattern {
|
||||
background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='36' height='72' viewBox='0 0 36 72'%3E%3Cg fill-rule='evenodd'%3E%3Cg \
|
||||
fill='%23000000' fill-opacity='1'%3E%3Cpath d='M2 6h12L8 18 2 6zm18 36h12l-6 12-6-12z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
._list > li::before {
|
||||
@apply text-blue-900;
|
||||
content: "*";
|
||||
}
|
||||
|
||||
/* created using emojicursor.app */
|
||||
._clap {
|
||||
cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='50' height='90' viewport='0 0 100 100' style='fill:black;font-size:50px;'><text y='50%'>✋\
|
||||
|
@ -64,7 +76,7 @@
|
|||
}
|
||||
|
||||
._fade-2 {
|
||||
animation: fade 2s 2s ease-out both;
|
||||
animation: fade 2s 1s ease-out both;
|
||||
}
|
||||
|
||||
._slide {
|
||||
|
@ -75,7 +87,7 @@
|
|||
|
||||
@screen md {
|
||||
._slide {
|
||||
animation-delay: calc(var(--delay) * 1.4ms + 1.5s);
|
||||
animation-delay: calc(var(--delay) * 1.4ms + 0.4s);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,11 +115,16 @@
|
|||
</style>
|
||||
|
||||
<script>
|
||||
import { useI18n } from "vue-i18n"
|
||||
import BlurredBlobCanvas from "../components/BlurredBlobCanvas.vue"
|
||||
import ClickToBounce from "../components/ClickToBounce.vue"
|
||||
|
||||
export default {
|
||||
name: "IndexPage",
|
||||
components: { ClickToBounce, BlurredBlobCanvas }
|
||||
components: { ClickToBounce, BlurredBlobCanvas },
|
||||
setup() {
|
||||
const { t } = useI18n()
|
||||
return { t }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
61
src/pages/legal-notice.vue
Normal file
61
src/pages/legal-notice.vue
Normal file
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<main class="prose pt-20">
|
||||
<h1>{{ t("heading") }}</h1>
|
||||
<p v-if="!isGerman">
|
||||
<i>As required by German law.</i>
|
||||
</p>
|
||||
<p>
|
||||
Dieses Impressum gilt für diese Webseite (moritzruth.de) und alle Webseiten, welche unter Subdomains von moritzruth.de erreichbar sind.
|
||||
</p>
|
||||
<h2>Angaben gemäß § 5 TMG</h2>
|
||||
<address>
|
||||
Moritz Ruth<br>
|
||||
Zum Galgenberg 19<br>
|
||||
66539 Neunkirchen
|
||||
</address>
|
||||
<p>
|
||||
E-Mail-Adresse:
|
||||
<a class="text-blue-900" href="mailto:hey@m0.is">
|
||||
hey@m0.is
|
||||
</a>
|
||||
</p>
|
||||
<h2>Haftung für Links</h2>
|
||||
<p>
|
||||
Diese Webseite enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine
|
||||
Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich.
|
||||
</p>
|
||||
<p>
|
||||
Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft.
|
||||
Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar.
|
||||
</p>
|
||||
<p>
|
||||
Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar.
|
||||
Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.
|
||||
</p>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en:
|
||||
heading: Legal Notice
|
||||
|
||||
de:
|
||||
heading: Impressum
|
||||
</i18n>
|
||||
|
||||
<script>
|
||||
import { useI18n } from "vue-i18n"
|
||||
import { computed } from "vue"
|
||||
|
||||
export default {
|
||||
name: "LegalNoticePage",
|
||||
setup() {
|
||||
const { locale, t } = useI18n()
|
||||
|
||||
return {
|
||||
isGerman: computed(() => locale.value.startsWith("de")),
|
||||
t
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,11 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
projects
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ProjectsPage"
|
||||
}
|
||||
</script>
|
29
src/pages/terms-and-conditions.vue
Normal file
29
src/pages/terms-and-conditions.vue
Normal file
|
@ -0,0 +1,29 @@
|
|||
<template>
|
||||
<div class="prose pt-20">
|
||||
<h1>{{ t("heading") }}</h1>
|
||||
<p>{{ t("message") }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en:
|
||||
message: Not yet available.
|
||||
heading: Terms and Conditions
|
||||
|
||||
de:
|
||||
message: Noch nicht verfügbar.
|
||||
heading: Allgemeine Geschäftsbedingungen
|
||||
</i18n>
|
||||
|
||||
<script>
|
||||
import { useI18n } from "vue-i18n"
|
||||
|
||||
export default {
|
||||
name: "TermsAndConditionsPage",
|
||||
setup() {
|
||||
const { t } = useI18n()
|
||||
|
||||
return { t }
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,6 +1,7 @@
|
|||
import vuePlugin from "@vitejs/plugin-vue"
|
||||
import windicssPlugin from "vite-plugin-windicss"
|
||||
import pagesPlugin from "vite-plugin-pages"
|
||||
import vueI18nPlugin from "@intlify/vite-plugin-vue-i18n"
|
||||
|
||||
/**
|
||||
* https://vitejs.dev/config/
|
||||
|
@ -9,6 +10,7 @@ import pagesPlugin from "vite-plugin-pages"
|
|||
export default {
|
||||
plugins: [
|
||||
vuePlugin(),
|
||||
vueI18nPlugin(),
|
||||
pagesPlugin(),
|
||||
windicssPlugin()
|
||||
]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue