Update website content, add quote of the day

This commit is contained in:
Jake Runyan 2026-02-12 23:15:01 -08:00
parent f2b6e8b1c2
commit 153c73f438
9 changed files with 140 additions and 65 deletions

View File

@ -1,8 +1,8 @@
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'About - Cooking',
description: 'Learn more about our recipe collection',
title: 'About - PWS Recipes',
description: 'Learn more about the PWS recipe collection',
};
export default function AboutPage() {
@ -10,22 +10,20 @@ export default function AboutPage() {
<div className="max-w-3xl space-y-8">
<div className="space-y-4">
<h1 className="text-4xl font-bold text-gray-900 dark:text-white">
About
About PWS Recipes
</h1>
<p className="text-lg text-gray-600 dark:text-gray-400">
Welcome to our content-first recipe site
Explore recipes in a user-friendly manner on a website that prioritizes your cooking experience over monetizing your clicks.
</p>
</div>
<div className="prose dark:prose-invert max-w-none">
<section className="space-y-4">
<h2 className="text-2xl font-semibold text-gray-900 dark:text-white">
Our Mission
The PWS Mission
</h2>
<p className="text-gray-600 dark:text-gray-400">
We believe cooking should be accessible, enjoyable, and creative. Our goal is to provide
high-quality recipes with clear instructions and beautiful photography to inspire home cooks
everywhere.
We believe that cooking should be accessible, enjoyable, and creative. Our goal while collecting and organizing these recipes is to make knowledge readily available and keep your cooking experience a cathartic and fun one.
</p>
</section>
@ -48,8 +46,7 @@ export default function AboutPage() {
Technology
</h2>
<p className="text-gray-600 dark:text-gray-400">
Built with modern web technologies including Next.js, React, TypeScript, and Tailwind CSS
to ensure fast performance and excellent SEO.
Built with modern web technologies including Next.js, React, TypeScript, and Tailwind CSS to ensure fast performance.
</p>
</section>
</div>

View File

@ -9,7 +9,7 @@
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--background: #111827;
--foreground: #ededed;
}
}

View File

@ -4,16 +4,16 @@ import Header from "@/components/Header";
import Footer from "@/components/Footer";
export const metadata: Metadata = {
title: "Cooking - Recipe Collection",
description: "A content-first recipe site with delicious recipes and cooking tips",
title: "PWS Recipes",
description: "A content-first recipe site with delicious recipes and cooking tips.",
keywords: ["recipes", "cooking", "food", "kitchen"],
authors: [{ name: "Cooking" }],
openGraph: {
type: "website",
locale: "en_US",
url: "https://cooking.example.com",
siteName: "Cooking",
title: "Cooking - Recipe Collection",
url: "https://recipes.whitney.rip",
siteName: "PWS Recipes",
title: "PWS Recipes",
description: "A content-first recipe site with delicious recipes and cooking tips",
},
};
@ -25,7 +25,7 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<body className="flex flex-col min-h-screen">
<body className="flex flex-col min-h-screen bg-white dark:bg-gray-900">
<Header />
<main className="flex-1 max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8 py-8">
{children}

View File

@ -1,28 +1,27 @@
import Image from 'next/image';
import Link from 'next/link';
import QuoteOfTheDay from '@/components/QuoteOfTheDay';
export default function Home() {
return (
<div className="space-y-12">
<section className="text-center space-y-6">
<h1 className="text-5xl font-bold text-gray-900 dark:text-white">
Welcome to Cooking
PWS Recipes
</h1>
<p className="text-xl text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
Discover delicious recipes, cooking tips, and culinary inspiration for every occasion.
</p>
<QuoteOfTheDay />
<div className="flex gap-4 justify-center">
<Link
href="/recipes"
className="px-6 py-3 bg-gray-900 dark:bg-white text-white dark:text-gray-900 rounded-lg hover:bg-gray-700 dark:hover:bg-gray-200 transition-colors font-medium"
>
Browse Recipes
Cook Something!
</Link>
<Link
href="/about"
className="px-6 py-3 border border-gray-900 dark:border-white text-gray-900 dark:text-white rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors font-medium"
>
Learn More
Why PWS Recipes?
</Link>
</div>
</section>
@ -32,16 +31,16 @@ export default function Home() {
<div className="w-full md:w-3/5 relative aspect-[3/2] rounded-2xl overflow-hidden shadow-lg">
<Image
src="/assets/want_to_cook.svg"
alt="Person deciding what to cook"
alt="Person happily cooking a stew"
fill
className="object-cover"
unoptimized
/>
</div>
<div className="w-full md:w-2/5 space-y-4">
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">Easy Recipes</h2>
<div className="w-full md:w-2/5 space-y-4 text-center md:text-left">
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">You Want to Cook</h2>
<p className="text-lg text-gray-600 dark:text-gray-400">
Step-by-step instructions for home cooks of all skill levels. Whether you&apos;re a beginner or an experienced cook, every recipe is written with clarity in mind.
Cooking is fun, theraputic, and you need to eat stuff to survive. I&apos;ve collected and tweaked recipes over the years, but over time the bookmark folder has gotten big and recipe sites have gotten worse...
</p>
<Link
href="/recipes"
@ -55,17 +54,17 @@ export default function Home() {
<div className="flex flex-col md:flex-row-reverse items-center gap-12">
<div className="w-full md:w-3/5 relative aspect-[3/2] rounded-2xl overflow-hidden shadow-lg">
<Image
src="/assets/online_cookbook.svg"
src="/assets/recipe_sites_suck.svg"
alt="Online cookbook illustration"
fill
className="object-cover"
unoptimized
/>
</div>
<div className="w-full md:w-2/5 space-y-4">
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">Beautiful Photos</h2>
<div className="w-full md:w-2/5 space-y-4 text-center md:text-left">
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">But Recipe Sites Suck!</h2>
<p className="text-lg text-gray-600 dark:text-gray-400">
High-quality images accompany every recipe to inspire your cooking journey. See exactly what you&apos;re making before you start.
Monetized recipe sites don't bother me, but I do mind when sites have overly aggressive ad integrations that block or move around the main content. Many modern sites share the same user-unfriendly plugins.
</p>
</div>
</div>
@ -73,17 +72,17 @@ export default function Home() {
<div className="flex flex-col md:flex-row items-center gap-12">
<div className="w-full md:w-3/5 relative aspect-[3/2] rounded-2xl overflow-hidden shadow-lg">
<Image
src="/assets/recipe_sites_suck.svg"
src="/assets/online_cookbook.svg"
alt="Organized recipe collection"
fill
className="object-cover"
unoptimized
/>
</div>
<div className="w-full md:w-2/5 space-y-4">
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">No Nonsense</h2>
<div className="w-full md:w-2/5 space-y-4 text-center md:text-left">
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">Welcome to my Self-Hosted Cookbook!</h2>
<p className="text-lg text-gray-600 dark:text-gray-400">
Just recipes. Find what you need quickly by browsing categories, filtering by tags, or searching by ingredient.
Rather than make a physical cookbook, I have built this website to collect my recipes. This content-first website framework renders each page from a MDX markdown file, offering a friendly approach to frontend design for us backend engineers.
</p>
</div>
</div>

View File

@ -9,7 +9,7 @@ export default function Header() {
href="/"
className="text-2xl font-bold text-gray-900 dark:text-white hover:text-gray-700 dark:hover:text-gray-300 transition-colors"
>
Cooking
PWS Recipes
</Link>
<div className="flex space-x-8">

View File

@ -0,0 +1,62 @@
'use client';
import { useState, useEffect } from 'react';
import quotes from '@/public/quotes.json';
interface Quote {
text: string;
author?: string;
link?: string;
}
function getDayOfYear(): number {
const now = new Date();
const start = new Date(now.getFullYear(), 0, 0);
const diff = now.getTime() - start.getTime();
return Math.floor(diff / (1000 * 60 * 60 * 24));
}
export default function QuoteOfTheDay() {
const [quote, setQuote] = useState<Quote | null>(null);
useEffect(() => {
const index = getDayOfYear() % quotes.length;
setQuote(quotes[index] as Quote);
}, []);
if (!quote) {
return <p className="text-xl text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">&nbsp;</p>;
}
const content = quote.author ? (
<>
<span className="italic">&ldquo;{quote.text}&rdquo;</span>
<span> &mdash; {quote.author}</span>
</>
) : (
<span>{quote.text}</span>
);
const href = quote.link && !/^https?:\/\//.test(quote.link)
? `https://${quote.link}`
: quote.link;
const wrapper = href ? (
<a
href={href}
target="_blank"
rel="noopener noreferrer"
className="hover:text-gray-900 dark:hover:text-gray-200 hover:underline transition-colors"
>
{content}
</a>
) : (
content
);
return (
<p className="text-xl text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
{wrapper}
</p>
);
}

View File

@ -34,51 +34,60 @@ export default function RecipeLayout({
{/* Mobile Overlay */}
{sidebarOpen && (
<div
className="lg:hidden fixed inset-0 bg-black bg-opacity-50 z-40"
className="lg:hidden fixed inset-0 bg-black/50 z-40"
onClick={() => setSidebarOpen(false)}
aria-hidden="true"
/>
)}
{/* Mobile menu button - only visible on mobile */}
<div className="lg:hidden sticky top-0 z-30 bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-700 p-4">
{/* Mobile filter button */}
<div className="lg:hidden mb-4">
<button
onClick={() => setSidebarOpen(true)}
className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
className="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-800 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors"
aria-label="Open filters sidebar"
aria-expanded={sidebarOpen}
aria-controls="recipes-sidebar"
>
<span aria-hidden="true"></span>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
</svg>
<span>Filters</span>
</button>
</div>
<div className="flex">
{/* Sidebar - Always visible on desktop (lg+), slide-out on mobile */}
{/* Sidebar - Always visible on desktop (lg+), slide-out drawer on mobile */}
<aside
id="recipes-sidebar"
className={`
fixed lg:relative z-50 lg:z-0
bg-white dark:bg-gray-900 border-r border-gray-200 dark:border-gray-700
w-64 lg:w-64
h-screen lg:h-auto
top-0 bottom-0 left-0
w-72 lg:w-64
bg-white dark:bg-gray-900
border-r border-gray-200 dark:border-gray-700
transition-transform duration-300 ease-in-out
${sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
`}
aria-label="Recipe filters"
>
<div className="h-full lg:sticky lg:top-0 flex flex-col p-4 overflow-y-auto">
{/* Mobile close button */}
<div className="h-full lg:sticky lg:top-0 flex flex-col overflow-y-auto">
{/* Mobile sidebar header */}
<div className="lg:hidden flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700">
<span className="text-sm font-semibold text-gray-900 dark:text-white">Filters</span>
<button
onClick={() => setSidebarOpen(false)}
className="lg:hidden absolute top-4 right-4 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 text-xl"
className="p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
aria-label="Close filters sidebar"
>
<span aria-hidden="true"></span>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
{/* Sidebar content */}
<div className="p-4">
{showFilters && filters && (
<RecipesSidebar
categories={categories}
@ -88,12 +97,13 @@ export default function RecipeLayout({
/>
)}
</div>
</div>
</aside>
{/* Main content */}
<main className="flex-1 p-6">
<div className="flex-1 min-w-0">
{children}
</main>
</div>
</div>
</div>
);

View File

@ -12,7 +12,7 @@ interface RecipePageClientProps {
export default function RecipePageClient({ recipe, sections }: RecipePageClientProps) {
return (
<div className="min-h-screen p-6">
<div>
<article className="max-w-4xl mx-auto">
{/* Back navigation */}
<nav aria-label="Breadcrumb">

7
public/quotes.json Normal file
View File

@ -0,0 +1,7 @@
[
{ "text": "Let him Cook!", "author": "Lil B", "link": "https://knowyourmeme.com/memes/let-him-cook-let-that-boy-cook"},
{ "text": "I think careful cooking is love, don't you?", "author": "Julia Child" },
{ "text": "The only time to eat diet food is while you're waiting for the steak to cook.", "author": "Julia Child" },
{ "text": "A recipe has no soul. You, as the cook, must bring soul to the recipe.", "author": "Thomas Keller"},
{ "text": "People who love to eat are always the best people.", "author": "Julia Child" }
]