Component Philosophy
Relevant source files
The following files were used as context for generating this wiki page:
The Grapevine website is built using Next.js and TypeScript, following a modern, component-based architecture. The philosophy centers on creating a clear hierarchy of reusable components, from low-level UI primitives to high-level page sections. This approach promotes consistency, maintainability, and developer efficiency. Styling is managed via Tailwind CSS, with a centralized theming system, and interactivity is enhanced with Framer Motion for animations.
Components are organized logically within the components/ directory, enabling a compositional approach where complex pages are assembled from smaller, self-contained blocks. This modularity is evident in how pages like the homepage or product page are constructed by stacking various feature and content components.
Project Structure and Organization
The project follows the standard Next.js App Router structure. The core of the component architecture resides in the components/ directory, which is further subdivided by component type.
Sources: README.md
This diagram illustrates the component directory structure as described in the project's README.md.
Sources: README.md
| Directory | Description |
|---|---|
app/ | Contains Next.js App Router pages, where components are imported and assembled to create views. |
components/ | The central repository for all React components. |
components/animations/ | Houses animation-specific components, likely wrappers for Framer Motion. |
components/icons/ | Contains custom icon components, such as the X and LinkedIn icons. |
components/primitives/ | Holds low-level, reusable UI elements like Buttons, Inputs, and layout containers. |
lib/ | Contains utility functions, such as the cn function for merging CSS classes. |
public/ | Stores static assets like images and fonts. |
Sources: README.md, components/contact-form.tsx:8, components/footer.tsx:5-7
Component Composition
Pages are constructed by composing multiple, large-scale "section" components. This pattern is visible across all main pages, where the page file itself is a clean, readable assembly of these sections.
For example, the homepage (app/page.tsx) is built by stacking components like HeroPartners, Features, AlternatingContent, StatsSection, ProofPoints, and CtaSection.
This diagram shows the component tree for the homepage.
Sources: app/page.tsx:21-78
Similarly, the root layout (app/layout.tsx) establishes the global page structure by wrapping all page content (children) with the <Header /> and <Footer /> components, ensuring a consistent look and feel across the entire site.
Sources: app/layout.tsx:103-105
Component Types
Components can be categorized into several distinct types based on their function and level of abstraction.
Layout Components
These components define the persistent structure of the application.
Header: The main site navigation, present on all pages.Footer: The site footer, containing navigation links, contact information, and legal notices. It is used in the root layout.Section&Container: Primitive components used to enforce consistent spacing and content width for all major page sections.
Sources: app/layout.tsx:103-105, components/footer.tsx, components/contact-form.tsx:14
Page Section Components
These are high-level, self-contained components that represent a full content block on a page. They are highly configurable through props.
Hero/HeroPlatform: Displays the main title, subtitle, and call-to-action at the top of a page.AlternatingContent: Renders a series of sections with text and images in an alternating layout.MarketplaceOverview: A complex component showcasing features in a circular diagram, with lists and cards.CtaSection: A call-to-action block, typically used at the bottom of a page.ProofPoints: Displays key statistics and customer testimonials.
Sources: app/page.tsx, app/product/page.tsx, components/proof-points.tsx, components/marketplace-overview.tsx
Primitive Components
These are the fundamental building blocks for the UI, found within components/primitives/. They are used to build more complex components.
| Component | Description | Example Usage |
|---|---|---|
Button | A styled button element. | components/contact-form.tsx:226 |
Input | A styled text input field with error handling. | components/contact-form.tsx:121 |
Select | A styled dropdown select element. | components/contact-form.tsx:184 |
Textarea | A styled multi-line text area. | components/contact-form.tsx:203 |
Section | A layout wrapper for consistent vertical spacing. | components/contact-form.tsx:112 |
Container | A layout wrapper for centered, max-width content. | components/contact-form.tsx:113 |
Sources: components/contact-form.tsx
Specialized Components
These components provide specific functionality that is not purely presentational.
Icon: A dynamic icon loader that renders icons from thelucide-reactlibrary by name. This avoids importing every icon individually.
Sources: README.md, components/marketplace-overview.tsx:10JsonLd: Injects JSON-LD structured data into the page's<head>for SEO purposes. It takes adataprop containing a schema object generated by helper functions inlib/seo.ts.
Sources: app/about/page.tsx:19-20, lib/seo.tsAnimateOnScroll: A wrapper component that uses Framer Motion to apply animations to its children when they scroll into view.
Sources: components/contact-form.tsx:115, package.json:15
Icon Component Props
The Icon component is configured via several props as detailed in the README.md.
| Prop | Type | Description |
|---|---|---|
name | IconName | The kebab-case name of the Lucide icon (required). |
size | number | Icon size in pixels. |
className | string | Tailwind/CSS classes for styling. |
strokeWidth | number | Stroke width (default: 2). |
Sources: README.md
State Management and Interactivity
For components requiring interactivity, such as forms, state is managed locally using React's useState hook. The ContactForm component is a prime example of this approach.
The component manages the following state variables:
formData: An object holding the values of all form fields.errors: An object to store validation errors for each field.charCount: Tracks the number of characters in the message textarea.isSubmitted: A boolean flag to show a success message.isLoading: A boolean flag to show a loading state during form submission.
Sources: components/contact-form.tsx:23-39
The form submission process involves client-side validation, an asynchronous API call to a /api/contact endpoint, and UI updates based on the outcome.
This sequence diagram shows the flow of a successful contact form submission.
Sources: components/contact-form.tsx:81-110
Styling and Theming
The project uses Tailwind CSS for its utility-first styling approach. A consistent theme is established in app/globals.css using CSS variables within a @theme block. This allows for centralized control over brand colors, fonts, and spacing.
Sources: package.json:28, app/globals.css:3-43
Key brand colors are defined as CSS variables:
| Variable | Value | Description |
|---|---|---|
--color-primary | #1980ef | Main brand blue. |
--color-navy | #0c0e2d | Dark background color. |
--color-body | #5c6876 | Default text color. |
--color-light | #f3f7fc | Light background accent. |
Sources: app/globals.css:5-12
The custom font "Ambit" is configured in app/layout.tsx and applied globally via the --font-sans CSS variable. The application also uses clsx and tailwind-merge to conditionally apply and merge Tailwind classes without conflicts, which is a common pattern for creating robust, reusable components.
Sources: app/layout.tsx:7-60, package.json:14,19, components/contact-form.tsx:8,187