Initial Commit

This commit is contained in:
2025-08-14 18:03:08 +01:00
parent 6490b08e08
commit 916c770216
32 changed files with 1595 additions and 10 deletions
+22 -9
View File
@@ -1,11 +1,24 @@
# ---> Vue
# gitignore template for Vue.js projects
#
# Recommended template: Node.gitignore
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
# TODO: where does this rule come from?
docs/_book
# TODO: where does this rule come from?
test/
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
+4 -1
View File
@@ -1,2 +1,5 @@
# vue_portfolio
# Vue 3 + Vite
This template should help get you started developing with Vue 3 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.
Learn more about IDE Support for Vue in the [Vue Docs Scaling up Guide](https://vuejs.org/guide/scaling-up/tooling.html#ide-support).
+294
View File
@@ -0,0 +1,294 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "portfolio",
"dependencies": {
"@tailwindcss/vite": "^4.1.11",
"aos": "^2.3.4",
"emailjs-com": "^3.2.0",
"tailwindcss": "^4.1.11",
"vue": "^3.5.18",
"vue-toast-notification": "^3",
"vue3-carousel": "^0.16.0",
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.1",
"vite": "^7.1.2",
},
},
},
"packages": {
"@ampproject/remapping": ["@ampproject/[email protected]", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="],
"@babel/helper-string-parser": ["@babel/[email protected]", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
"@babel/helper-validator-identifier": ["@babel/[email protected]", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="],
"@babel/parser": ["@babel/[email protected]", "", { "dependencies": { "@babel/types": "^7.28.0" }, "bin": "./bin/babel-parser.js" }, "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g=="],
"@babel/types": ["@babel/[email protected]", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
"@esbuild/aix-ppc64": ["@esbuild/[email protected]", "", { "os": "aix", "cpu": "ppc64" }, "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA=="],
"@esbuild/android-arm": ["@esbuild/[email protected]", "", { "os": "android", "cpu": "arm" }, "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ=="],
"@esbuild/android-arm64": ["@esbuild/[email protected]", "", { "os": "android", "cpu": "arm64" }, "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg=="],
"@esbuild/android-x64": ["@esbuild/[email protected]", "", { "os": "android", "cpu": "x64" }, "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw=="],
"@esbuild/darwin-arm64": ["@esbuild/[email protected]", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg=="],
"@esbuild/darwin-x64": ["@esbuild/[email protected]", "", { "os": "darwin", "cpu": "x64" }, "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ=="],
"@esbuild/freebsd-arm64": ["@esbuild/[email protected]", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q=="],
"@esbuild/freebsd-x64": ["@esbuild/[email protected]", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg=="],
"@esbuild/linux-arm": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "arm" }, "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw=="],
"@esbuild/linux-arm64": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw=="],
"@esbuild/linux-ia32": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "ia32" }, "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A=="],
"@esbuild/linux-loong64": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ=="],
"@esbuild/linux-mips64el": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA=="],
"@esbuild/linux-ppc64": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "ppc64" }, "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w=="],
"@esbuild/linux-riscv64": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg=="],
"@esbuild/linux-s390x": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "s390x" }, "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA=="],
"@esbuild/linux-x64": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg=="],
"@esbuild/netbsd-arm64": ["@esbuild/[email protected]", "", { "os": "none", "cpu": "arm64" }, "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q=="],
"@esbuild/netbsd-x64": ["@esbuild/[email protected]", "", { "os": "none", "cpu": "x64" }, "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g=="],
"@esbuild/openbsd-arm64": ["@esbuild/[email protected]", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ=="],
"@esbuild/openbsd-x64": ["@esbuild/[email protected]", "", { "os": "openbsd", "cpu": "x64" }, "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA=="],
"@esbuild/openharmony-arm64": ["@esbuild/[email protected]", "", { "os": "none", "cpu": "arm64" }, "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg=="],
"@esbuild/sunos-x64": ["@esbuild/[email protected]", "", { "os": "sunos", "cpu": "x64" }, "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw=="],
"@esbuild/win32-arm64": ["@esbuild/[email protected]", "", { "os": "win32", "cpu": "arm64" }, "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ=="],
"@esbuild/win32-ia32": ["@esbuild/[email protected]", "", { "os": "win32", "cpu": "ia32" }, "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww=="],
"@esbuild/win32-x64": ["@esbuild/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ=="],
"@isaacs/fs-minipass": ["@isaacs/[email protected]", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
"@jridgewell/gen-mapping": ["@jridgewell/[email protected]", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
"@jridgewell/resolve-uri": ["@jridgewell/[email protected]", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
"@jridgewell/sourcemap-codec": ["@jridgewell/[email protected]", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
"@jridgewell/trace-mapping": ["@jridgewell/[email protected]", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
"@rolldown/pluginutils": ["@rolldown/[email protected]", "", {}, "sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/[email protected]", "", { "os": "android", "cpu": "arm" }, "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA=="],
"@rollup/rollup-android-arm64": ["@rollup/[email protected]", "", { "os": "android", "cpu": "arm64" }, "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ=="],
"@rollup/rollup-darwin-arm64": ["@rollup/[email protected]", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ=="],
"@rollup/rollup-darwin-x64": ["@rollup/[email protected]", "", { "os": "darwin", "cpu": "x64" }, "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA=="],
"@rollup/rollup-freebsd-arm64": ["@rollup/[email protected]", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg=="],
"@rollup/rollup-freebsd-x64": ["@rollup/[email protected]", "", { "os": "freebsd", "cpu": "x64" }, "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw=="],
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/[email protected]", "", { "os": "linux", "cpu": "arm" }, "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA=="],
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/[email protected]", "", { "os": "linux", "cpu": "arm" }, "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ=="],
"@rollup/rollup-linux-arm64-gnu": ["@rollup/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng=="],
"@rollup/rollup-linux-arm64-musl": ["@rollup/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg=="],
"@rollup/rollup-linux-loongarch64-gnu": ["@rollup/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA=="],
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/[email protected]", "", { "os": "linux", "cpu": "ppc64" }, "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw=="],
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ=="],
"@rollup/rollup-linux-riscv64-musl": ["@rollup/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw=="],
"@rollup/rollup-linux-s390x-gnu": ["@rollup/[email protected]", "", { "os": "linux", "cpu": "s390x" }, "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA=="],
"@rollup/rollup-linux-x64-gnu": ["@rollup/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA=="],
"@rollup/rollup-linux-x64-musl": ["@rollup/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA=="],
"@rollup/rollup-win32-arm64-msvc": ["@rollup/[email protected]", "", { "os": "win32", "cpu": "arm64" }, "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g=="],
"@rollup/rollup-win32-ia32-msvc": ["@rollup/[email protected]", "", { "os": "win32", "cpu": "ia32" }, "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ=="],
"@rollup/rollup-win32-x64-msvc": ["@rollup/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg=="],
"@tailwindcss/node": ["@tailwindcss/[email protected]", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.11" } }, "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q=="],
"@tailwindcss/oxide": ["@tailwindcss/[email protected]", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.11", "@tailwindcss/oxide-darwin-arm64": "4.1.11", "@tailwindcss/oxide-darwin-x64": "4.1.11", "@tailwindcss/oxide-freebsd-x64": "4.1.11", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", "@tailwindcss/oxide-linux-x64-musl": "4.1.11", "@tailwindcss/oxide-wasm32-wasi": "4.1.11", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" } }, "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg=="],
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/[email protected]", "", { "os": "android", "cpu": "arm64" }, "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg=="],
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/[email protected]", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ=="],
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/[email protected]", "", { "os": "darwin", "cpu": "x64" }, "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw=="],
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/[email protected]", "", { "os": "freebsd", "cpu": "x64" }, "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA=="],
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/[email protected]", "", { "os": "linux", "cpu": "arm" }, "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg=="],
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ=="],
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ=="],
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg=="],
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q=="],
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/[email protected]", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@emnapi/wasi-threads": "^1.0.2", "@napi-rs/wasm-runtime": "^0.2.11", "@tybys/wasm-util": "^0.9.0", "tslib": "^2.8.0" }, "cpu": "none" }, "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g=="],
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/[email protected]", "", { "os": "win32", "cpu": "arm64" }, "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w=="],
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg=="],
"@tailwindcss/vite": ["@tailwindcss/[email protected]", "", { "dependencies": { "@tailwindcss/node": "4.1.11", "@tailwindcss/oxide": "4.1.11", "tailwindcss": "4.1.11" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw=="],
"@types/estree": ["@types/[email protected]", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
"@vitejs/plugin-vue": ["@vitejs/[email protected]", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-beta.29" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", "vue": "^3.2.25" } }, "sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw=="],
"@vue/compiler-core": ["@vue/[email protected]", "", { "dependencies": { "@babel/parser": "^7.28.0", "@vue/shared": "3.5.18", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-3slwjQrrV1TO8MoXgy3aynDQ7lslj5UqDxuHnrzHtpON5CBinhWjJETciPngpin/T3OuW3tXUf86tEurusnztw=="],
"@vue/compiler-dom": ["@vue/[email protected]", "", { "dependencies": { "@vue/compiler-core": "3.5.18", "@vue/shared": "3.5.18" } }, "sha512-RMbU6NTU70++B1JyVJbNbeFkK+A+Q7y9XKE2EM4NLGm2WFR8x9MbAtWxPPLdm0wUkuZv9trpwfSlL6tjdIa1+A=="],
"@vue/compiler-sfc": ["@vue/[email protected]", "", { "dependencies": { "@babel/parser": "^7.28.0", "@vue/compiler-core": "3.5.18", "@vue/compiler-dom": "3.5.18", "@vue/compiler-ssr": "3.5.18", "@vue/shared": "3.5.18", "estree-walker": "^2.0.2", "magic-string": "^0.30.17", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "sha512-5aBjvGqsWs+MoxswZPoTB9nSDb3dhd1x30xrrltKujlCxo48j8HGDNj3QPhF4VIS0VQDUrA1xUfp2hEa+FNyXA=="],
"@vue/compiler-ssr": ["@vue/[email protected]", "", { "dependencies": { "@vue/compiler-dom": "3.5.18", "@vue/shared": "3.5.18" } }, "sha512-xM16Ak7rSWHkM3m22NlmcdIM+K4BMyFARAfV9hYFl+SFuRzrZ3uGMNW05kA5pmeMa0X9X963Kgou7ufdbpOP9g=="],
"@vue/reactivity": ["@vue/[email protected]", "", { "dependencies": { "@vue/shared": "3.5.18" } }, "sha512-x0vPO5Imw+3sChLM5Y+B6G1zPjwdOri9e8V21NnTnlEvkxatHEH5B5KEAJcjuzQ7BsjGrKtfzuQ5eQwXh8HXBg=="],
"@vue/runtime-core": ["@vue/[email protected]", "", { "dependencies": { "@vue/reactivity": "3.5.18", "@vue/shared": "3.5.18" } }, "sha512-DUpHa1HpeOQEt6+3nheUfqVXRog2kivkXHUhoqJiKR33SO4x+a5uNOMkV487WPerQkL0vUuRvq/7JhRgLW3S+w=="],
"@vue/runtime-dom": ["@vue/[email protected]", "", { "dependencies": { "@vue/reactivity": "3.5.18", "@vue/runtime-core": "3.5.18", "@vue/shared": "3.5.18", "csstype": "^3.1.3" } }, "sha512-YwDj71iV05j4RnzZnZtGaXwPoUWeRsqinblgVJwR8XTXYZ9D5PbahHQgsbmzUvCWNF6x7siQ89HgnX5eWkr3mw=="],
"@vue/server-renderer": ["@vue/[email protected]", "", { "dependencies": { "@vue/compiler-ssr": "3.5.18", "@vue/shared": "3.5.18" }, "peerDependencies": { "vue": "3.5.18" } }, "sha512-PvIHLUoWgSbDG7zLHqSqaCoZvHi6NNmfVFOqO+OnwvqMz/tqQr3FuGWS8ufluNddk7ZLBJYMrjcw1c6XzR12mA=="],
"@vue/shared": ["@vue/[email protected]", "", {}, "sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA=="],
"aos": ["[email protected]", "", { "dependencies": { "classlist-polyfill": "^1.0.3", "lodash.debounce": "^4.0.6", "lodash.throttle": "^4.0.1" } }, "sha512-zh/ahtR2yME4I51z8IttIt4lC1Nw0ktsFtmeDzID1m9naJnWXhCoARaCgNOGXb5CLy3zm+wqmRAEgMYB5E2HUw=="],
"chownr": ["[email protected]", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
"classlist-polyfill": ["[email protected]", "", {}, "sha512-GzIjNdcEtH4ieA2S8NmrSxv7DfEV5fmixQeyTmqmRmRJPGpRBaSnA2a0VrCjyT8iW8JjEdMbKzDotAJf+ajgaQ=="],
"csstype": ["[email protected]", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
"detect-libc": ["[email protected]", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
"emailjs-com": ["[email protected]", "", {}, "sha512-Prbz3E1usiAwGjMNYRv6EsJ5c373cX7/AGnZQwOfrpNJrygQJ15+E9OOq4pU8yC977Z5xMetRfc3WmDX6RcjAA=="],
"enhanced-resolve": ["[email protected]", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="],
"entities": ["[email protected]", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"esbuild": ["[email protected]", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.9", "@esbuild/android-arm": "0.25.9", "@esbuild/android-arm64": "0.25.9", "@esbuild/android-x64": "0.25.9", "@esbuild/darwin-arm64": "0.25.9", "@esbuild/darwin-x64": "0.25.9", "@esbuild/freebsd-arm64": "0.25.9", "@esbuild/freebsd-x64": "0.25.9", "@esbuild/linux-arm": "0.25.9", "@esbuild/linux-arm64": "0.25.9", "@esbuild/linux-ia32": "0.25.9", "@esbuild/linux-loong64": "0.25.9", "@esbuild/linux-mips64el": "0.25.9", "@esbuild/linux-ppc64": "0.25.9", "@esbuild/linux-riscv64": "0.25.9", "@esbuild/linux-s390x": "0.25.9", "@esbuild/linux-x64": "0.25.9", "@esbuild/netbsd-arm64": "0.25.9", "@esbuild/netbsd-x64": "0.25.9", "@esbuild/openbsd-arm64": "0.25.9", "@esbuild/openbsd-x64": "0.25.9", "@esbuild/openharmony-arm64": "0.25.9", "@esbuild/sunos-x64": "0.25.9", "@esbuild/win32-arm64": "0.25.9", "@esbuild/win32-ia32": "0.25.9", "@esbuild/win32-x64": "0.25.9" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g=="],
"estree-walker": ["[email protected]", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
"fdir": ["[email protected]", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w=="],
"fsevents": ["[email protected]", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"graceful-fs": ["[email protected]", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
"jiti": ["[email protected]", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="],
"lightningcss": ["[email protected]", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="],
"lightningcss-darwin-arm64": ["[email protected]", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="],
"lightningcss-darwin-x64": ["[email protected]", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="],
"lightningcss-freebsd-x64": ["[email protected]", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="],
"lightningcss-linux-arm-gnueabihf": ["[email protected]", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="],
"lightningcss-linux-arm64-gnu": ["[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="],
"lightningcss-linux-arm64-musl": ["[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="],
"lightningcss-linux-x64-gnu": ["[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="],
"lightningcss-linux-x64-musl": ["[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="],
"lightningcss-win32-arm64-msvc": ["[email protected]", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="],
"lightningcss-win32-x64-msvc": ["[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="],
"lodash.debounce": ["[email protected]", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="],
"lodash.throttle": ["[email protected]", "", {}, "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="],
"magic-string": ["[email protected]", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
"minipass": ["[email protected]", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
"minizlib": ["[email protected]", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="],
"mkdirp": ["[email protected]", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="],
"nanoid": ["[email protected]", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"picocolors": ["[email protected]", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["[email protected]", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
"postcss": ["[email protected]", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
"rollup": ["[email protected]", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.46.2", "@rollup/rollup-android-arm64": "4.46.2", "@rollup/rollup-darwin-arm64": "4.46.2", "@rollup/rollup-darwin-x64": "4.46.2", "@rollup/rollup-freebsd-arm64": "4.46.2", "@rollup/rollup-freebsd-x64": "4.46.2", "@rollup/rollup-linux-arm-gnueabihf": "4.46.2", "@rollup/rollup-linux-arm-musleabihf": "4.46.2", "@rollup/rollup-linux-arm64-gnu": "4.46.2", "@rollup/rollup-linux-arm64-musl": "4.46.2", "@rollup/rollup-linux-loongarch64-gnu": "4.46.2", "@rollup/rollup-linux-ppc64-gnu": "4.46.2", "@rollup/rollup-linux-riscv64-gnu": "4.46.2", "@rollup/rollup-linux-riscv64-musl": "4.46.2", "@rollup/rollup-linux-s390x-gnu": "4.46.2", "@rollup/rollup-linux-x64-gnu": "4.46.2", "@rollup/rollup-linux-x64-musl": "4.46.2", "@rollup/rollup-win32-arm64-msvc": "4.46.2", "@rollup/rollup-win32-ia32-msvc": "4.46.2", "@rollup/rollup-win32-x64-msvc": "4.46.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg=="],
"source-map-js": ["[email protected]", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"tailwindcss": ["[email protected]", "", {}, "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA=="],
"tapable": ["[email protected]", "", {}, "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg=="],
"tar": ["[email protected]", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="],
"tinyglobby": ["[email protected]", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
"vite": ["[email protected]", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ=="],
"vue": ["[email protected]", "", { "dependencies": { "@vue/compiler-dom": "3.5.18", "@vue/compiler-sfc": "3.5.18", "@vue/runtime-dom": "3.5.18", "@vue/server-renderer": "3.5.18", "@vue/shared": "3.5.18" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-7W4Y4ZbMiQ3SEo+m9lnoNpV9xG7QVMLa+/0RFwwiAVkeYoyGXqWE85jabU4pllJNUzqfLShJ5YLptewhCWUgNA=="],
"vue-toast-notification": ["[email protected]", "", { "peerDependencies": { "vue": "^3.0" } }, "sha512-XNyWqwLIGBFfX5G9sK+clq3N3IPlhDjzNdbZaXkEElcotPlWs0wWZailk1vqhdtLYT/93Y4FHAVuzyatLmPZRA=="],
"vue3-carousel": ["[email protected]", "", { "peerDependencies": { "vue": "^3.5.0" } }, "sha512-IKRKtvHP8gNDRHSzINXwFbJ/Zy2HS+Gv2lXPnAEop6pxsvB17+fz2WQlNZ6ytilLkM5DOu/jXPoDQi/xy17bjg=="],
"yallist": ["[email protected]", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/[email protected]", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.4", "tslib": "^2.4.0" }, "bundled": true }, "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/[email protected]", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/[email protected]", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g=="],
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/[email protected]", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" }, "bundled": true }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/[email protected]", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="],
"@tailwindcss/oxide-wasm32-wasi/tslib": ["[email protected]", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/[email protected]", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="],
}
}
+3
View File
@@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar"]
}
+13
View File
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/assets/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Fernando Videira's Portfolio</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
+24
View File
@@ -0,0 +1,24 @@
{
"name": "portfolio",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@tailwindcss/vite": "^4.1.11",
"aos": "^2.3.4",
"emailjs-com": "^3.2.0",
"tailwindcss": "^4.1.11",
"vue": "^3.5.18",
"vue-toast-notification": "^3",
"vue3-carousel": "^0.16.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.1",
"vite": "^7.1.2"
}
}
+1
View File
@@ -0,0 +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="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+57
View File
@@ -0,0 +1,57 @@
<template>
<div class="font-logo bg-gray-950 min-h-screen">
<Suspense>
<template #default>
<div>
<NavBar />
<Hero />
<Services />
<About />
<Skills />
<Projects />
<!-- <Testimonials /> -->
<Contact />
<Footer />
<BackToTop />
</div>
</template>
<template #fallback>
<div class="flex justify-center items-center min-h-screen">
<LoadingSpinner />
</div>
</template>
</Suspense>
</div>
</template>
<script setup>
import { defineAsyncComponent } from "vue";
const NavBar = defineAsyncComponent(() => import("@/components/Navbar.vue"));
const Hero = defineAsyncComponent(() => import("@/components/Hero.vue"));
const Services = defineAsyncComponent(() =>
import("@/components/Services.vue")
);
const About = defineAsyncComponent(() => import("@/components/About.vue"));
const Skills = defineAsyncComponent(() => import("@/components/Skills.vue"));
const Projects = defineAsyncComponent(() =>
import("@/components/Projects.vue")
);
// const Testimonials = defineAsyncComponent(() =>
// import("@/components/Testemonial.vue")
// );
const Contact = defineAsyncComponent(() => import("@/components/Contact.vue"));
const Footer = defineAsyncComponent(() => import("@/components/Footer.vue"));
const BackToTop = defineAsyncComponent(() =>
import("@/components/BackToTop.vue")
);
import LoadingSpinner from "@/components/LoadingSpinner.vue";
</script>
<style>
* {
scrollbar-width: thin;
scrollbar-color: #111827 #f1f1f1;
}
</style>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="500" zoomAndPan="magnify" viewBox="0 0 375 374.999991" height="500" preserveAspectRatio="xMidYMid meet" version="1.0"><defs><clipPath id="dfb47b435a"><path d="M 82 90.4375 L 293.351562 90.4375 L 293.351562 284.6875 L 82 284.6875 Z M 82 90.4375 " clip-rule="nonzero"/></clipPath></defs><rect x="-37.5" width="450" fill="#ffffff" y="-37.499999" height="449.999989" fill-opacity="1"/><rect x="-37.5" width="450" fill="#000000" y="-37.499999" height="449.999989" fill-opacity="1"/><g clip-path="url(#dfb47b435a)"><path fill="#ffffff" d="M 256.140625 90.4375 C 256.230469 153.992188 256.226562 176.601562 256.226562 199.214844 C 256.226562 200.023438 256.0625 200.832031 255.910156 202.296875 C 255.910156 202.296875 255.90625 202.292969 255.90625 202.292969 L 236.234375 185.234375 C 219.777344 170.863281 203.328125 156.480469 186.835938 142.148438 C 186.53125 141.882812 186.152344 141.648438 185.75 141.460938 L 169.835938 127.660156 C 171.527344 127.496094 173.25 127.386719 175.007812 127.347656 C 182.699219 127.171875 190.394531 127.117188 240.265625 127.121094 L 240.265625 90.558594 C 190.644531 90.472656 183.191406 90.492188 175.746094 90.523438 C 154.546875 90.597656 135.253906 96.671875 118.527344 109.757812 C 95.390625 127.84375 82.710938 151.675781 82.285156 181.164062 C 81.890625 208.75 82.082031 236.34375 82.128906 284.558594 L 119.011719 284.558594 C 119.011719 253.054688 119.011719 240.308594 119.011719 227.570312 C 119.011719 224.382812 119.027344 224.378906 122.160156 224.378906 C 148.136719 224.378906 174.117188 224.378906 200.09375 224.378906 C 200.898438 224.378906 201.707031 224.378906 202.507812 224.378906 C 202.675781 224.101562 202.839844 223.820312 203.007812 223.542969 C 202.375 223.125 201.6875 222.773438 201.121094 222.28125 C 188.414062 211.238281 175.710938 200.195312 163.042969 189.109375 C 161.785156 188.007812 160.496094 187.574219 158.824219 187.582031 C 146.578125 187.636719 134.335938 187.613281 122.085938 187.605469 C 119.101562 187.605469 119.039062 187.601562 118.988281 184.527344 C 118.835938 175.164062 120.652344 166.214844 125.175781 157.96875 C 127.730469 153.316406 130.617188 149.183594 133.832031 145.570312 L 176.632812 182.691406 C 196.023438 199.566406 215.417969 216.445312 234.789062 233.335938 C 253.65625 249.785156 272.492188 266.277344 291.34375 282.738281 C 291.730469 283.078125 292.203125 283.3125 293.0625 283.875 C 293.0625 282.738281 293.0625 282.0625 293.0625 281.382812 C 293.0625 231.375 293.066406 181.375 293.066406 90.425781 L 256.140625 90.425781 Z M 256.140625 90.4375 " fill-opacity="1" fill-rule="nonzero"/></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

+1
View File
@@ -0,0 +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>

After

Width:  |  Height:  |  Size: 496 B

+114
View File
@@ -0,0 +1,114 @@
<template>
<section class="text-white mt-18" id="about">
<div class="absolute z-0 top-[93rem] inset-x-0 h-64 flex items-start">
<div
class="h-24 w-64 bg-gradient-to-br from-primary via-secondary blur-2xl to-[#570cac] opacity-20"
></div>
</div>
<div
class="md:grid md:grid-cols-2 gap-8 items-center py-8 px-4 xl:gap-16 sm:py-16 xl:px-16 z-1"
>
<div data-aos="flip-right">
<h2 class="text-4xl font-bold text-white text-left mb-8">
My Education
</h2>
<div class="space-y-8 py-8">
<div
v-for="el in education"
:key="el.id"
class="flex items-center md:w-[80%] w-full rounded-xl bg-gray-900 shadow-lg border border-[#1f1641]"
>
<div class="w-1/4 items-center justify-center flex">
<img
src="https://img.icons8.com/ios-glyphs/60/ffffff/graduation-cap--v1.png"
alt="graduation-cap--v1"
/>
</div>
<div class="w-3/4 pl-4 py-2">
<h3
class="text-2xl font-semibold uppercase text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary lg:text-xl"
>
{{ el.institution }}
</h3>
<p class="text-white">{{ el.course }}</p>
<p class="text-gray-400">{{ el.year }}</p>
</div>
</div>
</div>
</div>
<div
class="mt-4 md:mt-0 text-left flex flex-col z-10 h-full"
data-aos="flip-right"
>
<h2 class="text-4xl font-bold text-white md:text-center text-left mb-4">
More
<span
class="text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary"
>About</span
>
Me
</h2>
<p class="text-base lg:text-lg mt-8 py-8 text-justify">
I am a Software Engineering student from Portugal with 4+ years of
experience from my internships and Self Learning + Personal Projects.
I am passionate about technology and always eager to learn more. I am
currently pursuing my Bachelor's on Software Engineering after having
completed a CTeSP in programming, where I gained a solid foundation in
C, .NET, PHP, Java, and MySQL. In my free time I've taken a few online
courses on Unity 3D, Swift/SwiftUI, Cypress, Git, React, Golang. I've
also had the pleasure to be a QA/QC Intern at VOID Software in Leiria
for five months. There, I contributed to the testing and quality
assurance of several projects, using Cypress and Cucumber to automate
and streamline the testing process and Git to manage the source code
and collaborate with the development team. I am always looking for new
challenges and opportunities to grow as a developer.
</p>
<div class="grid grid-cols-3 gap-4 max-w-lg pt-8">
<div
class="text-center rounded-xl bg-gray-900 shadow-lg border border-[#1f1641] p-3"
>
<h3 class="text-white font-bold text-xl sm:text-2xl lg:text-3xl">
+200
</h3>
<p class="text-sm sm:text-base text-gray-300">Happy Clients</p>
</div>
<div
class="text-center rounded-xl bg-gray-900 shadow-lg border border-[#1f1641] p-3"
>
<h3 class="text-white font-bold text-xl sm:text-2xl lg:text-3xl">
+4
</h3>
<p class="text-sm sm:text-base text-gray-300">Years Experience</p>
</div>
<div
class="text-center rounded-xl bg-gray-900 shadow-lg border border-[#1f1641] p-3"
>
<h3 class="text-white font-bold text-xl sm:text-2xl lg:text-3xl">
+300
</h3>
<p class="text-sm sm:text-base text-gray-300">Projects</p>
</div>
</div>
</div>
</div>
</section>
</template>
<script setup>
import { ref } from "vue";
const education = ref([
{
id: 1,
course: "CTeSP in Programing and IT",
institution: "Polytechnic of Leiria",
year: "2023",
},
{
id: 2,
course: "Bachelor's Degree in Software Engineering",
institution: "Polytechnic of Leiria",
year: "2026 (Expected)",
},
]);
</script>
+33
View File
@@ -0,0 +1,33 @@
<template>
<button
v-if="isVisible"
@click="scrollToTop"
class="fixed bottom-4 right-4 bg-gradient-to-r from-primary to-pink-500 text-white rounded-full w-12 h-12 flex items-center justify-center text-xl cursor-pointer transition-opacity duration-300 hover:bg-blue-600"
>
</button>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
const isVisible = ref(false);
const handleScroll = () => {
isVisible.value = window.scrollY > 300;
};
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};
onMounted(() => {
window.addEventListener("scroll", handleScroll);
});
onUnmounted(() => {
window.removeEventListener("scroll", handleScroll);
});
</script>
+203
View File
@@ -0,0 +1,203 @@
<template>
<section class="text-white mt-20" id="contact">
<h2 class="text-4xl font-bold text-white text-left mb-4 px-4 xl:pl-16">
Let's Connect
</h2>
<div
class="grid md:grid-cols-2 gap-4 relative px-4 xl:px-16 mt-8"
data-aos="zoom-in-up"
>
<div>
<p class="text-[#ADB7BE]">
Check my email and linkedin or send a message here to get in touch!
</p>
<div class="col-lg-4 col-md-4 mb-lg-0 mt-5">
<div class="flex mb-10 items-center">
<div
class="p-2"
style="
background: #111a3e;
width: 50px;
height: 46px;
display: flex;
justify-content: center;
border-radius: 50%;
overflow: hidden;
border: 1px solid #111a3e;
backdrop-filter: blur(9px);
-webkit-backdrop-filter: blur(9px);
"
>
<img
src="https://img.icons8.com/metro/50/ffffff/new-post.png"
alt="new-post"
class="w-6"
/>
</div>
<div class="ml-5 text-white">
<h4>Email</h4>
<p class="text-[#ADB7BE]">info@fernandovideira.com</p>
</div>
</div>
<div class="flex mb-10 items-center">
<div
class="p-2"
style="
background: #111a3e;
width: 50px;
height: 46px;
display: flex;
justify-content: center;
border-radius: 50%;
overflow: hidden;
border: 1px solid #111a3e;
backdrop-filter: blur(9px);
-webkit-backdrop-filter: blur(9px);
"
>
<img
src="https://img.icons8.com/ios-filled/50/ffffff/phone.png"
alt="new-post"
class="w-6"
/>
</div>
<div class="ml-5 text-white">
<h4>Phone</h4>
<p class="text-[#ADB7BE]">(+351) 923-543-517</p>
</div>
</div>
<div class="flex mb-10 items-center">
<div
class="p-2"
style="
background: #111a3e;
width: 50px;
height: 46px;
display: flex;
justify-content: center;
border-radius: 50%;
overflow: hidden;
border: 1px solid #111a3e;
backdrop-filter: blur(9px);
-webkit-backdrop-filter: blur(9px);
"
>
<img
src="https://img.icons8.com/ios-filled/50/ffffff/linkedin.png"
alt="new-post"
class="w-6"
/>
</div>
<div class="ml-5 text-white">
<h4>Linkedin</h4>
<a href="https://www.linkedin.com/in/fernando-videira-info/"
><p class="text-[#ADB7BE]">Fernando Videira</p></a
>
</div>
</div>
</div>
</div>
<div
class="p-6"
style="
background: #101828;
width: 100%;
height: 100%;
border-radius: 20px;
overflow: hidden;
border: 1px solid #111a3e;
backdrop-filter: blur(9px);
-webkit-backdrop-filter: blur(9px);
"
>
<form
ref="form"
class="flex flex-col p-2"
data-aos="zoom-in-up"
@submit.prevent="sendEmail"
>
<div class="mb-6">
<label for="email" class="text-white block mb-2 text-sm font-medium"
>Email</label
>
<input
type="email"
id="email"
class="bg-gray-950 placeholder:[#9CA2A9] text-gray-100 text-sm rounded-lg block w-full p-2.5"
placeholder="[email protected]"
name="email"
/>
</div>
<div class="mb-6">
<label
for="subject"
class="text-white block mb-2 text-sm font-medium"
>Subject</label
>
<input
type="text"
id="subject"
class="bg-gray-950 placeholder:[#9CA2A9] text-gray-100 text-sm rounded-lg block w-full p-2.5"
placeholder="Subject"
name="subject"
/>
</div>
<div class="mb-6">
<label
for="message"
class="text-white block mb-2 text-sm font-medium"
>Message</label
>
<textarea
id="message"
rows="4"
class="bg-gray-950 placeholder:[#9CA2A9] text-gray-100 text-sm rounded-lg block w-full p-2.5"
placeholder="Message"
name="message"
></textarea>
</div>
<button
type="submit"
class="z-1 w-[100%!important] px-6 md:px-7 py-3 rounded-full sm:w-max flex justify-center text-white bg-primary border-2 border-transparent"
>
Send Message
</button>
</form>
</div>
<div
class="bg-gradient-to-tr opacity-25 from-[#570cac] to-primary blur-2xl h-20 w-80 z-0 absolute -top-1/2 -left-4 transform -translate-x-2/3 -translate-1/2"
></div>
</div>
</section>
</template>
<script setup>
import { ref } from "vue";
import emailjs from "emailjs-com";
import { useToast } from "vue-toast-notification";
const $toast = useToast();
const form = ref(null);
const sendEmail = async () => {
const isEmpty = [...form.value.elements].some(
(el) => el.tagName !== "BUTTON" && el.type !== "submit" && !el.value.trim()
);
if (isEmpty) {
$toast.warning("Please fill in all fields");
return;
}
try {
const result = await emailjs.sendForm(
"service_0oh6s0e",
"template_4s8pg7r",
form.value,
"fSghIDn2dawqKYyH7"
);
$toast.success("Email sent successfully!");
form.value.reset();
} catch (err) {
$toast.error("Error sending email. Try again later.");
}
};
</script>
+12
View File
@@ -0,0 +1,12 @@
<template>
<footer
class="mt-8 border z-10 border-[#33353F] border-l-transparent border-r-transparent text-white"
>
<div class="container p-12 flex justify-between">
<div>
<img src="@/assets/logo.png" alt="Logo" width="40" height="40" />
</div>
<p class="text-slate-600">© All rights reserved.</p>
</div>
</footer>
</template>
+122
View File
@@ -0,0 +1,122 @@
<template>
<section class="relative w-full" data-aos="zoom-in-up">
<div class="absolute top-0 inset-x-0 h-64 flex items-start">
<div
class="h-24 w-2/3 bg-gradient-to-br from-[#570cac] blur-2xl invisible opacity-40"
></div>
<div
class="h-20 w-3/5 bg-gradient-to-r from-[#670ccf] opacity-40 blur-2xl"
></div>
</div>
<div
class="w-full px-5 sm:px-8 md:px-12 max-w-screen-lg lg:max-w-screen-xl mx-auto relative"
>
<div
class="grid lg:grid-cols-2 gap-10 xl:gap-14 relative pt-24 lg:max-w-none max-w-2xl md:max-w-3xl mx-auto"
>
<div class="lg:py-6">
<div class="text-center lg:text-left">
<h1
class="pt-4 text-white font-bold text-4xl md:text-5xl lg:text-6xl"
>
Hi, I'm
<span
class="text-transparent bg-clip-text bg-gradient-to-r from-primary to-pink-500"
>Fernando</span
>🧑🏻‍💻
</h1>
</div>
<p
class="text-gray-300 pt-8 text-center lg:text-left mx-auto max-w-xl"
>
I'm a passionate Software Engineering student and Entrepreneur
always looking for new challenges!
</p>
<div
class="flex items-center gap-3 pt-9 flex-col sm:flex-row sm:w-max sm:mx-auto lg:mx-0"
>
<button
class="px-6 md:px-7 py-3 rounded-full relative group w-full sm:w-max flex justify-center"
>
<a href="#contact" class="absolute z-1 inset-0 rounded-3xl"></a>
<span
class="absolute inset-0 rounded-3xl group-hover:scale-105 origin-center transition-all ease-in-out bg-primary border-2 border-transparent"
></span>
<span class="relative flex items-center justify-center text-white"
>Hire Me</span
>
</button>
<button
class="border border-primary px-6 md:px-7 py-3 rounded-full relative group w-full sm:w-max flex justify-center"
>
<div
class="hover:scale-105 transition-all ease-in-out flex justify-center items-center relative"
>
<div class="svg-container">
<svg
class="download-icon"
width="18"
height="22"
viewBox="0 0 18 22"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
class="download-arrow"
d="M13 9L9 13M9 13L5 9M9 13V1"
stroke="#f59e0b"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M1 17V18C1 18.7956 1.31607 19.5587 1.87868 20.1213C2.44129 20.6839 3.20435 21 4 21H14C14.7956 21 15.5587 20.6839 16.1213 20.1213C16.6839 19.5587 17 18.7956 17 18V17"
stroke="#f59e0b"
stroke-width="2"
stroke-linecap="round"
/>
</svg>
<div class="download-loader text-white hidden2"></div>
</div>
<a
href="/resume.pdf"
download="resume.pdf"
class="pl-2 text-primary"
>Download Resume</a
>
</div>
</button>
</div>
</div>
<div class="lg:h-full md:flex">
<div
class="flex w-full h-96 min-h-[24rem] lg:min-h-[none] lg:w-full lg:h-full items-center relative"
>
<div
class="absolute z-0 top-1/2 -translate-y-1/2 w-5/6 right-0 h-[calc(80%+20px)] bg-gradient-to-tr opacity-25 from-[#570cac] to-primary blur-2xl"
></div>
<div
class="absolute h-full z-10 p-2 -translate-y-1/2 top-1/2 lg:right-3 md:right-40 sm:right-16 rounded-full shadow-lg border border-primary"
>
<img
src="@/assets/profile_image.jpg"
alt="hero picture"
width="500"
height="auto"
loading="lazy"
class="w-full h-full rounded-full object-cover"
/>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
<script setup>
import AOS from "aos";
import "aos/dist/aos.css";
AOS.init();
</script>
+30
View File
@@ -0,0 +1,30 @@
<template>
<div class="flex justify-center items-center h-full">
<svg
class="animate-spin h-16 w-16 text-white"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
<defs>
<linearGradient id="gradient1" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color: #f59e0b" />
<stop offset="100%" style="stop-color: #ec4899" />
</linearGradient>
</defs>
<circle
class="opacity-25"
cx="12"
cy="12"
r="10"
stroke="url(#gradient1)"
stroke-width="4"
fill="none"
></circle>
<path
fill="#f59e0b"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
></path>
</svg>
</div>
</template>
<script setup></script>
+80
View File
@@ -0,0 +1,80 @@
<template>
<header
class="flex justify-between items-center p-6 bg-opacity-50 relative z-20"
>
<div class="text-white text-3xl font-bold">
<div class="flex flex-row items-center">
<img src="@/assets/logo.png" alt="Logo" width="60" height="60" />
<h1>Portfolio</h1>
</div>
</div>
<!-- Mobile Toggle Button -->
<div class="md:hidden z-30">
<button
type="button"
class="block focus:outline-none"
@click="isMenuOpen = !isMenuOpen"
>
<span v-if="isMenuOpen" class="text-5xl">
<img
src="https://img.icons8.com/ios-filled/100/ffffff/delete-sign.png"
alt="close"
width="50"
height="50"
/>
</span>
<span v-else class="text-5xl">
<img
src="https://img.icons8.com/ios-filled/100/ffffff/menu--v6.png"
alt="menu"
width="50"
height="50"
/>
</span>
</button>
</div>
<!-- Navbar Links -->
<nav
:class="[
'fixed inset-0 z-20 flex flex-col items-center justify-center bg-[#111827] md:relative md:bg-transparent md:flex md:justify-between md:flex-row',
isMenuOpen ? 'block' : 'hidden',
]"
>
<ul
class="flex flex-col items-center space-y-5 md:flex-row md:space-x-5 md:space-y-0"
>
<li v-for="item in Menu" :key="item.name">
<a
:href="item.href"
class="block text-white hover:text-primary ease-linear text-2xl md:text-lg"
@click2="scrollToSection(item.href)"
>
{{ item.name }}
</a>
</li>
</ul>
</nav>
</header>
</template>
<script setup>
import { ref } from "vue";
const Menu = ref([
{ name: "Services", href: "#services" },
{ name: "About Me", href: "#about" },
{ name: "Skills", href: "#skills" },
{ name: "Projects", href: "#projects" },
// { name: "Testimonials", href: "#testimonials" },
{ name: "Contact", href: "#contact" },
]);
const isMenuOpen = ref(false);
const scrollToSection = (href) => {
isMenuOpen.value = false;
const section = document.querySelector(href);
if (section) {
section.scrollIntoView({ behavior: "smooth" });
}
};
</script>
+277
View File
@@ -0,0 +1,277 @@
<template>
<section class="text-white mt-20" id="projects">
<div class="px-4 xl:pl-16">
<div class="mb-4 md:flex md:justify-between xl:pr-16">
<h2 class="text-4xl font-bold text-white">My Projects</h2>
<div class="flex space-x-4 mb-4 mt-5 md:mt-0">
<button
class="hover:text-primary z-10"
v-for="cat in ['All', 'Academic', 'Personal']"
:key="cat"
@click="() => (selectedCategory = cat)"
>
{{ cat }}
</button>
</div>
</div>
<ul
class="px-4 sm:py-16 xl:pr-16 grid grid-cols-1 gap-6 pt-10 sm:grid-cols-2 md:gap-10 md:pt-12 lg:grid-cols-3"
data-aos="fade-right"
>
<div v-for="p in filteredProjects" :key="p.id">
<div
class="h-52 md:h-[24rem] rounded-t-xl relative group"
:style="{
backgroundImage: 'url(' + p.image + ')',
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center',
}"
>
<div
class="overlay items-center justify-center absolute top-0 left-0 w-full h-full bg-[#181818] bg-opacity-0 hidden group-hover:flex group-hover:bg-opacity-80 transition-all duration-50"
>
<a
v-if="p.webURL"
:href="p.webURL"
target="_blank"
rel="noopener"
class="h-14 w-14 mr-2 border-2 relative rounded-full border-[#ADB7BE] hover:border-white group/link"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
aria-hidden="true"
data-slot="icon"
class="h-10 w-10 text-[#ADB7BE] absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 cursor-pointer group-hover/link:text-white"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"
></path>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"
></path>
</svg>
</a>
<span
v-else
class="h-14 w-14 mr-2 border-2 relative rounded-full border-gray-600 opacity-40 cursor-not-allowed flex items-center justify-center"
aria-disabled="true"
title="Live demo unavailable"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
aria-hidden="true"
data-slot="icon"
class="h-10 w-10 text-[#ADB7BE] absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 cursor-pointer group-hover/link:text-white"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"
></path>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"
></path>
</svg>
</span>
<a
v-if="p.gitURL"
:href="p.gitURL"
target="_blank"
rel="noopener"
class="h-14 w-14 mr-2 border-2 relative rounded-full border-[#ADB7BE] hover:border-white group/link"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="1.5"
aria-hidden="true"
data-slot="icon"
class="h-10 w-10 text-[#ADB7BE] absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 cursor-pointer"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M17.25 6.75 22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3-4.5 16.5"
></path>
</svg>
</a>
<span
v-else
class="h-14 w-14 mr-2 border-2 relative rounded-full border-gray-600 opacity-40 cursor-not-allowed flex items-center justify-center"
aria-disabled="true"
title="Live demo unavailable"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="1.5"
aria-hidden="true"
data-slot="icon"
class="h-10 w-10 text-[#ADB7BE] absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 cursor-pointer"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M17.25 6.75 22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3-4.5 16.5"
></path>
</svg>
</span>
</div>
</div>
<div
class="text-white rounded-b-xl mt-3 bg-gray-900 shadow-lg border border-[#1f1641] py-6 px-4"
>
<h3 class="text-lg font-semibold uppercase lg:text-xl">
{{ p.title }}
</h3>
<p class="text-[#ADB7BE]">{{ p.description }}</p>
<div class="flex flex-wrap p-2.5">
<div
v-for="tech in p.technologies"
:key="tech"
class="text-center ml-1 mt-1 rounded-3xl bg-gray-800"
style="
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
border: 1px solid #111827;
backdrop-filter: blur(9px);
-webkit-backdrop-filter: blur(9px);
"
>
<p class="px-5 py-2">{{ tech }}</p>
</div>
</div>
</div>
</div>
</ul>
</div>
</section>
</template>
<script setup>
import { ref, computed } from "vue";
const projects = ref([
{
id: 1,
category: "Academic",
image: "src/assets/test.jpg",
title: "Stuff&Go Web Store",
description: "Supermarket e-commerce platform",
technologies: ["PHP", "JavaScript", "MySQL"],
gitURL: "https://github.com/FernandoJVideira/PL2-G7_ProjetoPlatSI",
webURL: "",
},
{
id: 2,
category: "Academic",
image: "src/assets/test.jpg",
title: "Stuff&Go Mobile App",
description: "Mobile application for supermarket shopping.",
technologies: ["Java", "MQTT", "Android"],
gitURL: "https://github.com/FernandoJVideira/PL2-G7_ProjetoAMSI",
webURL: "",
},
{
id: 3,
category: "Academic",
image: "src/assets/RestGest.png",
title: "RestGest",
description: "Restaurant POS system.",
technologies: ["C#", ".Net", "SQL Server"],
gitURL: "https://github.com/FernandoJVideira/PSI_DA_PL2_G",
webURL: "",
},
{
id: 4,
category: "Academic",
image: "src/assets/test.jpg",
title: "La Redoute Product Page UI",
description: "UI design for a La Redoute product page.",
technologies: ["HTML", "Bootstrap", "Three.js"],
gitURL: "https://github.com/FernandoJVideira/SGI_Projeto24",
webURL: "",
},
{
id: 5,
category: "Academic",
image: "src/assets/chat.png",
title: "Secure Chat",
description: "End-to-End Encrypted Multi-Client Chat Application.",
technologies: ["C#", ".Net", "Encryption Algorithms"],
gitURL: "https://github.com/FernandoJVideira/SGI_Projeto24",
webURL: "",
},
{
id: 6,
category: "Personal",
image: "src/assets/velox_bot.png",
title: "Velox Discord Bot",
description: "Multi-purpose Discord bot built in Python.",
technologies: ["Python", "PostgreSQL", "Discord.py"],
gitURL: "https://github.com/FernandoJVideira/VeloxDiscordBot",
webURL: "",
},
{
id: 7,
category: "Personal",
image: "src/assets/velox_web.png",
title: "Velox Web Framework",
description: "Fullstack laravel like web framework built with Go.",
technologies: ["Go"],
gitURL: "https://github.com/FernandoJVideira/velox",
webURL: "",
},
{
id: 8,
category: "Personal",
image: "src/assets/profile_image.jpg",
title: "My Portfolio",
description: "Showcase of my projects and skills built in Vue 3.",
technologies: ["Vue.js", "Tailwind CSS"],
gitURL: "",
webURL: "https://fernandovideira.com",
},
{
id: 9,
category: "Personal",
image: "src/assets/Lk.jpg",
title: "LK Results Website",
description: "Landing Page for my Company.",
technologies: ["React.js", "Typescript"],
gitURL: "",
webURL: "https://lk-results.com",
},
]);
const selectedCategory = ref("All");
const filteredProjects = computed(() => {
if (selectedCategory.value === "All") {
return projects.value;
}
return projects.value.filter(
(p) =>
p.category.toLocaleLowerCase() ===
selectedCategory.value.toLocaleLowerCase()
);
});
</script>
+59
View File
@@ -0,0 +1,59 @@
<template>
<section class="text-white mt-20" id="services">
<div class="px-4 xl:pl-16">
<h2 class="text-4xl font-bold text-white mb-4">My Services</h2>
</div>
<div
class="py-8 xl:px-16 px-4 sm:py-16 grid grid-cols-1 gap-6 pt-10 sm:grid-cols-2 md:gap-10 md:pt-12 lg:grid-cols-3"
>
<div
v-for="service in services"
:key="service.id"
data-aos="fade-up"
class="px-8 py-12 rounded-xl bg-gray-900 shadow-lg border border-[#1f1641]"
>
<div class="mx-auto h-24 w-24 text-center xl:h-28 xl:w-28">
<div>
<img :src="service.icon" alt="service icon" />
</div>
</div>
<div class="text-center">
<h3
class="pt-8 text-lg font-semibold uppercase text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary lg:text-xl"
>
{{ service.name }}
</h3>
<p class="text-gray pt-4 text-sm group-hover:text-white md:text-base">
{{ service.description }}
</p>
</div>
</div>
</div>
</section>
</template>
<script setup>
import { ref } from "vue";
const services = ref([
{
id: 1,
icon: "https://img.icons8.com/ios-filled/100/ffffff/google-code.png",
name: "Frontend Development",
description: "Building responsive and modern web applications.",
},
{
id: 2,
icon: "https://img.icons8.com/external-vectorslab-glyph-vectorslab/1000/fffeee/external-Technical-Writing-mobile-app-development-vectorslab-glyph-vectorslab.png",
name: "Backend Development",
description: "Building robust and scalable server-side RESTful APIs.",
},
{
id: 3,
icon: "https://img.icons8.com/ios-filled/100/ffffff/developer-mode.png",
name: "Mobile Development",
description:
"Building mobile applications with a focus on user experience and performance.",
},
]);
</script>
+104
View File
@@ -0,0 +1,104 @@
<template>
<section class="text-white mt-18" id="skills">
<div class="absolute right-0 top-[110rem] h-full w-full justify-end">
<span class="flex opacity-20">
<span class="w-16 h-32 rounded-l-full flex bg-primary blur-2xl"></span>
<span
class="w-16 h-32 rounded-l-full flex bg-[#f88fc2] blur-2xl mt-14"
></span>
</span>
</div>
<div
class="md:grid md:grid-cols-2 gap-8 items-center py-8 px-4 xl:gap-16 xl:px-16"
>
<div class="mt-4 md:mt-0 text-left flex flex-col z-10 h-full w-[80%]">
<h2 class="text-4xl font-bold text-white text-left mb-4">
My
<span
class="text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary"
>
Skills
</span>
</h2>
<div class="mt-8" v-for="skill in skills">
<div class="flex items-end justify-between" data-aos="fade-right">
<h4 class="font-semibold uppercase text-white">{{ skill.name }}</h4>
<h3 class="text-2xl font-bold text-white">{{ skill.width }}</h3>
</div>
<div class="mt-2 h-1 w-full bg-[#131d30] rounded-full">
<div
class="h-1 rounded-full bg-primary"
:style="{ width: skill.width }"
></div>
</div>
</div>
</div>
<div data-aos="flip-left">
<h2
class="text-4xl font-bold text-white text-left mb-8 md:text-center md:mt-0 mt-8"
>
My Experiences
</h2>
<div class="space-y-8 py-8" data-aos="fade-left">
<div
v-for="exp in experiences"
:key="exp.id"
class="flex items-center rounded-xl p-4 bg-gray-900 shadow-lg border border-[#1f1641]"
>
<div class="w-1/4 items-center justify-center flex">
<img
src="https://img.icons8.com/ios-filled/100/ffffff/lawyer.png"
alt="lawyer"
/>
</div>
<div class="w-3/4 pl-4">
<h3
class="text-2xl font-semibold uppercase text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary"
>
{{ exp.role }}
</h3>
<p class="text-white">{{ exp.company }}</p>
<p class="text-gray-400">{{ exp.date }}</p>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
<script setup>
import { ref } from "vue";
const skills = ref([
{
id: 1,
name: "Go",
width: "90% ",
},
{
id: 2,
name: "C#",
width: "70%",
},
{
id: 3,
name: "Nuxt.js",
width: "55%",
},
{
id: 4,
name: "Python",
width: "45%",
},
]);
const experiences = ref([
{
id: 1,
role: "QA Engineer Intern",
company: "Void Software",
date: "Feb 2023 - Jul 2023",
},
]);
</script>
+110
View File
@@ -0,0 +1,110 @@
<template>
<section class="text-white mt-20" id="testimonials" data-aos="zoom-in">
<h2 class="text-4xl font-bold text-white text-left mb-4 px-4 xl:pl-16">
Testimonials
</h2>
<div class="px-4 xl:px-16">
<Carousel v-bind="settings" :breakpoints="breakpoints">
<Slide v-for="t in testimonials" :key="t.id">
<div class="carousel__item p-4">
<div
class="w-full mx-auto bg-gray-900 shadow-lg border border-[#1f1641] p-5 text-white font-light mb-6"
>
<div class="w-full flex mb-4 items-center">
<div
class="overflow-hidden rounded-full w-10 h-10 bg-gray-50 border border-gray-200"
>
<img :src="t.image" alt="Profile Image" loading="lazy" />
</div>
<h6 class="ml-4 font-bold text-sm uppercase text-white">
{{ t.fullName }}
</h6>
</div>
<div class="w-full">
<p class="text-sm leading-tight">
<span
class="text-lg leading-none italic font-bold text-white mr-1"
>"</span
>{{ t.comment
}}<span
class="text-lg leading-none italic font-bold text-white mr-1"
>"</span
>
</p>
</div>
</div>
</div>
</Slide>
<template #addons>
<Navigation />
</template>
</Carousel>
</div>
</section>
</template>
<script setup>
import { ref } from "vue";
import { Carousel, Navigation, Slide } from "vue3-carousel";
import "vue3-carousel/dist/carousel.css";
const settings = ref({
itemsToShow: 1,
snapAlign: "center",
});
const breakpoints = ref({
700: {
itemsToShow: 2.5,
snapAlign: "center",
},
1024: {
itemsToShow: 3,
snapAlign: "start",
},
});
const testimonials = ref([
{
id: 1,
fullName: "client 1",
image: "src/assets/profile_image.jpg",
comment:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Aperiam minima reprehenderit maiores itaque molestiae optio, voluptatibus iusto eos doloremque consectetur! ",
},
{
id: 2,
fullName: "client 2",
image: "src/assets/profile_image.jpg",
comment:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Aperiam minima reprehenderit maiores itaque molestiae optio, voluptatibus iusto eos doloremque consectetur! ",
},
{
id: 3,
fullName: "client 3",
image: "src/assets/profile_image.jpg",
comment:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Aperiam minima reprehenderit maiores itaque molestiae optio, voluptatibus iusto eos doloremque consectetur! ",
},
{
id: 4,
fullName: "client 4",
image: "src/assets/profile_image.jpg",
comment:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Aperiam minima reprehenderit maiores itaque molestiae optio, voluptatibus iusto eos doloremque consectetur! ",
},
{
id: 5,
fullName: "client 5",
image: "src/assets/profile_image.jpg",
comment:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Aperiam minima reprehenderit maiores itaque molestiae optio, voluptatibus iusto eos doloremque consectetur! ",
},
]);
</script>
<style>
.carousel__prev,
.carousel__next {
color: white !important;
}
</style>
+10
View File
@@ -0,0 +1,10 @@
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import ToastPlugin from "vue-toast-notification";
// Import one of the available themes
//import 'vue-toast-notification/dist/theme-default.css';
import "vue-toast-notification/dist/theme-bootstrap.css";
createApp(App).use(ToastPlugin).mount("#app");
+7
View File
@@ -0,0 +1,7 @@
@import "tailwindcss";
@theme {
--color-primary: #f59e0b;
--color-secondary: #ec4899;
--font-logo: "Outfit", sans-serif;
}
+14
View File
@@ -0,0 +1,14 @@
import { defineConfig } from "vite";
import { fileURLToPath, URL } from "node:url";
import vue from "@vitejs/plugin-vue";
import tailwindcss from "@tailwindcss/vite";
// https://vite.dev/config/
export default defineConfig({
plugins: [vue(), tailwindcss()],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
});