{"id":41488410,"url":"https://github.com/kunalkeshan/hzel-brown","last_synced_at":"2026-01-23T18:10:49.617Z","repository":{"id":322607197,"uuid":"1084102157","full_name":"kunalkeshan/hzel-brown","owner":"kunalkeshan","description":"An artisan dessert shop e-commerce platform specializing in handcrafted brownies, brookies, cupcakes, and cookies with delivery across Tamil Nadu, India.","archived":false,"fork":false,"pushed_at":"2025-12-25T21:44:54.000Z","size":1620,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-27T07:13:55.739Z","etag":null,"topics":["bakery","ecommerce","nextjs","react-email","sanity-io","tailwindcss"],"latest_commit_sha":null,"homepage":"https://hzel-brown.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kunalkeshan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY_HEADERS_GUIDE.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-27T08:17:23.000Z","updated_at":"2025-12-25T21:44:55.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/kunalkeshan/hzel-brown","commit_stats":null,"previous_names":["kunalkeshan/hzel-brown"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kunalkeshan/hzel-brown","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kunalkeshan%2Fhzel-brown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kunalkeshan%2Fhzel-brown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kunalkeshan%2Fhzel-brown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kunalkeshan%2Fhzel-brown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kunalkeshan","download_url":"https://codeload.github.com/kunalkeshan/hzel-brown/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kunalkeshan%2Fhzel-brown/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28697428,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T17:25:48.045Z","status":"ssl_error","status_checked_at":"2026-01-23T17:25:47.153Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bakery","ecommerce","nextjs","react-email","sanity-io","tailwindcss"],"created_at":"2026-01-23T18:10:48.763Z","updated_at":"2026-01-23T18:10:49.611Z","avatar_url":"https://github.com/kunalkeshan.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hzel Brown\n\nAn artisan dessert shop e-commerce platform specializing in handcrafted brownies, brookies, cupcakes, and cookies with delivery across Tamil Nadu, India.\n\n## Table of Contents\n\n- [Features](#features)\n- [Tech Stack](#tech-stack)\n- [Prerequisites](#prerequisites)\n- [Installation](#installation)\n- [Environment Variables](#environment-variables)\n- [Development](#development)\n- [On-Demand Revalidation with Sanity Webhooks](#on-demand-revalidation-with-sanity-webhooks)\n- [Available Scripts](#available-scripts)\n- [Project Structure](#project-structure)\n- [Deployment](#deployment)\n- [License](#license)\n- [Contact](#contact)\n\n## Features\n\n- **Menu Management**: Browse categorized menu items with detailed information including ingredients, allergens, and pricing\n- **E-commerce Functionality**: Shopping cart, item details, and product categorization\n- **Content Management**: Fully integrated Sanity CMS for managing products, content, and site configuration\n- **Responsive Design**: Mobile-first approach with modern UI components\n- **Email Templates**: Integrated React Email for transactional emails\n- **Type Safety**: Full TypeScript support with auto-generated types from Sanity schema\n\n## Tech Stack\n\n- **Framework**: [Next.js 16](https://nextjs.org/) with App Router\n- **UI Library**: [React 19](https://react.dev/)\n- **CMS**: [Sanity](https://www.sanity.io/)\n- **Styling**: [Tailwind CSS](https://tailwindcss.com/)\n- **Component Library**: [Radix UI](https://www.radix-ui.com/)\n- **State Management**: [Zustand](https://zustand-demo.pmnd.rs/)\n- **Forms**: [React Hook Form](https://react-hook-form.com/) + [Zod](https://zod.dev/)\n- **Email**: [React Email](https://react.email/)\n- **Animations**: [Motion](https://motion.dev/)\n- **Language**: [TypeScript](https://www.typescriptlang.org/)\n\n## Prerequisites\n\nBefore you begin, ensure you have the following installed:\n\n- **Node.js**: v22.x or higher (LTS recommended)\n- **pnpm**: v10.x or higher\n\nYou can install pnpm globally using:\n\n```bash\nnpm install -g pnpm@latest\n# or using Corepack (recommended)\ncorepack enable\ncorepack use pnpm@latest\n```\n\n## Installation\n\n1. **Clone the repository**\n\n```bash\ngit clone https://github.com/kunalkeshan/hzel-brown.git\ncd hzel-brown\n```\n\n2. **Install dependencies**\n\n```bash\npnpm install\n```\n\n3. **Set up environment variables**\n\nCopy the `.env.sample` file to `.env.local` and fill in your environment variables:\n\n```bash\ncp .env.sample .env.local\n```\n\nSee [Environment Variables](#environment-variables) section for details.\n\n4. **Set up Sanity**\n\nIf you haven't already set up a Sanity project, you can initialize one using:\n\n```bash\nnpx sanity@latest init\n```\n\nThis will guide you through creating a new Sanity project or connecting to an existing one.\n\nFor detailed setup instructions, refer to the [next-sanity documentation](https://github.com/sanity-io/next-sanity).\n\n5. **Generate Sanity types**\n\n```bash\npnpm run generate:types\n```\n\n## Environment Variables\n\nCreate a `.env.local` file in the root directory with the following variables:\n\n```env\n# Sanity Configuration\nNEXT_PUBLIC_SANITY_PROJECT_ID=your_project_id\nNEXT_PUBLIC_SANITY_DATASET=your_dataset_name\n\n# Environment\nNODE_ENV=development\n\n# Site Configuration\nSITE_URL=http://localhost:3000\n\n# Sanity Webhook Secret (required for on-demand revalidation)\n# Generate a strong secret and add the same value to your Sanity webhook configuration\nSANITY_WEBHOOK_SECRET=your_webhook_secret\n```\n\n**Note**: For actual values and additional configuration details, refer to the `.env.sample` file or contact the repository owner.\n\n## Development\n\nTo start the development server:\n\n```bash\npnpm dev\n```\n\nThis will concurrently start:\n- **Next.js development server** at [http://localhost:3000](http://localhost:3000)\n- **Email preview server** at [http://localhost:3001](http://localhost:3001)\n\nYou can also run them individually:\n\n```bash\n# Next.js only\npnpm dev:app\n\n# Email preview only\npnpm dev:email\n```\n\n### Accessing Sanity Studio\n\nThe Sanity CMS admin panel is available at:\n\n```\nhttp://localhost:3000/cms\n```\n\n## On-Demand Revalidation with Sanity Webhooks\n\nThis application uses **on-demand revalidation** instead of time-based revalidation for optimal performance and reduced API calls. When content is updated in Sanity CMS, webhooks automatically trigger cache invalidation for affected pages.\n\n### How It Works\n\n1. **Content Update**: You create, update, or delete content in Sanity Studio\n2. **Webhook Trigger**: Sanity sends a webhook to your Next.js application\n3. **Cache Invalidation**: The webhook handler identifies affected pages and revalidates specific cache tags\n4. **Fresh Content**: Users immediately see updated content without waiting for a time-based revalidation interval\n\nThis approach provides:\n- ✅ **Instant updates**: Content changes are reflected immediately\n- ✅ **Reduced API usage**: No periodic polling or unnecessary revalidation\n- ✅ **Granular control**: Only affected pages are revalidated\n- ✅ **Better performance**: Cache stays fresh without rebuilding unaffected pages\n\n### Setting Up Webhooks\n\nTo enable on-demand revalidation, configure a webhook in your Sanity project:\n\n1. **Navigate to Webhook Settings**\n   - Go to [sanity.io/manage](https://www.sanity.io/manage)\n   - Select your project → **API** → **Webhooks**\n\n2. **Create a New Webhook**\n   - **Name**: `Next.js On-Demand Revalidation`\n   - **URL**: `https://your-production-domain.com/api/revalidate`\n   - **HTTP Method**: `POST`\n   - **Trigger on**: ✅ Create, ✅ Update, ✅ Delete\n\n3. **Configure Filter (GROQ)**\n   ```groq\n   _type in ['menuItem', 'menuCategory', 'siteConfig', 'legal', 'faqs']\n   ```\n   This ensures the webhook only fires for relevant content types.\n\n4. **Configure Projection (GROQ)**\n   ```groq\n   {\n     _id,\n     _type,\n     \"slug\": slug.current,\n     \"categorySlug\": category-\u003eslug.current\n   }\n   ```\n   This sends just enough data to determine which cache tags to invalidate.\n\n5. **Add Secret**\n   - Generate a strong secret (use a password generator)\n   - Add it to the webhook configuration in Sanity\n   - Add the same value as `SANITY_WEBHOOK_SECRET` in your `.env.local` and production environment variables\n\n6. **Save and Test**\n   - Save the webhook configuration\n   - Test it by updating any content in Sanity Studio\n   - Check your deployment logs to verify the webhook is being received\n\n### Technical Details\n\nThe webhook endpoint (`/app/api/revalidate/route.ts`) uses Next.js's [`revalidateTag`](https://nextjs.org/docs/app/api-reference/functions/revalidateTag) function to invalidate cache entries based on document type and slug.\n\n**Cache Tag Patterns:**\n\nThe application uses a type-safe tagging system defined in `/sanity/lib/cache-tags.ts`:\n\n- **Collection-level tags**: `collection:{type}` - Used to invalidate all documents of a specific type\n  - `collection:menuItem` - All menu items\n  - `collection:menuCategory` - All menu categories\n  - `collection:siteConfig` - Site configuration\n  - `collection:legal` - All legal documents\n  - `collection:faqs` - All FAQs\n\n- **Document-level tags**: `{type}:{slug}` - Used to invalidate a specific document\n  - `menuItem:chocolate-brownie` - Specific menu item\n  - `menuCategory:brownies` - Specific category\n  - `legal:privacy-policy` - Specific legal document\n\n**Example:**\n\nWhen updating a menu item with slug `chocolate-brownie` in the `brownies` category, the webhook will revalidate:\n- `collection:menuItem` - All menu pages showing menu items\n- `menuItem:chocolate-brownie` - The specific item detail page\n- `menuCategory:brownies` - The brownies category page\n\nThis type-safe approach ensures:\n- **Compile-time validation** - TypeScript enforces valid tag patterns\n- **Consistency** - Helper functions (`createCollectionTag`, `createDocumentTag`) ensure uniform tag creation\n- **Maintainability** - Tags are derived from Sanity schema types automatically\n\n### Documentation References\n\n- **Sanity Webhooks**: [sanity.io/docs/webhooks](https://www.sanity.io/docs/compute-and-ai/webhooks)\n- **Next.js On-Demand Revalidation**: [nextjs.org/docs/app/guides/incremental-static-regeneration#on-demand-revalidation-with-revalidatetag](https://nextjs.org/docs/app/guides/incremental-static-regeneration#on-demand-revalidation-with-revalidatetag)\n- **revalidateTag API**: [nextjs.org/docs/app/api-reference/functions/revalidateTag](https://nextjs.org/docs/app/api-reference/functions/revalidateTag)\n\n## Available Scripts\n\n| Script | Description |\n|--------|-------------|\n| `pnpm dev` | Start both Next.js and Email preview servers concurrently |\n| `pnpm dev:app` | Start Next.js development server with Turbopack |\n| `pnpm dev:email` | Start Email preview server on port 3001 |\n| `pnpm build` | Build the Next.js application for production |\n| `pnpm start` | Start the production server |\n| `pnpm lint` | Run ESLint to check code quality |\n| `pnpm generate:types` | Generate TypeScript types from Sanity schema |\n\n## Project Structure\n\n```\nhzel-brown/\n├── app/                    # Next.js App Router\n│   ├── (static)/          # Static pages (menu, cart, contact, etc.)\n│   ├── cms/               # Sanity Studio admin interface\n│   └── api/               # API routes\n│       └── revalidate/    # Webhook endpoint for on-demand revalidation\n├── components/            # React components\n│   ├── landing/          # Landing page components\n│   ├── menu/             # Menu-related components\n│   ├── cart/             # Shopping cart components\n│   └── ui/               # Reusable UI components\n├── sanity/                # Sanity CMS configuration\n│   ├── schemaTypes/      # Content type definitions\n│   ├── queries/          # GROQ queries\n│   └── lib/              # Sanity client and utilities\n├── stores/                # Zustand state management\n├── hooks/                 # Custom React hooks\n├── lib/                   # Utility functions\n├── types/                 # TypeScript type definitions\n└── public/                # Static assets\n```\n\n## Deployment\n\nThis application is designed to be deployed on [Vercel](https://vercel.com).\n\n[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/kunalkeshan/hzel-brown)\n\n### Deployment Steps\n\n1. Push your code to a Git repository (GitHub, GitLab, or Bitbucket)\n2. Import your repository to Vercel\n3. Configure your environment variables in the Vercel dashboard (including `SANITY_WEBHOOK_SECRET`)\n4. Deploy!\n5. **Important**: After deployment, configure the Sanity webhook with your production URL (see [On-Demand Revalidation](#on-demand-revalidation-with-sanity-webhooks))\n\nFor more information, see the [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying).\n\n## License\n\nThis project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details.\n\n## Contact\n\nFor questions, issues, or contributions, please contact the repository owner or open an issue on GitHub.\n\n---\n\nMade with ❤️ for artisan dessert lovers\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkunalkeshan%2Fhzel-brown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkunalkeshan%2Fhzel-brown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkunalkeshan%2Fhzel-brown/lists"}