Viridian
Viridian
Explore posts from servers
NNuxt
Created by Viridian on 4/21/2025 in #❓・help
Layout transitions not working between pages
@kapa.ai I have this socket code:
import { useNuxtApp } from 'nuxt/app';

export default defineWebSocketHandler({

open(peer) {
console.log('Peer connected!: ', peer.id);

const chatId = `chat:${peer.request.url.split('/')[5]}`;

peer.subscribe(chatId);

console.log(`Peer ${peer.id} subscribed to chat: ${chatId}`);
},

message(peer, message) {
console.log(`chat:${peer.request.url.split('/')[5]}`);
console.log('Message received: ', message.data instanceof Buffer ? message.data.toString() : message.data);
peer.publish(`chat:${peer.request.url.split('/')[5]}`, message.data);
},

close(peer) {
console.log('Peer disconnected: ', peer.id);
peer.unsubscribe(`chat:${peer.request.url.split('/')[5]}`);
console.log(`Peer ${peer.id} unsubscribed from chat:${peer.request.url.split('/')[5]}`);
},
})
import { useNuxtApp } from 'nuxt/app';

export default defineWebSocketHandler({

open(peer) {
console.log('Peer connected!: ', peer.id);

const chatId = `chat:${peer.request.url.split('/')[5]}`;

peer.subscribe(chatId);

console.log(`Peer ${peer.id} subscribed to chat: ${chatId}`);
},

message(peer, message) {
console.log(`chat:${peer.request.url.split('/')[5]}`);
console.log('Message received: ', message.data instanceof Buffer ? message.data.toString() : message.data);
peer.publish(`chat:${peer.request.url.split('/')[5]}`, message.data);
},

close(peer) {
console.log('Peer disconnected: ', peer.id);
peer.unsubscribe(`chat:${peer.request.url.split('/')[5]}`);
console.log(`Peer ${peer.id} unsubscribed from chat:${peer.request.url.split('/')[5]}`);
},
})
And this Vue code:
<script lang="ts" setup>
import { get, set } from '@vueuse/core';
import { type Message } from '~~/server/repository/message/messageRepository';

definePageMeta({
middleware: ['chat']
})

const route = useRoute();
const toast = useToast();
const { user } = useUserSession();
const scrollRef = ref(null);

const { open, send } = useWebSocket(`/ws/chat/${route.params.id}`, {
immediate: false,

async onMessage(ws, event) {
try {
console.log('received message:', event.data);
const newMessage = JSON.parse(event.data) as Message;
messages.value.push(newMessage);
scrollToBottom();
} catch (error) {
console.error('Error parsing message:', error);
}
}
})

const { data, error, refresh } = useFetch<Message[]>(() => `/api/chat/${route.params.id}/messages`, {
default: () => []
});

const message = ref<string>('');
const messages = ref<Message[]>([]);
const isLoading = ref<boolean>(false);

watchEffect(() => {
if (data.value) {
messages.value = [...data.value];
nextTick(() => scrollToBottom());
}
});

const scrollToBottom = () => {
nextTick(() => {
if (scrollRef.value) {
const container = scrollRef.value;
container.scrollTop = container.scrollHeight;
}
});
};

const sendMessage = async () => {
if (!message.value.trim()) return;

isLoading.value = true;
const content = message.value;
message.value = '';

try {
const response = await $fetch(`/api/message`, {
method: 'POST',
body: JSON.stringify({
content,
roomId: route.params.id,
userId: user?.value?.id
}),
});

send(JSON.stringify(response));
} catch (err) {
console.error('Error sending message:', err);
toast.add({ title: 'Failed to send message', color: 'error' });
} finally {
isLoading.value = false;
}
}

const formatTime = (dateString: Date) => {
const date = new Date(dateString);
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
};

const isCurrentUser = (userId: number) => {
return user?.value?.id === userId;
};

onMounted(async () => {
open();
scrollToBottom();
})
</script>
<script lang="ts" setup>
import { get, set } from '@vueuse/core';
import { type Message } from '~~/server/repository/message/messageRepository';

definePageMeta({
middleware: ['chat']
})

const route = useRoute();
const toast = useToast();
const { user } = useUserSession();
const scrollRef = ref(null);

const { open, send } = useWebSocket(`/ws/chat/${route.params.id}`, {
immediate: false,

async onMessage(ws, event) {
try {
console.log('received message:', event.data);
const newMessage = JSON.parse(event.data) as Message;
messages.value.push(newMessage);
scrollToBottom();
} catch (error) {
console.error('Error parsing message:', error);
}
}
})

const { data, error, refresh } = useFetch<Message[]>(() => `/api/chat/${route.params.id}/messages`, {
default: () => []
});

