diff --git a/.eslintrc.js b/.eslintrc.js index 180c177..bffd25f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,4 +9,9 @@ module.exports = { 'plugin:nuxt/recommended', 'codex', ], + rules: { + 'jsdoc/require-returns': 'off', + 'no-irregular-whitespace': 'off', + 'import/named': 'off', + }, }; diff --git a/assets/images/alerts-bg.png b/assets/images/alerts-bg.png new file mode 100644 index 0000000..fd5a765 Binary files /dev/null and b/assets/images/alerts-bg.png differ diff --git a/assets/images/check-features.png b/assets/images/check-features.png new file mode 100644 index 0000000..3d648b8 Binary files /dev/null and b/assets/images/check-features.png differ diff --git a/assets/images/check-integrations.png b/assets/images/check-integrations.png new file mode 100644 index 0000000..12c9ac7 Binary files /dev/null and b/assets/images/check-integrations.png differ diff --git a/assets/images/check-secure.png b/assets/images/check-secure.png new file mode 100644 index 0000000..272eca6 Binary files /dev/null and b/assets/images/check-secure.png differ diff --git a/assets/images/feature-event.png b/assets/images/feature-event.png deleted file mode 100644 index 9090ee9..0000000 Binary files a/assets/images/feature-event.png and /dev/null differ diff --git a/assets/images/feature-graph.png b/assets/images/feature-graph.png deleted file mode 100644 index 9abd1ee..0000000 Binary files a/assets/images/feature-graph.png and /dev/null differ diff --git a/assets/images/feature-notify.png b/assets/images/feature-notify.png deleted file mode 100644 index 7260838..0000000 Binary files a/assets/images/feature-notify.png and /dev/null differ diff --git a/assets/images/hand.png b/assets/images/hand.png new file mode 100644 index 0000000..2e63d9c Binary files /dev/null and b/assets/images/hand.png differ diff --git a/assets/images/hawk-desktop.png b/assets/images/hawk-desktop.png deleted file mode 100644 index 159e3c7..0000000 Binary files a/assets/images/hawk-desktop.png and /dev/null differ diff --git a/assets/images/hawk-logo.png b/assets/images/hawk-logo.png index 07f3b3c..f9b8a0d 100644 Binary files a/assets/images/hawk-logo.png and b/assets/images/hawk-logo.png differ diff --git a/assets/images/project-overview.png b/assets/images/project-overview.png new file mode 100644 index 0000000..8f34d12 Binary files /dev/null and b/assets/images/project-overview.png differ diff --git a/assets/images/russian-flag.png b/assets/images/russian-flag.png new file mode 100644 index 0000000..97903e1 Binary files /dev/null and b/assets/images/russian-flag.png differ diff --git a/assets/images/sentry-to-hawk.png b/assets/images/sentry-to-hawk.png new file mode 100644 index 0000000..1b9f3f5 Binary files /dev/null and b/assets/images/sentry-to-hawk.png differ diff --git a/assets/images/telemetry.png b/assets/images/telemetry.png new file mode 100644 index 0000000..526b59c Binary files /dev/null and b/assets/images/telemetry.png differ diff --git a/assets/images/tg-message-corner.png b/assets/images/tg-message-corner.png new file mode 100644 index 0000000..89fc9a8 Binary files /dev/null and b/assets/images/tg-message-corner.png differ diff --git a/assets/images/user-ava-1.png b/assets/images/user-ava-1.png new file mode 100644 index 0000000..ea74a2b Binary files /dev/null and b/assets/images/user-ava-1.png differ diff --git a/assets/images/user-ava-2.png b/assets/images/user-ava-2.png new file mode 100644 index 0000000..eb7b90c Binary files /dev/null and b/assets/images/user-ava-2.png differ diff --git a/assets/images/user-ava-3.png b/assets/images/user-ava-3.png new file mode 100644 index 0000000..5f35337 Binary files /dev/null and b/assets/images/user-ava-3.png differ diff --git a/assets/styles/common.pcss b/assets/styles/common.pcss index 650be93..ee97a72 100644 --- a/assets/styles/common.pcss +++ b/assets/styles/common.pcss @@ -1,11 +1,69 @@ -a { - text-decoration: none; - color: inherit; +:root { font-family: 'Inter', system-ui, sans-serif; } + +@supports (font-variation-settings: normal) { + :root { font-family: 'InterVariable', system-ui, sans-serif; } +} + +html { + font-size: 14px; + line-height: 20px; + word-spacing: 1px; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + box-sizing: border-box; + + background: var(--color-bg-main); +} + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; +} + +/** + * App content max size (1520px) + */ +.block-inner-container { + width: 100%; + max-width: var(--layout-block-inner-container-width); + margin: 0 auto; + padding: 0 var(--layout-paddings-horisontal); +} + + +/** + * Center column max size (1024px) + */ +.block-content-container { + width: 100%; + max-width: var(--layout-content-container-width); + margin: 0 auto; } -.small-heading { - color: var(--color-text-second); - text-transform: uppercase; - font-size: 13px; - font-weight: 500; +.svg-icon { + fill: currentColor; +} + +.link-with-icon { + display: inline-flex; + align-items: center; + gap: 7px; +} + +.desktop-only { + @media (max-width: 850px) { + display: none !important; + } +} + +.mobile-only { + display: none !important; + + @media (max-width: 850px) { + display: block !important; + } } diff --git a/assets/styles/variables.pcss b/assets/styles/variables.pcss index 36c7dbe..5929c6e 100644 --- a/assets/styles/variables.pcss +++ b/assets/styles/variables.pcss @@ -2,27 +2,77 @@ @custom-media --screen-small (max-width: 1024px); @custom-media --screen-mobile (max-width: 850px); @custom-media --screen-mobile-extra-small (max-width: 320px); +@custom-media --screen-desktop (min-width: 851px); +@custom-media --screen-retina (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi); :root { - --color-bg-main: #181B23; - --color-bg-header: #242732; - --color-text-main: #DBE6FF; - --color-bg-button-primary: #4979E4; - --color-text-second: rgba(219, 230, 255, 0.6); /* 60% alpha */ - --color-text-inversed: #242732; - --color-border-light: rgba(219, 230, 255, 0.1); /* 10% alpha */ + --color-bg-main: #000000; + --color-bg-secondary: #101010; + --color-bg-third: #080808; + --color-bg-popover: #231E30; + --color-text-main: #ffffff; + --color-text-secondary: #B5B5B5; + --color-text-third: #707070; + --color-text-link-visited: #6f6087; + + --color-code-text: #E1E4E8; + --color-code-comment: var(--color-text-secondary); + --color-code-token: #F97583; + --color-code-class: #79B8FF; + --color-code-string: #9ECBFF; + --color-code-method: #B392F0; + --color-code-object: #FFAB70; + --color-code-added-line-text: #63FFA1; + --color-code-added-line-bg: #083A1D; + --color-code-removed-line-text: #FF9FA1; + --color-code-removed-line-bg: #352020; + --color-code-highlighted-line-bg: #c63a5423; + + --color-signal: #652CFF; + + --color-button-primary: #652CFF; + --color-button-primary-hover: #5223CC; + --color-button-primary-border: #652CFF; + --color-button-primary-text: #F2F1F4; + + --color-button-secondary: #282B31; + --color-button-secondary-hover: #1E1E1E; + --color-button-secondary-border: #32363C; + --color-button-secondary-text: #D5D9E9; + + --hawk-text-primary: #DBE6FF; + --hawk-text-secondary: #7D849E; + --hawk-text-third: #646C81; + --hawk-color-signal: #4979E4; + --hawk-color-bg-secondary:rgba(125, 132, 158, 0.24); + --hawk-color-bg-main: #242732; + + --z-header: 100; + + + --color-separator: rgba(255, 255, 255, 0.12); + --color-separator-island: #171717; + + --layout-block-inner-container-width: 1520px; + --layout-content-container-width: 1024px; + + --layout-header-height: 64px; --layout-paddings-horisontal: 20px; - --layout-main-col-width: 1024px; + --layout-paddings-grid: 26px; + --layout-paddings-appshell: var(--layout-paddings-horisontal); + --layout-page-content-max-width: 660px; --layout-features-column-width: 620px; + --layout-features-wide-content-width: 847px; - --font-mono: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace; + --font-mono: "JetBrains Mono", SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace; } -@media (--screen-small) { +/* Variable font support */ +@supports (font-variation-settings: normal) { :root { - --layout-main-col-width: 860px; + --font-mono: "JetBrainsMonoVariable", "JetBrains Mono", SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace; } } diff --git a/assets/svg/chevron-down.svg b/assets/svg/chevron-down.svg new file mode 100644 index 0000000..1d5a072 --- /dev/null +++ b/assets/svg/chevron-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svg/chevron-signal.svg b/assets/svg/chevron-signal.svg new file mode 100644 index 0000000..add3fbc --- /dev/null +++ b/assets/svg/chevron-signal.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/assets/svg/codex.svg b/assets/svg/codex.svg new file mode 100644 index 0000000..d169077 --- /dev/null +++ b/assets/svg/codex.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svg/dots.svg b/assets/svg/dots.svg new file mode 100644 index 0000000..939b4e1 --- /dev/null +++ b/assets/svg/dots.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/svg/hawk-logo.svg b/assets/svg/hawk-logo.svg new file mode 100644 index 0000000..1665608 --- /dev/null +++ b/assets/svg/hawk-logo.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svg/integrations/django.svg b/assets/svg/integrations/django.svg new file mode 100644 index 0000000..d07b8e4 --- /dev/null +++ b/assets/svg/integrations/django.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/svg/integrations/fastapi.svg b/assets/svg/integrations/fastapi.svg new file mode 100644 index 0000000..234b98c --- /dev/null +++ b/assets/svg/integrations/fastapi.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/svg/integrations/flask.svg b/assets/svg/integrations/flask.svg new file mode 100644 index 0000000..a1c1abc --- /dev/null +++ b/assets/svg/integrations/flask.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/svg/integrations/go.svg b/assets/svg/integrations/go.svg new file mode 100644 index 0000000..4db004b --- /dev/null +++ b/assets/svg/integrations/go.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svg/integrations/java.svg b/assets/svg/integrations/java.svg new file mode 100644 index 0000000..6cc4b73 --- /dev/null +++ b/assets/svg/integrations/java.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/svg/integrations/javascript.svg b/assets/svg/integrations/javascript.svg new file mode 100644 index 0000000..72a202c --- /dev/null +++ b/assets/svg/integrations/javascript.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svg/integrations/kotlin.svg b/assets/svg/integrations/kotlin.svg new file mode 100644 index 0000000..465d28b --- /dev/null +++ b/assets/svg/integrations/kotlin.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svg/integrations/laravel.svg b/assets/svg/integrations/laravel.svg new file mode 100644 index 0000000..4f3a7f1 --- /dev/null +++ b/assets/svg/integrations/laravel.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/svg/integrations/nodejs.svg b/assets/svg/integrations/nodejs.svg new file mode 100644 index 0000000..04d0e2b --- /dev/null +++ b/assets/svg/integrations/nodejs.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svg/integrations/nuxt.svg b/assets/svg/integrations/nuxt.svg new file mode 100644 index 0000000..28b17af --- /dev/null +++ b/assets/svg/integrations/nuxt.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svg/integrations/php.svg b/assets/svg/integrations/php.svg new file mode 100644 index 0000000..aea4396 --- /dev/null +++ b/assets/svg/integrations/php.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svg/integrations/python.svg b/assets/svg/integrations/python.svg new file mode 100644 index 0000000..8acac2f --- /dev/null +++ b/assets/svg/integrations/python.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/svg/integrations/react.svg b/assets/svg/integrations/react.svg new file mode 100644 index 0000000..1ce77c1 --- /dev/null +++ b/assets/svg/integrations/react.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svg/integrations/sentry.svg b/assets/svg/integrations/sentry.svg new file mode 100644 index 0000000..0c7af0d --- /dev/null +++ b/assets/svg/integrations/sentry.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/svg/integrations/symfony.svg b/assets/svg/integrations/symfony.svg new file mode 100644 index 0000000..6d39721 --- /dev/null +++ b/assets/svg/integrations/symfony.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/svg/integrations/vite.svg b/assets/svg/integrations/vite.svg new file mode 100644 index 0000000..5702c5c --- /dev/null +++ b/assets/svg/integrations/vite.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/svg/integrations/vue.svg b/assets/svg/integrations/vue.svg new file mode 100644 index 0000000..d5f4a1c --- /dev/null +++ b/assets/svg/integrations/vue.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svg/integrations/webpack.svg b/assets/svg/integrations/webpack.svg new file mode 100644 index 0000000..528ce13 --- /dev/null +++ b/assets/svg/integrations/webpack.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svg/russia-bg.svg b/assets/svg/russia-bg.svg new file mode 100644 index 0000000..c632f69 --- /dev/null +++ b/assets/svg/russia-bg.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svg/used-by/befree.svg b/assets/svg/used-by/befree.svg new file mode 100644 index 0000000..5c19016 --- /dev/null +++ b/assets/svg/used-by/befree.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/svg/used-by/ofd.svg b/assets/svg/used-by/ofd.svg new file mode 100644 index 0000000..4b3561b --- /dev/null +++ b/assets/svg/used-by/ofd.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/svg/used-by/rocket.svg b/assets/svg/used-by/rocket.svg new file mode 100644 index 0000000..8d29443 --- /dev/null +++ b/assets/svg/used-by/rocket.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/svg/used-by/slogy.svg b/assets/svg/used-by/slogy.svg new file mode 100644 index 0000000..620cd72 --- /dev/null +++ b/assets/svg/used-by/slogy.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svg/used-by/stworka.svg b/assets/svg/used-by/stworka.svg new file mode 100644 index 0000000..4e70446 --- /dev/null +++ b/assets/svg/used-by/stworka.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svg/used-by/wazzup.svg b/assets/svg/used-by/wazzup.svg new file mode 100644 index 0000000..b8128a2 --- /dev/null +++ b/assets/svg/used-by/wazzup.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/svg/user.svg b/assets/svg/user.svg new file mode 100644 index 0000000..d56aa83 --- /dev/null +++ b/assets/svg/user.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svg/vue.svg b/assets/svg/vue.svg new file mode 100644 index 0000000..0ddb21e --- /dev/null +++ b/assets/svg/vue.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/components/button.vue b/components/button.vue new file mode 100644 index 0000000..0ca1fa9 --- /dev/null +++ b/components/button.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/components/contact.vue b/components/contact.vue index 5707562..0b5ee01 100644 --- a/components/contact.vue +++ b/components/contact.vue @@ -1,45 +1,62 @@ + + diff --git a/components/used-by.vue b/components/used-by.vue new file mode 100644 index 0000000..f75c51a --- /dev/null +++ b/components/used-by.vue @@ -0,0 +1,33 @@ + + + diff --git a/components/user-ava.vue b/components/user-ava.vue new file mode 100644 index 0000000..0b5e51e --- /dev/null +++ b/components/user-ava.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/composables/useIntersectionObserver.ts b/composables/useIntersectionObserver.ts new file mode 100644 index 0000000..7c7f77a --- /dev/null +++ b/composables/useIntersectionObserver.ts @@ -0,0 +1,133 @@ +import { ref, onMounted, onBeforeUnmount } from 'vue'; + +interface UseIntersectionObserverOptions { + threshold?: number; + rootMargin?: string; + once?: boolean; +} + +interface ObserverEntry { + element: HTMLElement; + isVisible: boolean; + options: UseIntersectionObserverOptions; + callbacks: { + onVisible: () => void; + onHidden?: () => void; + }; +} + +/** + * We store the observer instance in a shared variable to avoid creating a new instance for each element. + * And then reuse it for each element. + */ +let sharedObserver: IntersectionObserver | null = null; +const observerEntries = new Map(); + +/** + * Creates or reuses a shared IntersectionObserver instance + */ +function getSharedObserver(): IntersectionObserver { + if (!sharedObserver) { + sharedObserver = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + const observerEntry = observerEntries.get(entry.target as HTMLElement); + + if (observerEntry) { + // Calculate intersection ratio based on element's own threshold + const intersectionRatio = entry.intersectionRatio; + const threshold = observerEntry.options.threshold || 0.3; + const isIntersecting = intersectionRatio >= threshold; + + if (isIntersecting && !observerEntry.isVisible) { + observerEntry.isVisible = true; + observerEntry.callbacks.onVisible(); + + // Disconnect if once is true + if (observerEntry.options.once) { + sharedObserver?.unobserve(entry.target); + observerEntries.delete(entry.target as HTMLElement); + } + } else if (!isIntersecting && !observerEntry.options.once && observerEntry.callbacks.onHidden) { + observerEntry.isVisible = false; + observerEntry.callbacks.onHidden(); + } + } + }); + }, + { + threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], // Multiple thresholds for smooth detection + rootMargin: '0px 0px -80px 0px', // Increased bottom margin for earlier detection + } + ); + } + + return sharedObserver; +} + +/** + * Composable for intersection observer functionality + * Uses a shared observer instance for better performance + * + * @param options + */ +export function useIntersectionObserver(options: UseIntersectionObserverOptions = {}) { + const { + threshold = 0.5, // Higher threshold - element must be 50% visible + rootMargin = '0px 0px -60px 0px', // More padding from bottom + once = true, + } = options; + + const isVisible = ref(false); + const elementRef = ref(null); + + const setupObserver = () => { + if (process.client && elementRef.value) { + const observer = getSharedObserver(); + + // Create observer entry + const entry: ObserverEntry = { + element: elementRef.value, + isVisible: false, + options: { + threshold, + rootMargin, + once, + }, + callbacks: { + onVisible: () => { + isVisible.value = true; + }, + onHidden: once + ? undefined + : () => { + isVisible.value = false; + }, + }, + }; + + observerEntries.set(elementRef.value, entry); + observer.observe(elementRef.value); + } + }; + + const disconnect = () => { + if (elementRef.value && sharedObserver) { + sharedObserver.unobserve(elementRef.value); + observerEntries.delete(elementRef.value); + } + }; + + onMounted(() => { + setupObserver(); + }); + + onBeforeUnmount(() => { + disconnect(); + }); + + return { + isVisible, + elementRef, + }; +} diff --git a/composables/useUTM.ts b/composables/useUTM.ts new file mode 100644 index 0000000..9b28704 --- /dev/null +++ b/composables/useUTM.ts @@ -0,0 +1,25 @@ +/** + * Composable for generating URLs with UTM tracking parameters + * + * @param {string} baseUrl - The base URL to add UTM parameters to + * @param {string} content - The UTM content parameter for tracking + * @returns {Function} A function that returns the URL with UTM parameters + */ +export const useUTM = (baseUrl: string, content: string) => { + /** + * Generates a URL with UTM tracking parameters + * + * @returns The URL with UTM parameters + */ + const getUrl = (): string => { + const url = new URL(baseUrl); + + /* Add UTM parameters */ + url.searchParams.set('utm_source', 'hawk-tracker.ru'); + url.searchParams.set('utm_content', content); + + return url.toString(); + }; + + return getUrl; +}; diff --git a/layouts/default.vue b/layouts/default.vue index f76dc29..48c22ce 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -20,31 +20,5 @@ export default Vue.extend({ diff --git a/nuxt.config.js b/nuxt.config.js index b3c5c2b..d10cbb0 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -18,11 +18,11 @@ export default { }, { name: 'msapplication-TileColor', - content: '#242732', + content: '#000000', }, { name: 'theme-color', - content: '#242732', + content: '#000000', }, { name: 'apple-mobile-web-app-capable', @@ -52,11 +52,6 @@ export default { href: '/favicon.png', sizes: '32x32', }, - { - rel: 'stylesheet', - type: 'text/css', - href: 'https://fonts.googleapis.com/css?family=Roboto:400,500,700,900&display=swap', - }, { rel: 'icon', href: '/favicon.ico', @@ -66,11 +61,28 @@ export default { rel: 'apple-touch-icon', href: '/apple-touch-icon.png', }, + /* Font preloading to prevent font jumping */ + { + rel: 'preload', + href: '/fonts/Inter/InterVariable.woff2', + as: 'font', + type: 'font/woff2', + crossorigin: 'anonymous', + }, + { + rel: 'preload', + href: '/fonts/Inter/Inter-Regular.woff2', + as: 'font', + type: 'font/woff2', + crossorigin: 'anonymous', + }, ], }, // Global CSS (https://go.nuxtjs.dev/config-css) css: [ + '@/static/fonts/Inter/inter.css', + '@/static/fonts/JetBrainsMono/jetbrainsmono.css', '@/assets/styles/variables', '@/assets/styles/common', ], @@ -146,4 +158,9 @@ export default { }, }, }, + + // server: { + // port: 3000, + // host: '0.0.0.0', + // }, }; diff --git a/package.json b/package.json index 371bdef..f5feb95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hawk-yard", - "version": "1.0.0", + "version": "2.0.0", "private": true, "engines": { "node": ">=20.11.0", @@ -8,6 +8,7 @@ }, "scripts": { "dev": "nuxt", + "dev:network": "nuxt --hostname 0.0.0.0 --port 3000", "build": "nuxt build", "start": "nuxt start", "generate": "nuxt generate", diff --git a/pages/index.vue b/pages/index.vue index 4f1073d..daeea66 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -1,101 +1,190 @@