managarten/apps-archived/bauntown/apps/landing/src/layouts/ToolLayout.astro
Till-JS 61d181fbc2 chore: archive inactive projects to apps-archived/
Move inactive projects out of active workspace:
- bauntown (community website)
- maerchenzauber (AI story generation)
- memoro (voice memo app)
- news (news aggregation)
- nutriphi (nutrition tracking)
- reader (reading app)
- uload (URL shortener)
- wisekeep (AI wisdom extraction)

Update CLAUDE.md documentation:
- Add presi to active projects
- Document archived projects section
- Update workspace configuration

Archived apps can be re-activated by moving back to apps/

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 07:03:59 +01:00

267 lines
5.1 KiB
Text

---
import Layout from './Layout.astro';
import { getLangFromUrl, useTranslations } from '../utils/i18n';
import type { CollectionEntry } from 'astro:content';
interface Props {
tool: CollectionEntry<'tools'>;
}
const { tool } = Astro.props;
const { data } = tool;
const lang = getLangFromUrl(Astro.url);
// Format date based on language
const formattedDate = new Intl.DateTimeFormat(
lang === 'de' ? 'de-DE' : lang === 'it' ? 'it-IT' : 'en-US',
{
year: 'numeric',
month: 'long',
day: 'numeric',
}
).format(data.pubDate);
// Category translation
const t = useTranslations(lang);
const categoryKey = `tools.categories.${data.category}` as const;
const pricingKey = `tools.pricing.${data.pricing}` as const;
---
<Layout title={data.title} description={data.description}>
<div class="tool-header">
{data.image && <img src={data.image} alt={data.title} class="featured-image" />}
<h1>{data.title}</h1>
<p class="description">{data.description}</p>
<div class="tool-quick-info">
<span class="category-badge">{t(categoryKey)}</span>
<span class="pricing-badge">{t(pricingKey)}</span>
{
data.website && (
<a href={data.website} target="_blank" rel="noopener noreferrer" class="website-link">
{t('tools.website')} <span class="external-icon">↗</span>
</a>
)
}
</div>
</div>
<article class="tool-content">
<slot />
{
data.tags && data.tags.length > 0 && (
<div class="tags">
{data.tags.map((tag) => (
<span class="tag">{tag}</span>
))}
</div>
)
}
{
data.externalLinks && data.externalLinks.length > 0 && (
<div class="external-links">
<h3>Related Links</h3>
<ul>
{data.externalLinks.map((link) => (
<li>
<a href={link.url} target="_blank" rel="noopener noreferrer">
{link.title}
</a>
</li>
))}
</ul>
</div>
)
}
<div class="tool-meta">
<span class="category">{t(categoryKey)}</span>
<span class="author">{data.author}</span>
<time datetime={data.pubDate.toISOString()}>{formattedDate}</time>
</div>
</article>
</Layout>
<style>
.tool-header {
margin-top: 80px; /* Mehr Abstand zur Navigation */
margin-bottom: 3rem;
max-width: 680px;
margin-left: auto;
margin-right: auto;
text-align: left;
padding-top: 1rem;
}
.tool-quick-info {
display: flex;
gap: 1rem;
flex-wrap: wrap;
margin-bottom: 1.5rem;
}
.category-badge,
.pricing-badge {
font-size: 0.875rem;
padding: 0.35rem 0.75rem;
border-radius: 0.25rem;
font-weight: 500;
}
.category-badge {
background-color: rgba(var(--accent-color-rgb, 249, 115, 22), 0.1);
color: var(--accent-color);
}
.pricing-badge {
background-color: var(--card-bg);
border: 1px solid var(--border-color);
color: var(--text-color);
}
.website-link {
display: inline-flex;
align-items: center;
font-size: 0.875rem;
padding: 0.35rem 0.75rem;
border-radius: 0.25rem;
text-decoration: none;
background-color: var(--button-bg);
color: var(--button-text);
transition: background-color 0.2s ease;
}
.website-link:hover {
background-color: var(--button-hover-bg);
}
.external-icon {
margin-left: 0.25rem;
font-size: 0.75rem;
}
.tool-meta {
display: flex;
gap: 1.5rem;
font-size: 0.875rem;
flex-wrap: nowrap;
justify-content: flex-end;
text-align: left;
margin-top: 4rem;
padding-top: 1.5rem;
border-top: 1px solid var(--border-color);
}
.category {
color: var(--text-muted);
font-weight: 600;
}
time {
color: var(--text-muted);
margin-left: auto;
}
h1 {
font-size: 2.5rem;
margin-top: 1.5rem;
margin-bottom: 1.5rem;
text-align: left;
line-height: 1.2;
}
.description {
font-size: 1.25rem;
color: var(--text-muted);
margin-bottom: 1.5rem;
line-height: 1.6;
text-align: left;
}
.author {
color: var(--text-muted);
}
.featured-image {
width: 100%;
max-height: 500px;
object-fit: cover;
border-radius: 0.75rem;
margin-bottom: 2rem;
}
.tags {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin: 2rem 0;
}
.tag {
font-size: 0.875rem;
padding: 0.35rem 0.75rem;
background-color: rgba(var(--accent-color-rgb, 249, 115, 22), 0.1);
color: var(--accent-color);
border-radius: 0.25rem;
}
.external-links {
margin: 2rem 0;
padding: 1.5rem;
background-color: var(--card-bg);
border-radius: 0.75rem;
border: 1px solid var(--border-color);
}
.external-links h3 {
margin-top: 0;
font-size: 1.25rem;
}
.external-links ul {
padding-left: 1.5rem;
margin-bottom: 0;
}
.external-links a {
color: var(--accent-color);
text-decoration: none;
}
.external-links a:hover {
text-decoration: underline;
}
@media (max-width: 768px) {
.tool-header {
margin-top: 50px; /* Weniger Abstand auf mobilen Geräten */
padding-top: 2rem;
}
h1 {
font-size: 2rem;
margin-top: 1rem;
}
.tool-meta {
flex-direction: column;
gap: 0.5rem;
align-items: flex-start;
}
time {
margin-left: 0;
}
}
.tool-content {
line-height: 1.8;
font-size: 1.125rem;
max-width: 680px;
margin-left: auto;
margin-right: auto;
text-align: left;
}
</style>