Favicon and tags/categories pages fix

This commit is contained in:
HangerThem 2026-08-04 09:51:06 +02:00
parent 1078ed016f
commit 25a9cbda8f
21 changed files with 120 additions and 34 deletions

View file

@ -1,5 +1,6 @@
import { metadata } from '@/app/metadata' import { metadata } from '@/app/metadata'
import { getAllCategories, getCategoryBySlug, getPostsByCategory } from '@/lib/categories' import { getAllCategories, getCategoryBySlug, getPostsByCategory } from '@/lib/categories'
import { dateFormatter } from '@/utils/time'
import type { Metadata } from 'next' import type { Metadata } from 'next'
import Link from 'next/link' import Link from 'next/link'
@ -49,14 +50,35 @@ export default async function CategoryPage({ params }: CategoryPageProps) {
return ( return (
<main className="max-w-3xl 2xl:max-w-4xl mx-auto px-4 py-8 mb-8 lg:py-16 w-full"> <main className="max-w-3xl 2xl:max-w-4xl mx-auto px-4 py-8 mb-8 lg:py-16 w-full">
<h1>Category: {category}</h1> <div className="font-mono text-sm text-fg-dim mb-2">~/categories/{categorySlug}</div>
<ul>
{posts.map((post) => ( <div className="border-l border-border ml-1 mb-3">
<li key={post.slug}> <span className="py-2 px-5 block font-bold group-hover:text-accent transition-colors capitalize">
<Link href={`/posts/${post.slug}`}>{post.title}</Link> {category}
</li> </span>
))} <ul className="border-l border-border ml-8 mb-3">
</ul> {posts.map((post) => (
<li key={post.slug} className="pl-5">
<Link
href={`/posts/${post.slug}`}
className="group flex items-baseline justify-between gap-3 py-1.5 px-2 -ml-2 border-l-2 border-transparent hover:bg-accent/10 hover:border-accent transition-colors"
>
<span className="group-hover:text-accent transition-colors truncate">
{post.title}
</span>
{post.date && (
<time
dateTime={new Date(post.date).toISOString()}
className="text-sm whitespace-nowrap"
>
{dateFormatter.format(new Date(post.date))}
</time>
)}
</Link>
</li>
))}
</ul>
</div>
</main> </main>
) )
} }

View file

