mirror of
https://github.com/KazooTTT/kazoottt-blog.git
synced 2025-06-24 11:11:30 +08:00
Built resume template
This commit is contained in:
33
src/pages/404.astro
Normal file
33
src/pages/404.astro
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
import PageLayout from '@/layouts/BaseLayout.astro'
|
||||
import Button from '@/components/Button.astro'
|
||||
|
||||
const meta = {
|
||||
description: 'Not found',
|
||||
title: '404'
|
||||
}
|
||||
---
|
||||
|
||||
<PageLayout meta={meta}>
|
||||
<div class='px-4 py-10 text-center sm:px-6 lg:px-8'>
|
||||
<h1 class='block text-7xl font-bold sm:text-9xl'>404</h1>
|
||||
<p class='mt-3 text-muted-foreground'>Oops, something went wrong.</p>
|
||||
<p class=''>Sorry, we couldn't find your page.</p>
|
||||
<Button title='Back to home' href='/' style='button' class='mt-5'>
|
||||
<svg
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
width='14'
|
||||
height='14'
|
||||
viewBox='0 0 24 24'
|
||||
slot='icon-after'
|
||||
class='-scale-x-100'
|
||||
>
|
||||
<path
|
||||
fill='currentColor'
|
||||
d='m6.921 12.5l5.792 5.792L12 19l-7-7l7-7l.713.708L6.921 11.5H19v1z'
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
</Button>
|
||||
</div>
|
||||
</PageLayout>
|
113
src/pages/blog/[...page].astro
Normal file
113
src/pages/blog/[...page].astro
Normal file
@ -0,0 +1,113 @@
|
||||
---
|
||||
export const prerender = true
|
||||
|
||||
import type { GetStaticPaths, Page } from 'astro'
|
||||
import type { CollectionEntry } from 'astro:content'
|
||||
|
||||
import Button from '@/components/Button.astro'
|
||||
import Pagination from '@/components/Paginator.astro'
|
||||
import PostPreview from '@/components/blog/PostPreview.astro'
|
||||
import PageLayout from '@/layouts/BaseLayout.astro'
|
||||
import { getAllPosts, getUniqueTags, sortMDByDate } from '@/utils'
|
||||
|
||||
export const getStaticPaths = (async ({ paginate }) => {
|
||||
const allPosts = await getAllPosts()
|
||||
const allPostsByDate = sortMDByDate(allPosts)
|
||||
const uniqueTags = getUniqueTags(allPosts)
|
||||
return paginate(allPostsByDate, { pageSize: 10, props: { uniqueTags } })
|
||||
}) satisfies GetStaticPaths
|
||||
|
||||
interface Props {
|
||||
page: Page<CollectionEntry<'post'>>
|
||||
uniqueTags: string[]
|
||||
}
|
||||
|
||||
const { page, uniqueTags } = Astro.props
|
||||
|
||||
const meta = {
|
||||
description: 'Posts',
|
||||
title: 'Blog'
|
||||
}
|
||||
|
||||
const paginationProps = {
|
||||
...(page.url.prev && {
|
||||
prevUrl: {
|
||||
text: `← Previous Posts`,
|
||||
url: page.url.prev
|
||||
}
|
||||
}),
|
||||
...(page.url.next && {
|
||||
nextUrl: {
|
||||
text: `Next Posts →`,
|
||||
url: page.url.next
|
||||
}
|
||||
})
|
||||
}
|
||||
---
|
||||
|
||||
<PageLayout meta={meta}>
|
||||
<div class='w-full'>
|
||||
<Button title='Back' href='/' style='button'>
|
||||
<svg
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
width='14'
|
||||
height='14'
|
||||
viewBox='0 0 24 24'
|
||||
slot='icon-before'
|
||||
>
|
||||
<path
|
||||
fill='currentColor'
|
||||
d='m6.921 12.5l5.792 5.792L12 19l-7-7l7-7l.713.708L6.921 11.5H19v1z'
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
</Button>
|
||||
|
||||
<h1 class='mb-6 mt-5 text-2xl font-bold'>Blog</h1>
|
||||
<div class='grid gap-y-16 sm:grid-cols-[3fr_1fr] sm:gap-x-8'>
|
||||
<section aria-label='Blog posts list'>
|
||||
<ul class='flex flex-col gap-y-4 text-start'>
|
||||
{page.data.map((p) => <PostPreview post={p} withDesc />)}
|
||||
</ul>
|
||||
<Pagination {...paginationProps} />
|
||||
</section>
|
||||
{
|
||||
!!uniqueTags.length && (
|
||||
<aside>
|
||||
<h2 class='mb-4 flex items-center text-lg font-semibold'>
|
||||
<svg
|
||||
aria-hidden='true'
|
||||
class='h-6 w-6'
|
||||
fill='none'
|
||||
stroke='currentColor'
|
||||
stroke-linecap='round'
|
||||
stroke-linejoin='round'
|
||||
stroke-width='1.5'
|
||||
viewBox='0 0 24 24'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
>
|
||||
<path d='M0 0h24v24H0z' fill='none' stroke='none' />
|
||||
<path d='M7.859 6h-2.834a2.025 2.025 0 0 0 -2.025 2.025v2.834c0 .537 .213 1.052 .593 1.432l6.116 6.116a2.025 2.025 0 0 0 2.864 0l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-6.117 -6.116a2.025 2.025 0 0 0 -1.431 -.593z' />
|
||||
<path d='M17.573 18.407l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-7.117 -7.116' />
|
||||
<path d='M6 9h-.01' />
|
||||
</svg>
|
||||
Tags
|
||||
</h2>
|
||||
<ul class='text-bgColor flex flex-wrap gap-2'>
|
||||
{uniqueTags.map((tag) => (
|
||||
<li>
|
||||
<Button title={tag} href={`/tags/${tag}/`} style='pill' />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<span class='mt-4 block sm:text-end'>
|
||||
<a aria-label='View all blog categories' class='' href='/tags/' data-astro-prefetch>
|
||||
View all →
|
||||
</a>
|
||||
</span>
|
||||
</aside>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</PageLayout>
|
25
src/pages/blog/[slug].astro
Normal file
25
src/pages/blog/[slug].astro
Normal file
@ -0,0 +1,25 @@
|
||||
---
|
||||
export const prerender = true
|
||||
|
||||
import type { GetStaticPaths, InferGetStaticPropsType } from 'astro'
|
||||
|
||||
import PostLayout from '@/layouts/BlogPost.astro'
|
||||
import { getAllPosts } from '@/utils'
|
||||
|
||||
export const getStaticPaths = (async () => {
|
||||
const blogEntries = await getAllPosts()
|
||||
return blogEntries.map((entry) => ({
|
||||
params: { slug: entry.slug },
|
||||
props: { entry }
|
||||
}))
|
||||
}) satisfies GetStaticPaths
|
||||
|
||||
type Props = InferGetStaticPropsType<typeof getStaticPaths>
|
||||
|
||||
const { entry } = Astro.props
|
||||
const { Content } = await entry.render()
|
||||
---
|
||||
|
||||
<PostLayout post={entry}>
|
||||
<Content />
|
||||
</PostLayout>
|
215
src/pages/index.astro
Normal file
215
src/pages/index.astro
Normal file
@ -0,0 +1,215 @@
|
||||
---
|
||||
import PageLayout from '../layouts/BaseLayout.astro'
|
||||
import Section from '../components/Section.astro'
|
||||
import Card from '../components/Card.astro'
|
||||
import ProjectCard from '../components/ProjectCard.astro'
|
||||
import Label from '../components/Label.astro'
|
||||
import SkillLayout from '../components/SkillLayout.astro'
|
||||
import PostPreview from '@/components/blog/PostPreview.astro'
|
||||
|
||||
import { Image } from 'astro:assets'
|
||||
import astro from '../assets/about-astro.png'
|
||||
|
||||
import { getAllPosts, sortMDByDate } from '@/utils'
|
||||
|
||||
const languages = ['lorem', 'ipsum']
|
||||
const frontend = ['lorem', 'ipsum', 'lorem', 'ipsum', 'lorem', 'ipsum', 'lorem']
|
||||
const backend = ['lorem', 'ipsum', 'lorem', 'ipsum']
|
||||
const others = ['lorem', 'ipsum', 'lorem', 'ipsum', 'lorem']
|
||||
|
||||
const MAX_POSTS = 10
|
||||
const allPosts = await getAllPosts()
|
||||
const allPostsByDate = sortMDByDate(allPosts).slice(0, MAX_POSTS)
|
||||
---
|
||||
|
||||
<PageLayout meta={{ title: 'Home' }}>
|
||||
<div class='flex w-full flex-col gap-y-10'>
|
||||
<section class='flex flex-col items-center gap-y-7'>
|
||||
<Image
|
||||
src={astro}
|
||||
alt='profile photo'
|
||||
class='h-28 w-auto rounded-full p-2 bg-[#FFBE98]'
|
||||
loading='eager'
|
||||
/>
|
||||
|
||||
<div class='flex flex-col items-center gap-y-4'>
|
||||
<h1 class='text-3xl font-bold'>Lorem ipsum dolor</h1>
|
||||
<div
|
||||
class='flex flex-row items-center gap-x-3 rounded-3xl border border-input px-4 py-2 text-sm shadow-sm'
|
||||
>
|
||||
<span class='relative flex items-center justify-center'>
|
||||
<span
|
||||
class='absolute inline-flex h-2 w-2 animate-ping rounded-full border border-green-400 bg-green-400 opacity-75'
|
||||
></span>
|
||||
<span class='relative inline-flex h-2 w-2 rounded-full bg-green-400'></span>
|
||||
</span>
|
||||
|
||||
<p class=''>Available for work</p>
|
||||
</div>
|
||||
<div class='flex gap-x-7'>
|
||||
<Label title='Lorem Ipsum'>
|
||||
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' class='h-5 w-5' slot='icon'
|
||||
><path
|
||||
fill='currentColor'
|
||||
d='M4.615 20q-.69 0-1.152-.462Q3 19.075 3 18.385v-9.77q0-.69.463-1.152Q3.925 7 4.615 7H9V5.615q0-.69.463-1.152Q9.925 4 10.615 4h2.77q.69 0 1.153.463q.462.462.462 1.152V7h4.385q.69 0 1.152.463q.463.462.463 1.152v9.77q0 .69-.462 1.152q-.463.463-1.153.463zm0-1h14.77q.23 0 .423-.192q.192-.193.192-.423v-9.77q0-.23-.192-.423Q19.615 8 19.385 8H4.615q-.23 0-.423.192Q4 8.385 4 8.615v9.77q0 .23.192.423q.193.192.423.192M10 7h4V5.615q0-.23-.192-.423Q13.615 5 13.385 5h-2.77q-.23 0-.423.192q-.192.193-.192.423zM4 19V8z'
|
||||
></path></svg
|
||||
>
|
||||
</Label>
|
||||
<Label title='Ipsum'>
|
||||
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' class='h-5 w-5' slot='icon'
|
||||
><path
|
||||
fill='currentColor'
|
||||
d='M12.003 11.73q.668 0 1.14-.475q.472-.475.472-1.143t-.475-1.14q-.476-.472-1.143-.472t-1.14.476q-.472.475-.472 1.143t.475 1.14q.476.472 1.143.472M12 19.677q2.82-2.454 4.458-4.991q1.638-2.538 1.638-4.39q0-2.744-1.737-4.53T12 3.981q-2.621 0-4.359 1.785t-1.737 4.53q0 1.852 1.638 4.39q1.639 2.537 4.458 4.99m0 1.343q-3.525-3.117-5.31-5.814q-1.786-2.697-1.786-4.909q0-3.173 2.066-5.234Q9.037 3 12 3t5.03 2.062q2.066 2.061 2.066 5.234q0 2.212-1.785 4.909q-1.786 2.697-5.311 5.814m0-10.904'
|
||||
></path></svg
|
||||
>
|
||||
</Label>
|
||||
<Label
|
||||
title='Connect on Linkedin'
|
||||
as='a'
|
||||
href='https://www.linkedin.com/in/example/'
|
||||
target='_blank'
|
||||
>
|
||||
<svg
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
viewBox='0 0 16 16'
|
||||
slot='icon'
|
||||
class='h-5 w-5 text-foreground/75'
|
||||
><path
|
||||
fill='currentColor'
|
||||
d='M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854zm4.943 12.248V6.169H2.542v7.225zm-1.2-8.212c.837 0 1.358-.554 1.358-1.248c-.015-.709-.52-1.248-1.342-1.248S2.4 3.226 2.4 3.934c0 .694.521 1.248 1.327 1.248zm4.908 8.212V9.359c0-.216.016-.432.08-.586c.173-.431.568-.878 1.232-.878c.869 0 1.216.662 1.216 1.634v3.865h2.401V9.25c0-2.22-1.184-3.252-2.764-3.252c-1.274 0-1.845.7-2.165 1.193v.025h-.016l.016-.025V6.169h-2.4c.03.678 0 7.225 0 7.225z'
|
||||
></path></svg
|
||||
>
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Section title='About'>
|
||||
<p class='text-muted-foreground'>
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Reiciendis atque quia omnis
|
||||
consectetur, voluptas praesentium veniam blanditiis ratione asperiores accusantium laborum
|
||||
odit commodi quis deserunt incidunt et dolor iure ut! Lorem ipsum dolor sit, amet
|
||||
consectetur adipisicing elit. Alias quia, doloribus ut beatae perspiciatis voluptatibus.
|
||||
</p>
|
||||
</Section>
|
||||
|
||||
<Section title='Posts'>
|
||||
<ul class='flex flex-col gap-y-2'>
|
||||
{
|
||||
allPostsByDate.map((p) => (
|
||||
<li class='flex flex-col gap-x-2 sm:flex-row'>
|
||||
<PostPreview post={p} />
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
</Section>
|
||||
|
||||
<Section title='Experience'>
|
||||
<Card
|
||||
heading='Lorem Ipsum'
|
||||
subheading='Sit amet consectetur'
|
||||
date='Dec 2022 - Nov 2023'
|
||||
imagePath='/src/assets/about-astro.png'
|
||||
altText='Lorem, ipsum dolor sit'
|
||||
imageClass='h-12 w-auto md:-left-16'
|
||||
>
|
||||
<ul class='ml-4 list-disc text-muted-foreground'>
|
||||
<li>
|
||||
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolore debitis recusandae, ut
|
||||
molestiae laboriosam pariatur!
|
||||
|
||||
<li>Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestiae, pariatur!</li>
|
||||
</li>
|
||||
</ul>
|
||||
</Card>
|
||||
<Card
|
||||
heading='Lorem Ipsum'
|
||||
subheading='Sit amet consectetur'
|
||||
date='Dec 2022 - Nov 2023'
|
||||
imagePath='/src/assets/about-astro.png'
|
||||
altText='Lorem, ipsum dolor sit'
|
||||
imageClass='h-12 w-auto md:-left-16'
|
||||
/>
|
||||
</Section>
|
||||
|
||||
<Section title='Education'>
|
||||
<Card
|
||||
heading='Lorem Ipsum'
|
||||
subheading='Sit amet consectetur'
|
||||
date='Dec 2022 - Nov 2023'
|
||||
imagePath='/src/assets/about-astro.png'
|
||||
altText='Lorem, ipsum dolor sit'
|
||||
imageClass='h-12 w-auto md:-left-16'
|
||||
>
|
||||
<ul class='ml-4 list-disc text-muted-foreground'>
|
||||
<li>
|
||||
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolore debitis recusandae, ut
|
||||
molestiae laboriosam pariatur!
|
||||
|
||||
<li>Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestiae, pariatur!</li>
|
||||
</li>
|
||||
</ul>
|
||||
</Card>
|
||||
<Card
|
||||
heading='Lorem Ipsum'
|
||||
subheading='Sit amet consectetur'
|
||||
date='Dec 2022 - Nov 2023'
|
||||
imagePath='/src/assets/about-astro.png'
|
||||
altText='Lorem, ipsum dolor sit'
|
||||
imageClass='h-12 w-auto md:-left-16'
|
||||
/>
|
||||
</Section>
|
||||
|
||||
<Section title='Projects'>
|
||||
<div class='flex flex-col gap-y-3 sm:flex-row sm:gap-x-3 sm:gap-y-0'>
|
||||
<ProjectCard
|
||||
href='https://www.google.com'
|
||||
heading='Consectetur'
|
||||
subheading='Lorem ipsum dolor sit amet consectetur adipisicing elit.'
|
||||
imagePath='/src/assets/coming-soon.png'
|
||||
altText='Example'
|
||||
class='w-full sm:w-1/2'
|
||||
/>
|
||||
<ProjectCard
|
||||
as='div'
|
||||
heading='Coming soon...'
|
||||
subheading=''
|
||||
imagePath='/src/assets/coming-soon.png'
|
||||
altText='Lorem, ipsum dolor sit'
|
||||
class='w-full sm:w-1/2'
|
||||
/>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title='Certifications'>
|
||||
<Card
|
||||
as='a'
|
||||
heading='Lorem ipsum, dolor sit amet consectetur adipisicing.'
|
||||
subheading='Lorem ipsum dolor sit amet consectetur adipisicing elit. Aperiam dicta magni consequuntur corrupti.'
|
||||
date='Mar 2024 - Mar 2024'
|
||||
imagePath='/src/assets/about-astro.png'
|
||||
altText='Lorem, ipsum dolor sit'
|
||||
imageClass='h-11 w-auto md:-left-16'
|
||||
href='https://www.google.com'
|
||||
/>
|
||||
<Card
|
||||
as='a'
|
||||
heading='Lorem ipsum, dolor sit amet'
|
||||
subheading='Lorem ipsum dolor sit amet consectetur adipisicing elit. Aperiam dicta.'
|
||||
date='Mar 2029 - Mar 2032'
|
||||
imagePath='/src/assets/about-astro.png'
|
||||
altText='Lorem, ipsum dolor sit'
|
||||
imageClass='h-11 w-auto md:-left-16'
|
||||
href='https://www.google.com'
|
||||
/>
|
||||
</Section>
|
||||
|
||||
<Section title='Skills'>
|
||||
<SkillLayout title='Languages' skills={languages} />
|
||||
<SkillLayout title='Frontend' skills={frontend} />
|
||||
<SkillLayout title='Backend' skills={backend} />
|
||||
<SkillLayout title='Others' skills={others} />
|
||||
</Section>
|
||||
</div>
|
||||
</PageLayout>
|
19
src/pages/rss.xml.js
Normal file
19
src/pages/rss.xml.js
Normal file
@ -0,0 +1,19 @@
|
||||
import rss from '@astrojs/rss'
|
||||
import { siteConfig } from '@/site-config'
|
||||
import { getAllPosts } from '@/utils'
|
||||
|
||||
export const GET = async () => {
|
||||
const posts = await getAllPosts()
|
||||
|
||||
return rss({
|
||||
title: siteConfig.title,
|
||||
description: siteConfig.description,
|
||||
site: import.meta.env.SITE,
|
||||
items: posts.map((post) => ({
|
||||
title: post.data.title,
|
||||
description: post.data.description,
|
||||
pubDate: post.data.publishDate,
|
||||
link: `/blog/${post.slug}`
|
||||
}))
|
||||
})
|
||||
}
|
83
src/pages/tags/[tag]/[...page].astro
Normal file
83
src/pages/tags/[tag]/[...page].astro
Normal file
@ -0,0 +1,83 @@
|
||||
---
|
||||
export const prerender = true
|
||||
|
||||
import type { GetStaticPaths, Page } from 'astro'
|
||||
import type { CollectionEntry } from 'astro:content'
|
||||
|
||||
import Pagination from '@/components/Paginator.astro'
|
||||
import PostPreview from '@/components/blog/PostPreview.astro'
|
||||
import PageLayout from '@/layouts/BaseLayout.astro'
|
||||
import Button from '@/components/Button.astro'
|
||||
import { getAllPosts, getUniqueTags, sortMDByDate } from '@/utils'
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async ({ paginate }) => {
|
||||
const allPosts = await getAllPosts()
|
||||
const allPostsByDate = sortMDByDate(allPosts)
|
||||
const uniqueTags = getUniqueTags(allPostsByDate)
|
||||
|
||||
return uniqueTags.flatMap((tag) => {
|
||||
const filterPosts = allPostsByDate.filter((post) => post.data.tags.includes(tag))
|
||||
return paginate(filterPosts, {
|
||||
pageSize: 10,
|
||||
params: { tag }
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
interface Props {
|
||||
page: Page<CollectionEntry<'post'>>
|
||||
}
|
||||
|
||||
const { page } = Astro.props
|
||||
const { tag } = Astro.params
|
||||
|
||||
const meta = {
|
||||
description: `View all posts with the tag - ${tag}`,
|
||||
title: `Tag: ${tag}`
|
||||
}
|
||||
|
||||
const paginationProps = {
|
||||
...(page.url.prev && {
|
||||
prevUrl: {
|
||||
text: `← Previous Tags`,
|
||||
url: page.url.prev
|
||||
}
|
||||
}),
|
||||
...(page.url.next && {
|
||||
nextUrl: {
|
||||
text: `Next Tags →`,
|
||||
url: page.url.next
|
||||
}
|
||||
})
|
||||
}
|
||||
---
|
||||
|
||||
<PageLayout meta={meta}>
|
||||
<div class='w-full'>
|
||||
<Button title='Back' href='/blog' style='button'>
|
||||
<svg
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
width='14'
|
||||
height='14'
|
||||
viewBox='0 0 24 24'
|
||||
slot='icon-before'
|
||||
>
|
||||
<path
|
||||
fill='currentColor'
|
||||
d='m6.921 12.5l5.792 5.792L12 19l-7-7l7-7l.713.708L6.921 11.5H19v1z'
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
</Button>
|
||||
<h1 class='mb-6 mt-5 flex items-end gap-x-2 text-2xl font-bold'>
|
||||
Tags:
|
||||
<span class='text-xl'>#{tag}</span>
|
||||
</h1>
|
||||
<section aria-label='Blog post list'>
|
||||
<ul class='flex flex-col gap-y-3 text-start'>
|
||||
{page.data.map((p) => <PostPreview as='h2' post={p} withDesc />)}
|
||||
</ul>
|
||||
<Pagination {...paginationProps} />
|
||||
</section>
|
||||
</div>
|
||||
</PageLayout>
|
55
src/pages/tags/index.astro
Normal file
55
src/pages/tags/index.astro
Normal file
@ -0,0 +1,55 @@
|
||||
---
|
||||
import Button from '@/components/Button.astro'
|
||||
import PageLayout from '@/layouts/BaseLayout.astro'
|
||||
import { getAllPosts, getUniqueTagsWithCount } from '@/utils'
|
||||
|
||||
const allPosts = await getAllPosts()
|
||||
const allTags = getUniqueTagsWithCount(allPosts)
|
||||
|
||||
const meta = {
|
||||
description: "A list of all the topics I've written about in my posts",
|
||||
title: 'All Tags'
|
||||
}
|
||||
---
|
||||
|
||||
<PageLayout meta={meta}>
|
||||
<div class='w-full'>
|
||||
<Button title='Back' href='/blog' style='button'>
|
||||
<svg
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
width='14'
|
||||
height='14'
|
||||
viewBox='0 0 24 24'
|
||||
slot='icon-before'
|
||||
>
|
||||
<path
|
||||
fill='currentColor'
|
||||
d='m6.921 12.5l5.792 5.792L12 19l-7-7l7-7l.713.708L6.921 11.5H19v1z'
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
</Button>
|
||||
|
||||
<h1 class='mb-6 mt-5 text-2xl font-bold'>Tags</h1>
|
||||
|
||||
<ul class='flex flex-col gap-y-3'>
|
||||
{
|
||||
allTags.map(([tag, val]) => (
|
||||
<li class='flex items-center gap-x-2 '>
|
||||
<a
|
||||
class='inline-block underline underline-offset-4 hover:text-foreground/75'
|
||||
data-astro-prefetch
|
||||
href={`/tags/${tag}/`}
|
||||
title={`View posts with the tag: ${tag}`}
|
||||
>
|
||||
#{tag}
|
||||
</a>
|
||||
<span class='inline-block'>
|
||||
- {val} post{val > 1 && 's'}
|
||||
</span>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</PageLayout>
|
Reference in New Issue
Block a user