basicstack.org/pages/packages/index.vue
Paperclip CTO a7bd527793 Initial commit: Move basicstack.org frontend to Forgejo
Migrate the Nuxt 3 + Vue 3 SSR frontend application for basicstack.org to our self-hosted Forgejo instance. This repository will serve as the source for all future development and deployment of the basicstack.org website.

The application includes:
- Nuxt 3 + Vue 3 SSR setup
- Directus CMS integration
- Tailwind CSS styling
- Kubernetes deployment manifests
- Docker containerization

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-28 12:32:23 +00:00

167 lines
3.9 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="packages-page">
<div class="page-header">
<div class="container">
<h1>Software Packages</h1>
<p>Open source software we deploy and maintain on BasicStack infrastructure</p>
</div>
</div>
<div class="container page-body">
<div v-if="packages && packages.length > 0" class="packages-grid">
<NuxtLink
v-for="pkg in packages"
:key="pkg.id"
:to="`/packages/${pkg.slug}`"
class="package-card card"
>
<div class="package-header">
<img
v-if="pkg.logo"
:src="getAssetUrl(pkg.logo)"
:alt="pkg.name + ' logo'"
class="package-logo"
/>
<div v-else class="package-logo-placeholder">{{ pkg.name[0] }}</div>
<div class="package-info">
<h2 class="package-name">{{ pkg.name }}</h2>
<div class="package-meta">
<span v-if="pkg.screenshots && pkg.screenshots.length > 0" class="badge badge-primary">
{{ pkg.screenshots.length }} screenshot{{ pkg.screenshots.length !== 1 ? 's' : '' }}
</span>
<span v-if="pkg.deployment_details && pkg.deployment_details.length > 0" class="badge badge-primary">
Deploy docs
</span>
</div>
</div>
</div>
<p class="package-desc">{{ pkg.short_description }}</p>
<div class="package-links" v-if="pkg.website_url || pkg.documentation_url">
<span v-if="pkg.website_url" class="link-badge">Website</span>
<span v-if="pkg.documentation_url" class="link-badge">Docs</span>
</div>
</NuxtLink>
</div>
<div v-else class="empty">
<p>No packages found. Content will be added soon.</p>
</div>
</div>
</div>
</template>
<script setup lang="ts">
const { getPackages, getAssetUrl } = useDirectus()
const { data: packages } = await useAsyncData('packages', () => getPackages())
useSeoMeta({
title: 'Packages BasicStack',
description: 'Browse all open source software packages deployed on BasicStack infrastructure.',
})
</script>
<style scoped>
.page-header {
background: var(--color-bg-secondary);
border-bottom: 1px solid var(--color-border);
padding: var(--space-2xl) 0;
}
.page-header h1 {
margin-bottom: var(--space-sm);
}
.page-header p {
color: var(--color-text-muted);
margin: 0;
}
.page-body {
padding: var(--space-2xl) var(--space-lg);
}
.packages-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: var(--space-lg);
}
.package-card {
text-decoration: none;
color: inherit;
transition: box-shadow 0.2s, transform 0.2s;
display: flex;
flex-direction: column;
gap: var(--space-md);
}
.package-card:hover {
box-shadow: var(--shadow-lg);
transform: translateY(-2px);
text-decoration: none;
}
.package-header {
display: flex;
align-items: flex-start;
gap: var(--space-md);
}
.package-logo {
width: 56px;
height: 56px;
object-fit: contain;
flex-shrink: 0;
}
.package-logo-placeholder {
width: 56px;
height: 56px;
border-radius: var(--radius-md);
background: var(--color-primary);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.25rem;
font-weight: 700;
flex-shrink: 0;
}
.package-name {
font-size: 1.125rem;
margin: 0 0 var(--space-xs);
}
.package-meta {
display: flex;
flex-wrap: wrap;
gap: var(--space-xs);
}
.package-desc {
color: var(--color-text-muted);
font-size: 0.9375rem;
margin: 0;
flex: 1;
}
.package-links {
display: flex;
gap: var(--space-sm);
}
.link-badge {
font-size: 0.75rem;
color: var(--color-text-muted);
border: 1px solid var(--color-border);
padding: 0.125rem 0.5rem;
border-radius: var(--radius-sm);
}
.empty {
text-align: center;
padding: var(--space-3xl) 0;
color: var(--color-text-muted);
}
</style>