const message = ref<string>('');
const messages = ref<Message[]>([]);
const isLoading = ref<boolean>(false);

watchEffect(() => {
if (data.value) {
messages.value = [...data.value];
nextTick(() => scrollToBottom());
}
});

const scrollToBottom = () => {
nextTick(() => {
if (scrollRef.value) {
const container = scrollRef.value;
container.scrollTop = container.scrollHeight;
}
});
};

const sendMessage = async () => {
if (!message.value.trim()) return;

isLoading.value = true;
const content = message.value;
message.value = '';

try {
const response = await $fetch(`/api/message`, {
method: 'POST',
body: JSON.stringify({
content,
roomId: route.params.id,
userId: user?.value?.id
}),
});

send(JSON.stringify(response));
} catch (err) {
console.error('Error sending message:', err);
toast.add({ title: 'Failed to send message', color: 'error' });
} finally {
isLoading.value = false;
}
}

const formatTime = (dateString: Date) => {
const date = new Date(dateString);
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
};

const isCurrentUser = (userId: number) => {
return user?.value?.id === userId;
};

onMounted(async () => {
open();
scrollToBottom();
})
</script>
For some reason, the code in the onMessage function doesn't run whenever a message is published. What am I doing wrong?
36 replies
NNuxt
Created by Viridian on 4/21/2025 in #❓・help
Layout transitions not working between pages
@kapa.ai When I log peer.context I get {}. Here's my chat.vue page:
<script lang="ts" setup>
const { open, send } = useWebSocket('/ws/chat/123', {
immediate: false,
async onMessage(ws, event) {
console.log(event.data);
}
})

onMounted(() => {
open();
})
</script>

<template>
<div>
Chat
</div>
<UButton @click="send('test')">Send some data</UButton>
</template>

<style scoped>

</style>
<script lang="ts" setup>
const { open, send } = useWebSocket('/ws/chat/123', {
immediate: false,
async onMessage(ws, event) {
console.log(event.data);
}
})

onMounted(() => {
open();
})
</script>

<template>
<div>
Chat
</div>
<UButton @click="send('test')">Send some data</UButton>
</template>

<style scoped>

</style>
What do I change to give the context to the peer?
36 replies
NNuxt
Created by Viridian on 4/21/2025 in #❓・help
Layout transitions not working between pages
@kapa.ai I have a WebSocket route routes/ws/chat/[id].ts. Is there a way to get the chat ID from the route parameters in the websocket handler? I cannot seem to access it through peer at all, and I want to make sure that clients can always connect to the right room ID, since my application will have multiple user-managed rooms (in a database too).
36 replies
NNuxt
Created by Viridian on 4/21/2025 in #❓・help
Layout transitions not working between pages
I fixed this by removing a comment in the top-level of my layout, as it counted as another node.
36 replies
NNuxt
Created by Viridian on 4/21/2025 in #❓・help
Layout transitions not working between pages
@kapa.ai I managed to get the transition to work more consistently by explicitly making a default.vue layout:
<script lang="ts" setup>

</script>

<template>
<div>
<p>default layout</p>
<slot />
</div>
</template>

<style scoped>

</style>
<script lang="ts" setup>

</script>

<template>
<div>
<p>default layout</p>
<slot />
</div>
</template>

<style scoped>

</style>
This makes the transition work from / --> /login - but trying to go back from login to / shows a blank page and nothing else. I already tried wrapping a div around NuxtLayout:
<template>
<NuxtRouteAnnouncer />
<NuxtLoadingIndicator />
<UApp>
<NuxtLayout>
<NuxtPage class="font-site relative" />
</NuxtLayout>
<Version class="fixed bottom-4 left-4" />
</UApp>
</template>

<style>
.slide-left-enter-active,
.slide-left-leave-active,
.slide-right-enter-active,
.slide-right-leave-active {
transition: all 0.4s;
}

.slide-left-enter-from,
.slide-left-leave-to {
transform: translateX(-100%);
}

.slide-right-enter-from,
.slide-right-leave-to {
transform: translateX(-150%);
opacity: 0;
}
</style>
<template>
<NuxtRouteAnnouncer />
<NuxtLoadingIndicator />
<UApp>
<NuxtLayout>
<NuxtPage class="font-site relative" />
</NuxtLayout>
<Version class="fixed bottom-4 left-4" />
</UApp>
</template>

<style>
.slide-left-enter-active,
.slide-left-leave-active,
.slide-right-enter-active,
.slide-right-leave-active {
transition: all 0.4s;
}

.slide-left-enter-from,
.slide-left-leave-to {
transform: translateX(-100%);
}

.slide-right-enter-from,
.slide-right-leave-to {
transform: translateX(-150%);
opacity: 0;
}
</style>
But that didn't work.
36 replies
NNuxt
Created by Viridian on 4/21/2025 in #❓・help
Layout transitions not working between pages
This didn't fix it. Any recommendations?
36 replies
NNuxt
Created by Viridian on 4/21/2025 in #❓・help
Layout transitions not working between pages
I moved all of the transitions to app.vue. Now the transition works from / to /login, but only once - after the first transition, going back from /login to / does nothing, and then / to login doesn't do anything anymore either. @kapa.ai
36 replies
NNuxt
Created by Viridian on 4/20/2025 in #❓・help
Tailwind classes not applying while using Nuxt UI v3
@kapa.ai I made an app.config.ts with this configuration:
export default defineAppConfig({
ui: {
colors: {
primary: 'rose',
neutral: 'zinc'
}
}
})

export default defineAppConfig({
ui: {
colors: {
primary: 'rose',
neutral: 'zinc'
}
}
})

But the theme colors aren't changing even after restarting the application. Why is this? I'm using @nuxt/ui
13 replies
NNuxt
Created by Viridian on 4/20/2025 in #❓・help
Tailwind classes not applying while using Nuxt UI v3
Solved because of some stupid scoped css issues 🤣
13 replies
NNuxt
Created by Viridian on 12/4/2024 in #❓・help
Strange error when trying to run dev mode on a fresh install
@kapa.ai how can I set a custom color (e.g. a tailwind class red-100) for my UProgress element? I can only use predefined ones like 'primary' for now
22 replies
NNuxt
Created by Viridian on 1/29/2025 in #❓・help
<USelect> in #trailing slot in <UInput> does not appear clickable
@kapa.ai How do I improve performance in my UItemInput? Can I use something like vue-virtual-scroller? Here's my code:
<UInputMenu
v-model="value"
:items="items"
placeholder="Search for resources..."
class="w-full"
size="xl"
icon="i-lucide-search"
>
<template #item-leading="{ item, index }">
<UIcon v-if="item.type === 'route'" class="text-green-500" name="i-lucide-map" />
<img v-if="item.type === 'pokemon'" :src="`https://raw.githubusercontent.com/May8th1995/sprites/master/${parseMonName(item.label)}.png`">
<UIcon v-if="item.type === 'trainer'" class="text-green-500" name="mdi-pokeball" />
</template>
</UInputMenu>
<UInputMenu
v-model="value"
:items="items"
placeholder="Search for resources..."
class="w-full"
size="xl"
icon="i-lucide-search"
>
<template #item-leading="{ item, index }">
<UIcon v-if="item.type === 'route'" class="text-green-500" name="i-lucide-map" />
<img v-if="item.type === 'pokemon'" :src="`https://raw.githubusercontent.com/May8th1995/sprites/master/${parseMonName(item.label)}.png`">
<UIcon v-if="item.type === 'trainer'" class="text-green-500" name="mdi-pokeball" />
</template>
</UInputMenu>
16 replies
NNuxt
Created by Viridian on 1/29/2025 in #❓・help
<USelect> in #trailing slot in <UInput> does not appear clickable
@kapa.ai Is there a way to make a search Input with autocomplete? What would I use?
16 replies
NNuxt
Created by Viridian on 11/13/2024 in #❓・help
USelect option values always turn into strings
@kapa.ai - Given this code:
const selectedPeriod = ref<'day' | 'month' | 'year'>('day');
const rateValue = ref<number | undefined>();

const periodOptions = [
{ label: 'per dag', value: 'day' },
{ label: 'per maand', value: 'month' },
{ label: 'per jaar', value: 'year' },
];

const dailyRate = computed(() => {
if (rateValue.value === undefined) return undefined;
switch (selectedPeriod.value) {
case 'day':
return rateValue.value;
case 'month':
return rateValue.value / 30; // Using 30 days as per existing constant
case 'year':
return rateValue.value / 365;
default:
return undefined;
}
});

<UFormGroup :label="labels.daily" size="lg" :ui="{ label: { base: 'font-semibold text-md' } }">
<UInput
type="number"
step="0.01"
placeholder="3.14"
input-class="no-spinner"
:model-value="rateValue"
@update:model-value="updateRateValue"
icon="i-material-symbols-electric-bolt"
>
<template #trailing>
<USelect
v-model="selectedPeriod"
:options="periodOptions"
size="xs"
:ui="{ base: 'w-28' }"
/>
</template>
</UInput>
</UFormGroup>
const selectedPeriod = ref<'day' | 'month' | 'year'>('day');
const rateValue = ref<number | undefined>();

const periodOptions = [
{ label: 'per dag', value: 'day' },
{ label: 'per maand', value: 'month' },
{ label: 'per jaar', value: 'year' },
];

