Compare commits

..
Author SHA1 Message Date
2995f517eb chore(deps): lock file maintenance
Some checks are pending
renovate/stability-days Updates have not met minimum release age requirement
ci / ci (22, debian-trixie) (push) Successful in 31s
2026-07-20 00:20:55 +00:00
c753f4d4f3 Merge pull request 'chore(deps): update devdependencies (non-major)' (#36) from renovate/devdependencies-(non-major) into master
All checks were successful
ci / ci (22, debian-trixie) (push) Successful in 26s
2026-07-20 02:05:48 +02:00
c5ce6d3155 chore(deps): update devdependencies (non-major)
All checks were successful
renovate/stability-days Updates have met minimum release age requirement
ci / ci (22, debian-trixie) (push) Successful in 26s
2026-07-20 00:05:30 +00:00
6f75475c39 Merge pull request 'chore(deps): update all non-major dependencies' (#35) from renovate/all-minor-patch into master
Some checks failed
ci / ci (22, debian-trixie) (push) Has been cancelled
2026-07-20 02:05:27 +02:00
71c84d9a0f chore(deps): update all non-major dependencies
All checks were successful
renovate/stability-days Updates have met minimum release age requirement
ci / ci (22, debian-trixie) (push) Successful in 32s
2026-07-20 00:05:10 +00:00
8db15d3d80
make ide happy
All checks were successful
ci / ci (22, debian-trixie) (push) Successful in 29s
2026-07-19 09:03:11 +02:00
62d60aadf1
chore: lint
Some checks failed
ci / ci (22, debian-trixie) (push) Failing after 30s
2026-07-19 08:54:39 +02:00
ad1c7b89f1
feat: / locales 2026-07-19 08:54:03 +02:00
354148357f
feat: locales in header & footer 2026-07-19 08:50:50 +02:00
94880e20a2
cleanup 2026-07-19 08:22:43 +02:00
15955d860c
chore: remove status page 2026-07-19 08:15:47 +02:00
12 changed files with 7557 additions and 8693 deletions

View file

@ -31,7 +31,7 @@ useSeoMeta({
<NuxtPage />
</UMain>
<USeparator icon="i-simple-icons-nuxtdotjs" />
<USeparator />
<MainFooter />
</UApp>

View file

@ -1,4 +1,8 @@
<script lang="ts" src="../composables/MainFooter.ts"></script>
<script setup lang="ts">
import footerLinks from '~/composables/MainFooter'
const { t } = useLocale()
</script>
<template>
<UFooter>
@ -16,12 +20,12 @@
</span>
</div>
<div class="text-sm text-gray-400 space-y-1">
<p>Copyright 2026</p>
<p>Site maintained by Spacebar Network</p>
<p>Developed by our contributors</p>
<p>Copyright {{ new Date().getFullYear() }}</p>
<p>{{ t.footer?.siteMaintained }}</p>
<p>{{ t.footer?.developedBy }}</p>
<p class="mt-4 max-w-[320px] leading-snug text-gray-500">
Spacebar Network (SPBR) is an extension of Splatfestival Network (SPFN), which aims to be a Nintendo Network recreation primarily for hosting Splatfests. Spacebar is separate from this purpose, though we remain partnered with Splatfestival.
{{ t.footer?.description }}
</p>
</div>
</div>
@ -31,7 +35,7 @@
<template #left>
<span class="text-sm text-gray-500">
© {{ new Date().getFullYear() }} Spacebar Network. All rights reserved.
© {{ new Date().getFullYear() }} {{ t.footer?.copyright }}
</span>
</template>

View file

@ -1,135 +0,0 @@
<template>
<div class="service-card">
<div class="card-header">
<div class="service-info">
<h3 class="service-name">
{{ name }}
</h3>
<span
class="info-tooltip"
title="Click for historical uptime metrics"
>?</span>
</div>
<div
class="current-status-dot"
:class="status.toLowerCase()"
/>
</div>
<div class="uptime-graph">
<div
v-for="(day, index) in uptimeHistory"
:key="index"
class="bar"
:class="day.status"
:title="formatTooltip(day)"
/>
</div>
<div class="card-footer">
<span class="time-ago">90 days ago</span>
<span class="uptime-percentage">{{ uptimePercentage }}% uptime</span>
<span class="time-today">Today</span>
</div>
<div class="status-label">
{{ status }}
</div>
</div>
</template>
<script lang="ts" src="../composables/ServiceCard.ts"></script>
<style scoped>
.service-card {
background-color: #161b22;
border: 1px solid #30363d;
border-radius: 6px;
padding: 20px;
color: #c9d1d9;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.service-info {
display: flex;
align-items: center;
gap: 6px;
}
.service-name {
font-size: 1.05rem;
font-weight: 600;
margin: 0;
color: #f0f6fc;
}
.info-tooltip {
font-size: 0.75rem;
color: #8b949e;
background-color: #21262d;
width: 14px;
height: 14px;
border-radius: 50%;
display: inline-flex;
justify-content: center;
align-items: center;
cursor: help;
}
.current-status-dot {
width: 14px;
height: 14px;
border-radius: 50%;
}
.current-status-dot.normal { background-color: #238636; }
.current-status-dot.degraded { background-color: #d29922; }
.current-status-dot.outage { background-color: #f85149; }
.uptime-graph {
display: flex;
gap: 2px;
height: 34px;
margin-bottom: 8px;
}
.bar {
flex: 1;
background-color: #238636;
border-radius: 1px;
transition: opacity 0.2s;
}
.bar:hover {
opacity: 0.7;
transform: scaleY(1.1);
}
.bar.normal { background-color: #238636; }
.bar.degraded { background-color: #d29922; }
.bar.outage { background-color: #f85149; }
.card-footer {
display: flex;
justify-content: space-between;
font-size: 0.75rem;
color: #8b949e;
border-bottom: 1px solid #21262d;
padding-bottom: 8px;
margin-bottom: 8px;
}
.uptime-percentage {
color: #8b949e;
}
.status-label {
font-size: 0.85rem;
color: #8b949e;
}
</style>

View file

@ -1,90 +0,0 @@
<template>
<header class="status-header">
<div class="status-banner operational">
<span class="status-icon"></span>
All Systems Operational
</div>
</header>
</template>
<style scoped>
.status-header {
background-color: #0d1117;
border-bottom: 1px solid #30363d;
padding-bottom: 24px;
}
.header-illustration {
height: 220px;
background: linear-gradient(180deg, #070a0e 0%, #0d1117 100%);
position: relative;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}
.factory-backdrop {
width: 100%;
max-width: 900px;
height: 100%;
position: relative;
opacity: 0.6;
}
.pipeline {
position: absolute;
top: 60%;
left: 5%;
right: 5%;
height: 8px;
background: #21262d;
border-radius: 4px;
}
.engineer {
position: absolute;
font-size: 2.5rem;
}
.dynamic-float-1 { top: 30%; left: 15%; animation: float 4s ease-in-out infinite; }
.dynamic-float-2 { top: 45%; left: 50%; animation: float 5s ease-in-out infinite 1s; }
.dynamic-float-3 { top: 25%; left: 80%; animation: float 6s ease-in-out infinite 0.5s; }
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
.status-banner {
max-width: 900px;
margin: -25px auto 0 auto;
position: relative;
z-index: 10;
padding: 16px 24px;
border-radius: 6px;
font-weight: 600;
font-size: 1.15rem;
display: flex;
align-items: center;
gap: 12px;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
}
.status-banner.operational {
background-color: #238636;
color: #ffffff;
border: 1px solid #2ea44f;
}
.status-icon {
background: rgba(255, 255, 255, 0.2);
width: 24px;
height: 24px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.9rem;
}
</style>

View file

@ -12,17 +12,17 @@
</RouterLink>
<nav class="links">
<a href="#">Supported games</a>
<a href="#">Error Codes</a>
<a href="#">Discord Server</a>
<a href="#">Install SPBR</a>
<a href="#">{{ t.nav?.supportedGames }}</a>
<a href="#">{{ t.nav?.errorCodes }}</a>
<a href="#">{{ t.nav?.discordServer }}</a>
<a href="#">{{ t.nav?.installSpbr }}</a>
</nav>
<div class="search-box">
<input
v-model="query"
type="text"
placeholder="Search"
:placeholder="t.nav?.searchPlaceholder"
>
<button class="search-btn">
<Icon
@ -40,6 +40,8 @@
import { ref } from 'vue'
const query = ref('')
const { t } = useLocale()
</script>
<style scoped>

View file

@ -0,0 +1,12 @@
import { ref } from 'vue'
import enMessages from '../locales/message-en.json'
const messages = ref(enMessages)
export const useLocale = () => {
// todo add changer
return {
t: messages
}
}

View file

@ -0,0 +1,49 @@
{
"nav": {
"supportedGames": "Supported games",
"errorCodes": "Error Codes",
"discordServer": "Discord Server",
"installSpbr": "Install SPBR",
"searchPlaceholder": "Search"
},
"footer": {
"siteMaintained": "Site maintained by Spacebar Network",
"developedBy": "Developed by our contributors",
"description": "Spacebar Network (SPBR) is an extension of Splatfestival Network (SPFN), which aims to be a Nintendo Network recreation primarily for hosting Splatfests. Spacebar is separate from this purpose, though we remain partnered with Splatfestival.",
"copyright": "Spacebar Network. All rights reserved."
},
"home": {
"spotlight": {
"titlePart1": "We do justice to the Wii ",
"titlePart2": "U",
"subtext": "Our service is designed to give the Wii U the treatment it deserves: pure royalty. We are dedicated to providing a stable, secure, and authentic online experience that recaptures the original magic of the Nintendo Network. By prioritizing reliability and nostalgia, we ensure that your favorite console remains a vibrant portal to the games and communities you love.",
"hintText": "Pssst.. our codebase is open source! Check out our Forgejo repository to see how we bring the Wii U back to life, and maybe even contribute yourself: "
},
"featuresSection": {
"title": "Everything you miss about the Wii U online experience",
"description": "Spacebar Network is built from the ground up, and we use everything in our power to make the experience fast.",
"items": {
"stable": {
"title": "Stable Experience",
"description": "Unlike other services, ours aims to be lightweight and efficient, allowing us to support more players than ever seen before."
},
"secure": {
"title": "Safe & Secure",
"description": "Active moderation and robust server architecture keep the community friendly, toxic-free, and safe for all."
},
"openSource": {
"title": "Open Source Spirit",
"description": "Built by fans, for fans. Our server frameworks are transparent, community-reviewed, and open for contributions from fellow developers."
}
}
},
"ctaSection": {
"title": "Dust off your GamePad",
"description": "The Wii U era doesn't have to end. Join Spacebar Network today and help build a thriving, nostalgic community of active players.",
"links": {
"guide": "Setup Guide",
"repo": "Forgejo Repository"
}
}
}
}

View file

@ -1,3 +1,7 @@
<script setup lang="ts">
const { t } = useLocale()
</script>
<template>
<div>
<section class="gamepad-spotlight-container">
@ -11,13 +15,14 @@
</div>
<div class="text-wrapper">
<h1 class="archivo-black title">
We do justice to the Wii <span class="text-wiiu-blue">U</span>.
{{ t.home?.spotlight?.titlePart1 }}<span class="text-wiiu-blue">{{ t.home?.spotlight?.titlePart2 }}</span>.
</h1>
<p class="subtext">
Our service is designed to give the Wii U the treatment it deserves: pure royalty. We are dedicated to providing a stable, secure, and authentic online experience that recaptures the original magic of the Nintendo Network. By prioritizing reliability and nostalgia, we ensure that your favorite console remains a vibrant portl to the games and communities you love.
{{ t.home?.spotlight?.subtext }}
</p>
<p class="hint-text">
Pssst.. our codebase is open source! Check out our Forgejo repository to see how we bring the Wii U back to life, and maybe even contribute yourself: <a
{{ t.home?.spotlight?.hintText }}
<a
href="https://git.spbr.net/spacebar"
target="_blank"
class="text-blue-400 underline"
@ -29,35 +34,35 @@
<UPageSection
id="features"
title="Everything you miss about the Wii U online experience"
description="Spacebar Network is built from the ground up, and we use everything in our power to make the experience fast."
:title="t.home?.featuresSection?.title"
:description="t.home?.featuresSection?.description"
:features="[{
icon: 'i-octicon-cpu-24',
title: 'Stable Experience',
description: 'Unlike other services, ours aims to be lightweight and efficient, allowing us to support more players than ever seen before.'
title: t.home?.featuresSection?.items?.stable?.title,
description: t.home?.featuresSection?.items?.stable?.description
}, {
icon: 'i-octicon-shield-check-24',
title: 'Safe & Secure',
description: 'Active moderation and robust server architecture keep the community friendly, toxic-free, and safe for all.'
title: t.home?.featuresSection?.items?.secure?.title,
description: t.home?.featuresSection?.items?.secure?.description
}, {
icon: 'i-octicon-code-24',
title: 'Open Source Spirit',
description: 'Built by fans, for fans. Our server frameworks are transparent, community-reviewed, and open for contributions from fellow developers.'
title: t.home?.featuresSection?.items?.openSource?.title,
description: t.home?.featuresSection?.items?.openSource?.description
}]"
/>
<UPageSection>
<UPageCTA
title="Dust off your GamePad"
description="The Wii U era doesn't have to end. Join Spacebar Network today and help build a thriving, nostalgic community of active players."
:title="t.home?.ctaSection?.title"
:description="t.home?.ctaSection?.description"
variant="subtle"
:links="[{
label: 'Setup Guide',
label: t.home?.ctaSection?.links?.guide,
to: '/docs/connect',
trailingIcon: 'i-octicon-arrow-right-24',
color: 'neutral'
}, {
label: 'Forgejo Repository',
label: t.home?.ctaSection?.links?.repo,
to: 'https://git.spbr.net/spacebar',
target: '_blank',
icon: 'i-simple-icons-gitea',

View file

@ -1,156 +0,0 @@
<template>
<div class="status-dashboard-container">
<div class="dashboard-meta">
<h2 class="title">
Current Status
</h2>
<div class="historical-link">
Uptime over the past 90 days. <a href="#">View historical uptime.</a>
</div>
</div>
<div class="status-banner operational">
<svg
class="octicon octicon-check"
viewBox="0 0 24 24"
width="24"
height="24"
aria-hidden="true"
fill="currentColor"
>
<path d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2Zm0 1.5a8.5 8.5 0 1 0 0 17 8.5 8.5 0 0 0 0-17Zm4.78 6.28-5.5 5.5a.75.75 0 0 1-1.06 0l-2.5-2.5a.751.751 0 0 1 .018-1.08.75.75 0 0 1 1.042.02L11 13.44l4.97-4.97a.75.75 0 0 1 1.06 1.06Z" />
</svg>
All Systems Operational
</div>
<div class="services-grid">
<ServiceCard
v-for="service in mockServices"
:key="service.id"
:name="service.name"
:status="service.status"
:uptime-percentage="service.uptimePercentage"
:uptime-history="service.history"
/>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import ServiceCard from '~/components/ServiceCard.vue'
definePageMeta({
layout: 'default'
})
const sharedHistory = (() => {
const history = []
const now = new Date()
for (let i = 89; i >= 0; i--) {
const dayDate = new Date(now.getTime() - i * 24 * 60 * 60 * 1000)
history.push({
date: dayDate.toISOString().split('T')[0],
status: 'normal',
incident: 'No incidents'
})
}
return history
})()
const serviceNames = [
'Website', 'Account', 'Connection Test', 'Super Mario Maker',
'Mario Tennis: Ultra Smash', 'Wii Sports Club', 'Splatoon Global Testfire',
'Splatoon', 'Friends', 'ぷよぷよテトリス', 'Wii U Chat',
'Sonic & All-Stars Racing Transformed', 'Minecraft: Wii U Edition', 'Fast Racing Neo'
]
// only here until i actually implement health checks, its 6:30am and i havent slept..
const mockServices = ref(
serviceNames.map((name, index) => ({
id: index + 1,
name,
status: 'Normal',
uptimePercentage: 100.00,
history: sharedHistory
}))
)
</script>
<style scoped>
@import url('https://fonts.googleapis.com/css2?family=Archivo+Black&display=swap');
.status-dashboard-container {
max-width: 900px;
margin: 40px auto;
padding: 0 20px;
}
.dashboard-meta {
display: flex;
justify-content: space-between;
align-items: flex-end;
margin-bottom: 24px;
}
.title {
font-family: 'Archivo Black', sans-serif;
font-weight: 400;
font-size: 1.5rem;
color: #f0f6fc;
margin: 0;
}
.historical-link {
font-size: 0.85rem;
color: #8b949e;
}
.historical-link a {
color: #f0883e;
text-decoration: none;
}
.historical-link a:hover {
text-decoration: underline;
}
.status-banner {
margin-bottom: 32px;
padding: 16px 24px;
border-radius: 6px;
font-weight: 600;
font-size: 1.15rem;
display: flex;
align-items: center;
gap: 12px;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
}
.status-banner.operational {
background-color: #238636;
color: #ffffff;
border: 1px solid #2ea44f;
}
.octicon-check {
flex-shrink: 0;
}
.services-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}
@media (max-width: 768px) {
.services-grid {
grid-template-columns: 1fr;
}
.dashboard-meta {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
}
</style>

995
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -17,21 +17,21 @@
]
},
"dependencies": {
"@iconify-json/lucide": "^1.2.115",
"@iconify-json/simple-icons": "^1.2.88",
"@nuxt/ui": "^4.9.0",
"@iconify-json/lucide": "^1.2.116",
"@iconify-json/simple-icons": "^1.2.89",
"@nuxt/ui": "^4.10.0",
"@primer/octicons": "^19.29.1",
"nuxt": "^4.5.0",
"tailwindcss": "^4.3.2"
},
"devDependencies": {
"@iconify-json/octicon": "^1.2.28",
"@iconify-json/octicon": "^1.2.29",
"@nuxt/eslint": "^1.16.0",
"@nuxt/icon": "^2.2.5",
"@nuxt/icon": "^2.3.1",
"eslint": "^10.6.0",
"husky": "^9.1.7",
"lint-staged": "^17.0.8",
"typescript": "^6.0.3",
"vue-tsc": "^3.3.5"
"vue-tsc": "^3.3.6"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 180 KiB

Before After
Before After