mirror of
https://github.com/runyanjake/cooking.git
synced 2026-03-26 09:53:17 -07:00
Update website content, add quote of the day
This commit is contained in:
parent
f2b6e8b1c2
commit
153c73f438
@ -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>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--background: #111827;
|
||||
--foreground: #ededed;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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}
|
||||
|
||||
35
app/page.tsx
35
app/page.tsx
@ -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'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'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'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>
|
||||
|
||||
@ -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">
|
||||
|
||||
62
components/QuoteOfTheDay.tsx
Normal file
62
components/QuoteOfTheDay.tsx
Normal 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"> </p>;
|
||||
}
|
||||
|
||||
const content = quote.author ? (
|
||||
<>
|
||||
<span className="italic">“{quote.text}”</span>
|
||||
<span> — {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>
|
||||
);
|
||||
}
|
||||
@ -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>
|
||||
);
|
||||
|
||||
@ -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
7
public/quotes.json
Normal 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" }
|
||||
]
|
||||
Loading…
x
Reference in New Issue
Block a user