Initial commit for website

This commit is contained in:
Timo Knuth 2026-03-16 21:38:49 +01:00
parent 609e3eb0ae
commit f0c19fbbfa
15 changed files with 65 additions and 45 deletions

View File

@ -1,6 +1,6 @@
# HOTSCHPOTSH — Handmade Pottery Atelier # KNUTH Ceramics — Handmade Pottery Atelier
Welcome to the official repository for **HOTSCHPOTSH**, a premium handmade pottery e-commerce platform and editorial site. This project features a React-based frontend, a Node.js/Express backend, and a PostgreSQL database for full content and order management. Welcome to the official repository for **KNUTH Ceramics**, a premium handmade pottery e-commerce platform and editorial site. This project features a React-based frontend, a Node.js/Express backend, and a PostgreSQL database for full content and order management.
--- ---

View File

@ -2,7 +2,33 @@ import React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { FOOTER_LINKS } from '../constants'; import { FOOTER_LINKS } from '../constants';
const DISABLED_FOOTER_LINKS = new Set([
'Best Sellers',
'Gift Cards',
'Sustainability',
'Careers',
'Press',
]);
const Footer: React.FC = () => { const Footer: React.FC = () => {
const renderFooterLink = (link: { label: string; href: string }) => {
const baseClassName = 'text-lg font-light transition-all duration-300 block';
if (DISABLED_FOOTER_LINKS.has(link.label)) {
return (
<span className={`${baseClassName} text-stone-500 cursor-not-allowed`} aria-disabled="true">
{link.label}
</span>
);
}
return (
<Link className={`${baseClassName} hover:text-stone-400 hover:pl-2`} to={link.href}>
{link.label}
</Link>
);
};
return ( return (
<footer className="bg-primary dark:bg-black text-white pt-32 pb-12 px-6 md:px-12 border-t border-stone-800"> <footer className="bg-primary dark:bg-black text-white pt-32 pb-12 px-6 md:px-12 border-t border-stone-800">
<div className="max-w-[1920px] mx-auto"> <div className="max-w-[1920px] mx-auto">
@ -11,7 +37,7 @@ const Footer: React.FC = () => {
<div className="lg:col-span-5 flex flex-col justify-between h-full"> <div className="lg:col-span-5 flex flex-col justify-between h-full">
<div> <div>
<h2 className="font-display text-6xl md:text-8xl leading-none tracking-tighter mb-8 bg-gradient-to-br from-white to-stone-400 bg-clip-text text-transparent"> <h2 className="font-display text-6xl md:text-8xl leading-none tracking-tighter mb-8 bg-gradient-to-br from-white to-stone-400 bg-clip-text text-transparent">
HOTSCHPOTSH KNUTH Ceramics
</h2> </h2>
<p className="font-body text-lg font-light text-stone-400 leading-relaxed max-w-md"> <p className="font-body text-lg font-light text-stone-400 leading-relaxed max-w-md">
Handcrafted ceramics for the modern home. Created with intention, fired with patience, and delivered with care. Handcrafted ceramics for the modern home. Created with intention, fired with patience, and delivered with care.
@ -43,9 +69,7 @@ const Footer: React.FC = () => {
<ul className="space-y-6"> <ul className="space-y-6">
{FOOTER_LINKS[0].links.map((link) => ( {FOOTER_LINKS[0].links.map((link) => (
<li key={link.label}> <li key={link.label}>
<Link className="text-lg font-light hover:text-stone-400 hover:pl-2 transition-all duration-300 block" to={link.href}> {renderFooterLink(link)}
{link.label}
</Link>
</li> </li>
))} ))}
</ul> </ul>
@ -55,9 +79,7 @@ const Footer: React.FC = () => {
<ul className="space-y-6"> <ul className="space-y-6">
{FOOTER_LINKS[1].links.map((link) => ( {FOOTER_LINKS[1].links.map((link) => (
<li key={link.label}> <li key={link.label}>
<Link className="text-lg font-light hover:text-stone-400 hover:pl-2 transition-all duration-300 block" to={link.href}> {renderFooterLink(link)}
{link.label}
</Link>
</li> </li>
))} ))}
</ul> </ul>
@ -67,9 +89,7 @@ const Footer: React.FC = () => {
<ul className="space-y-6"> <ul className="space-y-6">
{FOOTER_LINKS[2].links.map((link) => ( {FOOTER_LINKS[2].links.map((link) => (
<li key={link.label}> <li key={link.label}>
<Link className="text-lg font-light hover:text-stone-400 hover:pl-2 transition-all duration-300 block" to={link.href}> {renderFooterLink(link)}
{link.label}
</Link>
</li> </li>
))} ))}
</ul> </ul>
@ -79,7 +99,7 @@ const Footer: React.FC = () => {
{/* Bottom Bar */} {/* Bottom Bar */}
<div className="border-t border-white/10 pt-12 flex flex-col md:flex-row justify-between items-center text-xs text-stone-500 tracking-widest uppercase font-light"> <div className="border-t border-white/10 pt-12 flex flex-col md:flex-row justify-between items-center text-xs text-stone-500 tracking-widest uppercase font-light">
<p>© 2025 HOTSCHPOTSH Ceramics. All rights reserved.</p> <p>© 2025 KNUTH Ceramics. All rights reserved.</p>
<div className="flex space-x-8 mt-6 md:mt-0"> <div className="flex space-x-8 mt-6 md:mt-0">
<Link className="hover:text-white transition-colors" to="/privacy">Privacy</Link> <Link className="hover:text-white transition-colors" to="/privacy">Privacy</Link>
<Link className="hover:text-white transition-colors" to="/returns">Terms</Link> <Link className="hover:text-white transition-colors" to="/returns">Terms</Link>
@ -92,4 +112,4 @@ const Footer: React.FC = () => {
); );
}; };
export default Footer; export default Footer;

View File

@ -29,11 +29,11 @@ const GallerySection: React.FC = () => {
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="w-12 h-12 rounded-full bg-gradient-to-br from-purple-500 via-pink-500 to-orange-400 p-[2px]"> <div className="w-12 h-12 rounded-full bg-gradient-to-br from-purple-500 via-pink-500 to-orange-400 p-[2px]">
<div className="w-full h-full rounded-full bg-white dark:bg-background-dark flex items-center justify-center"> <div className="w-full h-full rounded-full bg-white dark:bg-background-dark flex items-center justify-center">
<span className="font-display text-lg">H</span> <span className="font-display text-lg">K</span>
</div> </div>
</div> </div>
<div> <div>
<h4 className="font-display text-xl text-text-main dark:text-white">@hotchpotsh_ceramics</h4> <h4 className="font-display text-xl text-text-main dark:text-white">@knuth_ceramics</h4>
<p className="text-xs text-text-muted">24.8k followers</p> <p className="text-xs text-text-muted">24.8k followers</p>
</div> </div>
</div> </div>
@ -126,16 +126,16 @@ const GallerySection: React.FC = () => {
<div className="flex items-center gap-3 pb-4 border-b border-stone-200 dark:border-stone-700"> <div className="flex items-center gap-3 pb-4 border-b border-stone-200 dark:border-stone-700">
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-purple-500 via-pink-500 to-orange-400 p-[2px]"> <div className="w-10 h-10 rounded-full bg-gradient-to-br from-purple-500 via-pink-500 to-orange-400 p-[2px]">
<div className="w-full h-full rounded-full bg-white dark:bg-stone-900 flex items-center justify-center"> <div className="w-full h-full rounded-full bg-white dark:bg-stone-900 flex items-center justify-center">
<span className="font-display text-sm">H</span> <span className="font-display text-sm">K</span>
</div> </div>
</div> </div>
<span className="font-bold text-sm text-text-main dark:text-white">hotchpotsh_ceramics</span> <span className="font-bold text-sm text-text-main dark:text-white">knuth_ceramics</span>
</div> </div>
{/* Caption */} {/* Caption */}
<div className="flex-1 py-4"> <div className="flex-1 py-4">
<p className="text-sm text-text-main dark:text-white"> <p className="text-sm text-text-main dark:text-white">
<span className="font-bold">hotchpotsh_ceramics</span> {selectedImage.caption} <span className="font-bold">knuth_ceramics</span> {selectedImage.caption}
</p> </p>
</div> </div>
@ -176,4 +176,4 @@ const GallerySection: React.FC = () => {
); );
}; };
export default GallerySection; export default GallerySection;

View File

@ -39,11 +39,11 @@ const Header: React.FC = () => {
{/* Logo */} {/* Logo */}
<div className="flex-shrink-0 relative group cursor-pointer"> <div className="flex-shrink-0 relative group cursor-pointer">
<Link className="font-display text-4xl md:text-5xl font-light tracking-widest uppercase text-text-main dark:text-white" to="/"> <Link className="relative z-10 font-display text-4xl md:text-5xl font-light tracking-widest uppercase text-text-main dark:text-white" to="/">
HOTSCHPOTSH KNUTH Ceramics
</Link> </Link>
{/* Subtle glow effect on hover */} {/* Subtle glow effect on hover */}
<div className="absolute -inset-4 bg-white/20 blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 rounded-full" /> <div className="absolute -inset-4 bg-white/20 blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 rounded-full pointer-events-none" />
</div> </div>
{/* Desktop Nav */} {/* Desktop Nav */}
@ -116,4 +116,4 @@ const Header: React.FC = () => {
); );
}; };
export default Header; export default Header;

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"/> <meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/> <meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>HOTSCHPOTSH Ceramics - Editorial Collection</title> <title>KNUTH Ceramics - Editorial Collection</title>
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script> <script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;0,600;1,300;1,400&amp;family=Manrope:wght@200;300;400;500&amp;display=swap" rel="stylesheet"/> <link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;0,600;1,300;1,400&amp;family=Manrope:wght@200;300;400;500&amp;display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/> <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
@ -85,4 +85,4 @@
<div id="root"></div> <div id="root"></div>
<script type="module" src="/index.tsx"></script> <script type="module" src="/index.tsx"></script>
</body> </body>
</html> </html>

View File

@ -1,5 +1,5 @@
{ {
"name": "IKKAI Ceramics", "name": "KNUTH Ceramics",
"description": "A high-fidelity recreation of the IKKAI Ceramics editorial e-commerce website featuring a minimalist design, custom typography, and responsive layout.", "description": "A high-fidelity recreation of the KNUTH Ceramics editorial e-commerce website featuring a minimalist design, custom typography, and responsive layout.",
"requestFramePermissions": [] "requestFramePermissions": []
} }

View File

@ -28,7 +28,7 @@ const Contact: React.FC = () => {
{ {
icon: "📧", icon: "📧",
title: "Email", title: "Email",
detail: "support@hotchpotshceramics.com", detail: "support@knuthceramics.com",
description: "Best for order inquiries or detailed questions" description: "Best for order inquiries or detailed questions"
}, },
{ {
@ -193,7 +193,7 @@ const Contact: React.FC = () => {
</p> </p>
<div className="flex justify-center gap-6"> <div className="flex justify-center gap-6">
<a <a
href="https://instagram.com/hotchpotshceramics" href="https://instagram.com/knuthceramics"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="px-8 py-3 bg-white dark:bg-stone-900 text-black dark:text-white border border-stone-300 dark:border-stone-700 text-xs font-bold uppercase tracking-widest hover:bg-stone-100 dark:hover:bg-stone-800 transition-colors" className="px-8 py-3 bg-white dark:bg-stone-900 text-black dark:text-white border border-stone-300 dark:border-stone-700 text-xs font-bold uppercase tracking-widest hover:bg-stone-100 dark:hover:bg-stone-800 transition-colors"
@ -201,7 +201,7 @@ const Contact: React.FC = () => {
Instagram Instagram
</a> </a>
<a <a
href="https://facebook.com/hotchpotshceramics" href="https://facebook.com/knuthceramics"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="px-8 py-3 bg-white dark:bg-stone-900 text-black dark:text-white border border-stone-300 dark:border-stone-700 text-xs font-bold uppercase tracking-widest hover:bg-stone-100 dark:hover:bg-stone-800 transition-colors" className="px-8 py-3 bg-white dark:bg-stone-900 text-black dark:text-white border border-stone-300 dark:border-stone-700 text-xs font-bold uppercase tracking-widest hover:bg-stone-100 dark:hover:bg-stone-800 transition-colors"

View File

@ -177,7 +177,7 @@ const Cookies: React.FC = () => {
> >
<h2 className="font-display text-3xl mb-4">Questions About Cookies?</h2> <h2 className="font-display text-3xl mb-4">Questions About Cookies?</h2>
<p className="font-body font-light text-stone-300 mb-8 max-w-2xl mx-auto"> <p className="font-body font-light text-stone-300 mb-8 max-w-2xl mx-auto">
For any questions about cookies or to opt-out of analytics tracking, please contact us at <strong>support@hotchpotshceramics.com</strong> For any questions about cookies or to opt-out of analytics tracking, please contact us at <strong>support@knuthceramics.com</strong>
</p> </p>
<Link <Link
to="/contact" to="/contact"

View File

@ -34,7 +34,7 @@ const faqData: FAQItem[] = [
}, },
{ {
question: "How do I contact you with questions?", question: "How do I contact you with questions?",
answer: "We're here to help! Feel free to reach out anytime. You can email our customer support at support@hotchpotshceramics.com or use the contact form on our site. We aim to respond within 12 business days. Thank you for choosing Hotchpotsh we love answering your questions and hearing your feedback!" answer: "We're here to help! Feel free to reach out anytime. You can email our customer support at support@knuthceramics.com or use the contact form on our site. We aim to respond within 12 business days. Thank you for choosing KNUTH Ceramics we love answering your questions and hearing your feedback!"
} }
]; ];

View File

@ -4,7 +4,7 @@ import BlogPostLayout from '../../components/BlogPostLayout';
const MotivationInClay: React.FC = () => { const MotivationInClay: React.FC = () => {
React.useEffect(() => { React.useEffect(() => {
document.title = "Creative Block for Potters: 10 Tips for Motivation | Hotchpotsh"; document.title = "Creative Block for Potters: 10 Tips for Motivation | KNUTH Ceramics";
let meta = document.querySelector('meta[name="description"]'); let meta = document.querySelector('meta[name="description"]');
if (!meta) { if (!meta) {
meta = document.createElement('meta'); meta = document.createElement('meta');
@ -93,4 +93,4 @@ const MotivationInClay: React.FC = () => {
); );
}; };
export default MotivationInClay; export default MotivationInClay;

View File

@ -4,7 +4,7 @@ import BlogPostLayout from '../../components/BlogPostLayout';
const PackagingGuide: React.FC = () => { const PackagingGuide: React.FC = () => {
React.useEffect(() => { React.useEffect(() => {
document.title = "How to Package Pottery for Shipping: A Safe Guide | Hotchpotsh"; document.title = "How to Package Pottery for Shipping: A Safe Guide | KNUTH Ceramics";
let meta = document.querySelector('meta[name="description"]'); let meta = document.querySelector('meta[name="description"]');
if (!meta) { if (!meta) {
meta = document.createElement('meta'); meta = document.createElement('meta');
@ -87,4 +87,4 @@ const PackagingGuide: React.FC = () => {
); );
}; };
export default PackagingGuide; export default PackagingGuide;

View File

@ -7,7 +7,7 @@ import BlogPostLayout from '../../components/BlogPostLayout';
const ProductPhotography: React.FC = () => { const ProductPhotography: React.FC = () => {
React.useEffect(() => { React.useEffect(() => {
document.title = "Product Photography for Pottery: Tips for Sales | Hotchpotsh"; document.title = "Product Photography for Pottery: Tips for Sales | KNUTH Ceramics";
// Simple meta description update for basic SPA // Simple meta description update for basic SPA
let meta = document.querySelector('meta[name="description"]'); let meta = document.querySelector('meta[name="description"]');
if (!meta) { if (!meta) {
@ -90,4 +90,4 @@ const ProductPhotography: React.FC = () => {
); );
}; };
export default ProductPhotography; export default ProductPhotography;

View File

@ -76,7 +76,7 @@ const Privacy: React.FC = () => {
}, },
{ {
subtitle: "Exercise Your Rights", subtitle: "Exercise Your Rights",
text: "To exercise any of these rights or with questions about your data, contact us at privacy@hotchpotshceramics.com. We will respond within 30 days." text: "To exercise any of these rights or with questions about your data, contact us at privacy@knuthceramics.com. We will respond within 30 days."
} }
] ]
}, },
@ -127,7 +127,7 @@ const Privacy: React.FC = () => {
transition={{ delay: 0.4, duration: 0.8 }} transition={{ delay: 0.4, duration: 0.8 }}
className="font-body text-lg font-light text-stone-500 leading-relaxed max-w-3xl" className="font-body text-lg font-light text-stone-500 leading-relaxed max-w-3xl"
> >
At HOTCHPOTSH Ceramics, your privacy and trust are important to us. We collect and handle your information responsibly, because 60% of people are more likely to trust brands that protect their data. This policy explains what data we collect, how we use it, and your rights. At KNUTH Ceramics, your privacy and trust are important to us. We collect and handle your information responsibly, because 60% of people are more likely to trust brands that protect their data. This policy explains what data we collect, how we use it, and your rights.
</motion.p> </motion.p>
<motion.p <motion.p
initial={{ y: 30, opacity: 0 }} initial={{ y: 30, opacity: 0 }}
@ -177,7 +177,7 @@ const Privacy: React.FC = () => {
> >
<h2 className="font-display text-3xl mb-4">Contact & Updates</h2> <h2 className="font-display text-3xl mb-4">Contact & Updates</h2>
<p className="font-body font-light text-stone-300 leading-relaxed mb-6 max-w-3xl"> <p className="font-body font-light text-stone-300 leading-relaxed mb-6 max-w-3xl">
If you have any privacy questions, or if you want to request or update your personal data, please contact us at <strong>privacy@hotchpotshceramics.com</strong> or use our contact page. We may update this Privacy Policy occasionally to reflect changes in our practices; the latest version will always be posted here with an updated date. If you have any privacy questions, or if you want to request or update your personal data, please contact us at <strong>privacy@knuthceramics.com</strong> or use our contact page. We may update this Privacy Policy occasionally to reflect changes in our practices; the latest version will always be posted here with an updated date.
</p> </p>
<p className="font-body font-light text-stone-400 text-sm"> <p className="font-body font-light text-stone-400 text-sm">
By shopping with us, you acknowledge you have read and agree to this Privacy Policy. By shopping with us, you acknowledge you have read and agree to this Privacy Policy.

View File

@ -7,7 +7,7 @@ const Returns: React.FC = () => {
{ {
step: "01", step: "01",
title: "Contact Us", title: "Contact Us",
description: "Email support@hotchpotshceramics.com within 14 days of delivery with your order number and photos of the item and packaging." description: "Email support@knuthceramics.com within 14 days of delivery with your order number and photos of the item and packaging."
}, },
{ {
step: "02", step: "02",

View File

@ -63,7 +63,7 @@ const Shipping: React.FC = () => {
transition={{ delay: 0.4, duration: 0.8 }} transition={{ delay: 0.4, duration: 0.8 }}
className="font-body text-lg font-light text-stone-500 leading-relaxed" className="font-body text-lg font-light text-stone-500 leading-relaxed"
> >
HOTCHPOTSH Ceramics proudly ships nationwide from our Texas studio. We strive to make delivery smooth and transparent for you. KNUTH Ceramics proudly ships nationwide from our Texas studio. We strive to make delivery smooth and transparent for you.
</motion.p> </motion.p>
</div> </div>