const dailyRate = computed(() => {
if (rateValue.value === undefined) return undefined;
switch (selectedPeriod.value) {
case 'day':
return rateValue.value;
case 'month':
return rateValue.value / 30; // Using 30 days as per existing constant
case 'year':
return rateValue.value / 365;
default:
return undefined;
}
});

<UFormGroup :label="labels.daily" size="lg" :ui="{ label: { base: 'font-semibold text-md' } }">
<UInput
type="number"
step="0.01"
placeholder="3.14"
input-class="no-spinner"
:model-value="rateValue"
@update:model-value="updateRateValue"
icon="i-material-symbols-electric-bolt"
>
<template #trailing>
<USelect
v-model="selectedPeriod"
:options="periodOptions"
size="xs"
:ui="{ base: 'w-28' }"
/>
</template>
</UInput>
</UFormGroup>
For some reason, the select inside the input isn't able to be clicked to select another option.
66 replies
NNuxt
Created by Viridian on 11/13/2024 in #❓・help
USelect option values always turn into strings
@kapa.ai How can I set ~ as an alias?
66 replies
NNuxt
Created by Viridian on 11/13/2024 in #❓・help
USelect option values always turn into strings
@kapa.ai I have these settings for Nuxt:
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
// https://nuxt.com/modules

modules: [
'@nuxthub/core',
'@nuxt/eslint',
'@nuxt/ui',
],

// https://devtools.nuxt.com
devtools: { enabled: true },

css: ['~/assets/css/main.css'],

// Env variables - https://nuxt.com/docs/getting-started/configuration#environment-variables-and-private-tokens
runtimeConfig: {
public: {
// Can be overridden by NUXT_PUBLIC_HELLO_TEXT environment variable
helloText: 'Hello from the Edge 👋',
},
},
// https://nuxt.com/docs/getting-started/upgrade#testing-nuxt-4
future: { compatibilityVersion: 4 },
compatibilityDate: '2024-07-30',

nitro: {
experimental: {
tasks: true,
},
},

// https://hub.nuxt.com/docs/getting-started/installation#options
hub: {
database: true,
},

// https://eslint.nuxt.com
eslint: {
config: {
stylistic: {
quotes: 'single',
},
},
},
})
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
// https://nuxt.com/modules

modules: [
'@nuxthub/core',
'@nuxt/eslint',
'@nuxt/ui',
],

// https://devtools.nuxt.com
devtools: { enabled: true },

css: ['~/assets/css/main.css'],

// Env variables - https://nuxt.com/docs/getting-started/configuration#environment-variables-and-private-tokens
runtimeConfig: {
public: {
// Can be overridden by NUXT_PUBLIC_HELLO_TEXT environment variable
helloText: 'Hello from the Edge 👋',
},
},
// https://nuxt.com/docs/getting-started/upgrade#testing-nuxt-4
future: { compatibilityVersion: 4 },
compatibilityDate: '2024-07-30',

nitro: {
experimental: {
tasks: true,
},
},

// https://hub.nuxt.com/docs/getting-started/installation#options
hub: {
database: true,
},

// https://eslint.nuxt.com
eslint: {
config: {
stylistic: {
quotes: 'single',
},
},
},
})
For some reason, I get this error: 500 [vite-node] [ERR_LOAD_URL] ~/assets/css/main.css at ~/assets/css/main.css I have the assets folder in the root.
66 replies
NNuxt
Created by Viridian on 11/13/2024 in #❓・help
USelect option values always turn into strings
@kapa.ai Can I add multiple css files to the assets/css folder and use Tailwind classes in there to separate concerns?
66 replies
NNuxt
Created by Viridian on 11/13/2024 in #❓・help
USelect option values always turn into strings
@kapa.ai - How can I make a UButton only be as long as its content is?
66 replies
NNuxt
Created by Viridian on 11/13/2024 in #❓・help
USelect option values always turn into strings
@kapa.ai How can I disable the default number input behavior (adding a number incrementor/decrementor on the right side of the input) on UInput elements?
66 replies
NNuxt
Created by Viridian on 11/13/2024 in #❓・help
USelect option values always turn into strings
@kapa.ai How can I change the color of label text inside a UFormGroup:
<UFormGroup label="Ik betaal per kWh:">
<UInput>

</UInput>
</UFormGroup>
<UFormGroup label="Ik betaal per kWh:">
<UInput>

</UInput>
</UFormGroup>
66 replies
NNuxt
Created by Viridian on 11/13/2024 in #❓・help
USelect option values always turn into strings
@kapa.ai - On phone, focusing on NuxtUI elements makes the user unable to zoom out again. How can I prevent this behavior?
66 replies