@ -34,9 +34,9 @@ export default function CategoriesPage() {
return ( return (
<main className="max-w-3xl 2xl:max-w-4xl mx-auto px-4 py-8 mb-8 lg:py-16 w-full"> <main className="max-w-3xl 2xl:max-w-4xl mx-auto px-4 py-8 mb-8 lg:py-16 w-full">
<div className="text-sm text-fg-dim mb-2">~/categories</div> <div className="font-mono text-sm text-fg-dim mb-2">~/categories</div>
<ul className="border-l border-neutral-800 ml-1"> <ul className="border-l border-border ml-1">
{categoryNames.map((category) => { {categoryNames.map((category) => {
const categoryPosts = posts.filter((post) => post.category === category) const categoryPosts = posts.filter((post) => post.category === category)
@ -49,10 +49,10 @@ export default function CategoriesPage() {
<span className="font-bold group-hover:text-accent transition-colors"> <span className="font-bold group-hover:text-accent transition-colors">
{category} {category}
</span> </span>
<span className="font-mono text-xs text-neutral-600">({categoryPosts.length})</span> <span className="text-xs text-fg">({categoryPosts.length})</span>
</Link> </Link>
<ul className="border-l border-neutral-800 ml-3 mb-3"> <ul className="border-l border-border ml-3 mb-3">
{categoryPosts.map((post) => ( {categoryPosts.map((post) => (
<li key={post.slug} className="pl-5"> <li key={post.slug} className="pl-5">
<Link <Link

View file

@ -1,5 +1,6 @@
import { metadata } from '@/app/metadata' import { metadata } from '@/app/metadata'
import { getAllTags, getPostsByTag, getTagBySlug } from '@/lib/tags' import { getAllTags, getPostsByTag, getTagBySlug } from '@/lib/tags'
import { dateFormatter } from '@/utils/time'
import type { Metadata } from 'next' import type { Metadata } from 'next'
import Link from 'next/link' import Link from 'next/link'
@ -49,14 +50,35 @@ export default async function TagPage({ params }: TagPageProps) {
return ( return (
<main className="max-w-3xl 2xl:max-w-4xl mx-auto px-4 py-8 mb-8 lg:py-16 w-full"> <main className="max-w-3xl 2xl:max-w-4xl mx-auto px-4 py-8 mb-8 lg:py-16 w-full">
<h1>Tag: {tag}</h1> <div className="font-mono text-sm text-fg-dim mb-2">~/tags/{tagSlug}</div>
<ul>
{posts.map((post) => ( <div className="border-l border-border ml-1 mb-3">
<li key={post.slug}> <span className="py-2 px-5 block font-bold group-hover:text-accent transition-colors capitalize">
<Link href={`/posts/${post.slug}`}>{post.title}</Link> {tag}
</li> </span>
))} <ul className="border-l border-border ml-8 mb-3">
</ul> {posts.map((post) => (
<li key={post.slug} className="pl-5">
<Link
href={`/posts/${post.slug}`}
className="group flex items-baseline justify-between gap-3 py-1.5 px-2 -ml-2 border-l-2 border-transparent hover:bg-accent/10 hover:border-accent transition-colors"
>
<span className="group-hover:text-accent transition-colors truncate">
{post.title}
</span>
{post.date && (
<time
dateTime={new Date(post.date).toISOString()}
className="text-sm whitespace-nowrap"
>
{dateFormatter.format(new Date(post.date))}
</time>
)}
</Link>
</li>
))}
</ul>
</div>
</main> </main>
) )
} }

View file

@ -34,9 +34,9 @@ export default function TagsPage() {
return ( return (
<main className="max-w-3xl 2xl:max-w-4xl mx-auto px-4 py-8 mb-8 lg:py-16 w-full"> <main className="max-w-3xl 2xl:max-w-4xl mx-auto px-4 py-8 mb-8 lg:py-16 w-full">
<div className="text-sm text-fg-dim mb-2">~/tags</div> <div className="font-mono text-sm text-fg-dim mb-2">~/tags</div>
<ul className="border-l border-neutral-800 ml-1"> <ul className="border-l border-border ml-1">
{tagNames.map((tag) => { {tagNames.map((tag) => {
const tagPosts = posts.filter((post) => post.tags && post.tags.includes(tag)) const tagPosts = posts.filter((post) => post.tags && post.tags.includes(tag))
@ -49,10 +49,10 @@ export default function TagsPage() {
<span className="font-bold group-hover:text-accent transition-colors capitalize"> <span className="font-bold group-hover:text-accent transition-colors capitalize">
{tag} {tag}
</span> </span>
<span className="font-mono text-xs text-neutral-600">({tagPosts.length})</span> <span className="text-xs text-fg">({tagPosts.length})</span>
</Link> </Link>
<ul className="border-l border-neutral-800 ml-3 mb-3"> <ul className="border-l border-border ml-3 mb-3">
{tagPosts.map((post) => ( {tagPosts.map((post) => (
<li key={post.slug} className="pl-5"> <li key={post.slug} className="pl-5">
<Link <Link

BIN
app/apple-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 15 KiB

1
app/icon0.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

BIN
app/icon1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 857 B

25
app/manifest.ts Normal file
View file

@ -0,0 +1,25 @@
import type { MetadataRoute } from 'next'
export default function manifest(): MetadataRoute.Manifest {
return {
name: 'Ephemeris',
short_name: 'Ephemeris',
icons: [
{
src: '/web-app-manifest-192x192.png',
sizes: '192x192',
type: 'image/png',
purpose: 'maskable',
},
{
src: '/web-app-manifest-512x512.png',
sizes: '512x512',
type: 'image/png',
purpose: 'maskable',
},
],
theme_color: '#ef1f1f',
background_color: '#ef1f1f',
display: 'standalone',
}
}

View file

@ -12,4 +12,9 @@ export const metadata: Metadata = {
url: process.env.SITE_URL, url: process.env.SITE_URL,
siteName: 'Ephemeris', siteName: 'Ephemeris',
}, },
appleWebApp: {
title: 'Ephemeris',
statusBarStyle: 'default',
capable: true,
},
} }

View file

@ -106,9 +106,13 @@ export default async function Post({ params }: { params: Promise<{ slug: string
<h2 className="text-lg font-bold">Tags</h2> <h2 className="text-lg font-bold">Tags</h2>
<div className="flex flex-wrap gap-1"> <div className="flex flex-wrap gap-1">
{meta.tags.map((tag) => ( {meta.tags.map((tag) => (
<span key={tag} className="bg-accent/20 text-accent px-3 py-1 rounded-full text-xs"> <Link
key={tag}
href={`/tags/${slugify(tag)}`}
className="bg-accent/20 text-accent px-3 py-1 rounded-full text-xs hover:bg-accent/30 transition-colors"
>
{tag} {tag}
</span> </Link>
))} ))}
</div> </div>
</div> </div>

View file

@ -23,7 +23,7 @@ export function ImageWrapper({ src, alt, isListing }: ImageWrapperProps) {
<span className="text-xs text-fg-dim font-mono">~/{src}</span> <span className="text-xs text-fg-dim font-mono">~/{src}</span>
</div> </div>
<Image <Image
src={`/${src}`} src={`/posts/${src}`}
alt={alt ?? ''} alt={alt ?? ''}
width={isListing ? 400 : 800} width={isListing ? 400 : 800}
height={isListing ? 240 : 400} height={isListing ? 240 : 400}

View file

@ -1,9 +1,9 @@
import { metadata } from '@/app/metadata' import { metadata } from '@/app/metadata'
import { NotepadText } from 'lucide-react'
import { NavLinks } from '@/components/layout/NavLinks' import { NavLinks } from '@/components/layout/NavLinks'
import { siBluesky, siGithub, siMatrix, siTelegram, type SimpleIcon } from 'simple-icons' import { siBluesky, siGithub, siMatrix, siTelegram, type SimpleIcon } from 'simple-icons'
import { ExternalLink } from '@/components/ui/ExternalLink' import { ExternalLink } from '@/components/ui/ExternalLink'
import { getGitCommitHash } from '@/utils/git' import { getGitCommitHash } from '@/utils/git'
import Image from 'next/image'
type SocialLink = { type SocialLink = {
icon: SimpleIcon icon: SimpleIcon
@ -38,7 +38,7 @@ export async function Sidebar() {
<div className="sticky top-0 flex flex-col h-screen gap-4 py-4"> <div className="sticky top-0 flex flex-col h-screen gap-4 py-4">
<div> <div>
<h2 className="text-2xl font-bold mb-4 flex items-center gap-2"> <h2 className="text-2xl font-bold mb-4 flex items-center gap-2">
<NotepadText className="w-6 h-6" /> <Image src="/logo.png" alt="Ephemeris Logo" width={32} height={32} />
<span>{metadata.title!.toString()}</span> <span>{metadata.title!.toString()}</span>
</h2> </h2>
<ul className="space-y-2"> <ul className="space-y-2">

View file

@ -1,4 +1,4 @@
import { Folder, GitBranch, Home, Info, Rss, Tags } from 'lucide-react' import { ChartColumnStacked, GitBranch, Home, Info, Rss, Tags } from 'lucide-react'
type NavItem = { type NavItem = {
href: string href: string
@ -12,7 +12,11 @@ const navIconsClassName = 'w-6 h-6 lg:w-4 lg:h-4'
export const navItems: NavItem[] = [ export const navItems: NavItem[] = [
{ href: '/', label: 'Home', icon: <Home className={navIconsClassName} /> }, { href: '/', label: 'Home', icon: <Home className={navIconsClassName} /> },
{ href: '/about', label: 'About', icon: <Info className={navIconsClassName} /> }, { href: '/about', label: 'About', icon: <Info className={navIconsClassName} /> },
{ href: '/categories', label: 'Categories', icon: <Folder className={navIconsClassName} /> }, {
href: '/categories',
label: 'Categories',
icon: <ChartColumnStacked className={navIconsClassName} />,
},
{ href: '/tags', label: 'Tags', icon: <Tags className={navIconsClassName} /> }, { href: '/tags', label: 'Tags', icon: <Tags className={navIconsClassName} /> },
{ {
href: '/feed.xml', href: '/feed.xml',

View file

@ -48,7 +48,7 @@ export function Post({ post, isLatest, showImageSlot }: PostProps) {
{title} {title}
</Link> </Link>
</h2> </h2>
<p className="text-fg-dim font-mono text-sm">{description}</p> <p className="text-fg-dim text-sm">{description}</p>
<div className="flex gap-2 items-center text-fg-dim text-xs font-mono mt-1"> <div className="flex gap-2 items-center text-fg-dim text-xs font-mono mt-1">
<time dateTime={publishedAt.toISOString()}>{dateFormatter.format(publishedAt)}</time> <time dateTime={publishedAt.toISOString()}>{dateFormatter.format(publishedAt)}</time>
<span>&middot;</span> <span>&middot;</span>

View file

@ -39,8 +39,11 @@ export function TableOfContents({ items }: { items: TocItem[] }) {
return ( return (
<aside className="hidden lg:block w-80 2xl:w-100"> <aside className="hidden lg:block w-80 2xl:w-100">
<nav aria-label="Table of contents" className="sticky top-20"> <nav
<h2 className="text-2xl font-bold mb-4">Table of Contents</h2> aria-label="Table of contents"
className="sticky top-12 border-l border-border h-fit pl-4 py-4"
>
<h2 className="text-xl font-bold mb-4">Table of Contents</h2>
<ul className="space-y-1 text-sm"> <ul className="space-y-1 text-sm">
{items.map((item) => ( {items.map((item) => (
<li key={item.id} className={indentByLevel[item.level] ?? 'pl-0'}> <li key={item.id} className={indentByLevel[item.level] ?? 'pl-0'}>

BIN
public/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View file

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB