diff --git a/README.md b/README.md index 357f271..a50a922 100644 --- a/README.md +++ b/README.md @@ -94,28 +94,30 @@ This is a list of the various technologies used to build this template: Edit the `src/consts.ts` file to update your site's metadata, navigation links, and social links: -```typescript +```ts export const SITE: Site = { - TITLE: 'astro-erudite', - DESCRIPTION: + title: 'astro-erudite', + description: 'astro-erudite is a opinionated, unstyled blogging template—built with Astro, Tailwind, and shadcn/ui.', - EMAIL: 'jason@enscribe.dev', - NUM_POSTS_ON_HOMEPAGE: 2, - SITEURL: 'https://astro-erudite.vercel.app', + href: 'https://astro-erudite.vercel.app', + featuredPostCount: 2, + postsPerPage: 3, } -export const NAV_LINKS: Link[] = [ - { href: '/blog', label: 'blog' }, - { href: '/authors', label: 'authors' }, - { href: '/about', label: 'about' }, - { href: '/tags', label: 'tags' }, +export const NAV_LINKS: SocialLink[] = [ + { + href: '/blog', + label: 'blog', + }, + // ... ] -export const SOCIAL_LINKS: Link[] = [ - { href: 'https://github.com/jktrn', label: 'GitHub' }, - { href: 'https://twitter.com/enscry', label: 'Twitter' }, - { href: 'jason@enscribe.dev', label: 'Email' }, - { href: '/rss.xml', label: 'RSS' }, +export const SOCIAL_LINKS: SocialLink[] = [ + { + href: 'https://github.com/jktrn', + label: 'GitHub', + }, + // ... ] ``` @@ -185,8 +187,8 @@ The blog post schema is defined as follows: | Field | Type (Zod) | Requirements | Required | | ------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -| `title` | `string` | Must be ≤60 characters. | Yes | -| `description` | `string` | Must be ≤155 characters. | Yes | +| `title` | `string` | Should be ≤60 characters. | Yes | +| `description` | `string` | Should be ≤155 characters. | Yes | | `date` | `coerce.date()` | Must be in `YYYY-MM-DD` format. | Yes | | `image` | `image()` | Should be exactly 1200px × 630px. | Optional | | `tags` | `string[]` | Preferably use kebab-case for these. | Optional | diff --git a/src/components/AuthorCard.astro b/src/components/AuthorCard.astro index aef182e..aeee83a 100644 --- a/src/components/AuthorCard.astro +++ b/src/components/AuthorCard.astro @@ -1,8 +1,8 @@ --- import Link from '@/components/Link.astro' import AvatarComponent from '@/components/ui/avatar' -import type { Link as SocialLink } from '@/consts' import { cn } from '@/lib/utils' +import type { SocialLink } from '@/types' import type { CollectionEntry } from 'astro:content' import SocialIcons from './SocialIcons.astro' diff --git a/src/components/Head.astro b/src/components/Head.astro index f40d1fc..c0c16fa 100644 --- a/src/components/Head.astro +++ b/src/components/Head.astro @@ -30,7 +30,7 @@ const { title, description, image = '/static/twitter-card.png' } = Astro.props <title>{title}</title> <meta name="title" content={title} /> <meta name="description" content={description} /> -<meta name="author" content={SITE.TITLE} /> +<meta name="author" content={SITE.title} /> <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> @@ -44,7 +44,7 @@ const { title, description, image = '/static/twitter-card.png' } = Astro.props <meta property="og:type" content="website" /> <meta property="og:url" content={Astro.url} /> -<meta property="og:site_name" content={SITE.TITLE} /> +<meta property="og:site_name" content={SITE.title} /> <meta property="og:title" content={title} /> <meta property="og:description" content={description} /> <meta property="og:image" content={new URL(image, Astro.url)} /> diff --git a/src/components/Header.astro b/src/components/Header.astro index b21f093..09fa6be 100644 --- a/src/components/Header.astro +++ b/src/components/Header.astro @@ -19,7 +19,7 @@ import logo from '../../public/static/logo.svg' class="hover:text-primary flex shrink-0 items-center gap-2 text-xl font-medium transition-colors duration-300" > <Image src={logo} alt="Logo" class="size-8" /> - {SITE.TITLE} + {SITE.title} </Link> <div class="flex items-center gap-2 md:gap-4"> <nav class="hidden items-center gap-4 text-sm sm:gap-6 md:flex"> diff --git a/src/components/SocialIcons.astro b/src/components/SocialIcons.astro index 46d0622..236bb6a 100644 --- a/src/components/SocialIcons.astro +++ b/src/components/SocialIcons.astro @@ -1,51 +1,37 @@ --- import Link from '@/components/Link.astro' import { buttonVariants } from '@/components/ui/button' -import type { Link as SocialLink } from '@/consts' -import { cn } from '@/lib/utils' +import { ICON_MAP } from '@/consts' +import type { SocialLink } from '@/types' import { Icon } from 'astro-icon/components' interface Props { links: SocialLink[] - className?: string } -const { links, className } = Astro.props - -const iconMap = { - Website: 'lucide:globe', - GitHub: 'lucide:github', - LinkedIn: 'lucide:linkedin', - Twitter: 'lucide:twitter', - Email: 'lucide:mail', - RSS: 'lucide:rss', -} - -const getSocialLink = ({ href, label }: SocialLink) => ({ - href: label === 'Email' ? `mailto:${href}` : href, - ariaLabel: label, - iconName: - iconMap[label as keyof typeof iconMap] || 'lucide:message-circle-question', -}) +const { links } = Astro.props --- -<ul class={cn('flex flex-wrap gap-2', className)} role="list"> +<ul class="flex flex-wrap gap-2" role="list"> { - links.map((link) => { - const { href, ariaLabel, iconName } = getSocialLink(link) - return ( - <li> - <Link - href={href} - aria-label={ariaLabel} - title={ariaLabel} - class={buttonVariants({ variant: 'outline', size: 'icon' })} - external - > - <Icon name={iconName} class="size-4" /> - </Link> - </li> - ) - }) + links.map(({ href, label }) => ( + <li> + <Link + href={href} + aria-label={label} + title={label} + class={buttonVariants({ variant: 'outline', size: 'icon' })} + external + > + <Icon + name={ + ICON_MAP[label as keyof typeof ICON_MAP] || + 'lucide:message-circle-question' + } + class="size-4" + /> + </Link> + </li> + )) } </ul> diff --git a/src/consts.ts b/src/consts.ts index 84cadc0..30967bb 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -1,37 +1,53 @@ -export type Site = { - TITLE: string - DESCRIPTION: string - EMAIL: string - NUM_POSTS_ON_HOMEPAGE: number - POSTS_PER_PAGE: number - SITEURL: string -} - -export type Link = { - href: string - label: string -} +import type { IconMap, SocialLink, Site } from '@/types' export const SITE: Site = { - TITLE: 'astro-erudite', - DESCRIPTION: + title: 'astro-erudite', + description: 'astro-erudite is a opinionated, unstyled blogging template—built with Astro, Tailwind, and shadcn/ui.', - EMAIL: 'jason@enscribe.dev', - NUM_POSTS_ON_HOMEPAGE: 2, - POSTS_PER_PAGE: 3, - SITEURL: 'https://astro-erudite.vercel.app', + href: 'https://astro-erudite.vercel.app', + featuredPostCount: 2, + postsPerPage: 3, } -export const NAV_LINKS: Link[] = [ - { href: '/blog', label: 'blog' }, - { href: '/authors', label: 'authors' }, - { href: '/about', label: 'about' }, - { href: '/tags', label: 'tags' }, +export const NAV_LINKS: SocialLink[] = [ + { + href: '/blog', + label: 'blog', + }, + { + href: '/authors', + label: 'authors', + }, + { + href: '/about', + label: 'about', + }, ] -export const SOCIAL_LINKS: Link[] = [ - { href: 'https://github.com/jktrn', label: 'GitHub' }, - { href: 'https://twitter.com/enscry', label: 'Twitter' }, - { href: 'jason@enscribe.dev', label: 'Email' }, - { href: '/rss.xml', label: 'RSS' }, +export const SOCIAL_LINKS: SocialLink[] = [ + { + href: 'https://github.com/jktrn', + label: 'GitHub', + }, + { + href: 'https://twitter.com/enscry', + label: 'Twitter', + }, + { + href: 'mailto:jason@enscribe.dev', + label: 'Email', + }, + { + href: '/rss.xml', + label: 'RSS', + }, ] + +export const ICON_MAP: IconMap = { + Website: 'lucide:globe', + GitHub: 'lucide:github', + LinkedIn: 'lucide:linkedin', + Twitter: 'lucide:twitter', + Email: 'lucide:mail', + RSS: 'lucide:rss', +} diff --git a/src/content.config.ts b/src/content.config.ts index 28709e1..212b8f1 100644 --- a/src/content.config.ts +++ b/src/content.config.ts @@ -5,18 +5,8 @@ const blog = defineCollection({ loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/blog' }), schema: ({ image }) => z.object({ - title: z - .string() - .max( - 60, - 'Title should be 60 characters or less for optimal Open Graph display.', - ), - description: z - .string() - .max( - 155, - 'Description should be 155 characters or less for optimal Open Graph display.', - ), + title: z.string(), + description: z.string(), date: z.coerce.date(), image: image().optional(), tags: z.array(z.string()).optional(), diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index 0dd3d4c..91160b0 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -17,7 +17,7 @@ const { title, description, image } = Astro.props <html lang="en"> <head> <Head - title={`${title} | ${SITE.TITLE}`} + title={`${title} | ${SITE.title}`} description={description} image={image} /> diff --git a/src/pages/404.astro b/src/pages/404.astro index 2007b55..29a416f 100644 --- a/src/pages/404.astro +++ b/src/pages/404.astro @@ -8,7 +8,7 @@ import Layout from '@/layouts/Layout.astro' import { cn } from '@/lib/utils' --- -<Layout title="404" description={SITE.DESCRIPTION}> +<Layout title="404" description={SITE.description}> <Container class="flex grow flex-col gap-y-6"> <Breadcrumbs items={[{ label: '???', icon: 'lucide:circle-help' }]} /> diff --git a/src/pages/about.astro b/src/pages/about.astro index 35e2316..ce17ed4 100644 --- a/src/pages/about.astro +++ b/src/pages/about.astro @@ -10,7 +10,7 @@ import { getCollection } from 'astro:content' const projects = await getCollection('projects') --- -<Layout title="About" description={SITE.DESCRIPTION}> +<Layout title="About" description={SITE.description}> <Container class="flex flex-col gap-y-6"> <Breadcrumbs items={[{ label: 'About', icon: 'lucide:info' }]} /> diff --git a/src/pages/blog/[...page].astro b/src/pages/blog/[...page].astro index dcf116b..ae30dc0 100644 --- a/src/pages/blog/[...page].astro +++ b/src/pages/blog/[...page].astro @@ -16,7 +16,7 @@ export async function getStaticPaths({ const allPosts = await getCollection('blog', ({ data }) => !data.draft) return paginate( allPosts.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()), - { pageSize: SITE.POSTS_PER_PAGE }, + { pageSize: SITE.postsPerPage }, ) } diff --git a/src/pages/index.astro b/src/pages/index.astro index c78da60..0a168dd 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -10,10 +10,10 @@ import { getCollection } from 'astro:content' const blog = (await getCollection('blog')) .filter((post) => !post.data.draft) .sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()) - .slice(0, SITE.NUM_POSTS_ON_HOMEPAGE) + .slice(0, SITE.featuredPostCount) --- -<Layout title="Home" description={SITE.DESCRIPTION}> +<Layout title="Home" description={SITE.description}> <Container class="flex flex-col gap-y-6"> <section> <div class="rounded-lg border"> diff --git a/src/pages/rss.xml.ts b/src/pages/rss.xml.ts index 83ccd62..deef5e0 100644 --- a/src/pages/rss.xml.ts +++ b/src/pages/rss.xml.ts @@ -9,9 +9,9 @@ export async function GET(context: APIContext) { posts.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()) return rss({ - title: SITE.TITLE, - description: SITE.DESCRIPTION, - site: context.site ?? SITE.SITEURL, + title: SITE.title, + description: SITE.description, + site: context.site ?? SITE.href, items: posts.map((post) => ({ title: post.data.title, description: post.data.description, diff --git a/src/styles/global.css b/src/styles/global.css index 573fcb2..ec729fe 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -39,7 +39,7 @@ @font-face { font-family: 'Geist'; src: url('/fonts/GeistVF.woff2') format('woff2-variations'); - font-weight: 100 500; + font-weight: 100 900; font-style: normal; font-display: swap; } @@ -47,7 +47,7 @@ @font-face { font-family: 'Geist Mono'; src: url('/fonts/GeistMonoVF.woff2') format('woff2-variations'); - font-weight: 100 600; + font-weight: 100 900; font-style: normal; font-display: swap; } @@ -94,11 +94,10 @@ } html { - color-scheme: light; - @apply bg-background text-foreground; + @apply bg-background text-foreground scheme-light; &.dark { - color-scheme: dark; + @apply scheme-dark; } ::-webkit-scrollbar-corner { diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..cca598a --- /dev/null +++ b/src/types.ts @@ -0,0 +1,16 @@ +export type Site = { + title: string + description: string + href: string + featuredPostCount: number + postsPerPage: number +} + +export type SocialLink = { + href: string + label: string +} + +export type IconMap = { + [key: string]: string +}