npm package: @parallaxis-innovations/storesprint
Description: StoreSprint by Parallaxis: Ship a Shopify storefront in ~1 hour with JSON pages, shortcodes, component showcase, and production SEO.
Latest version: 0.2.1

# StoreSprint by Parallaxis

Ship a Shopify storefront in ~1 hour. A batteries‑included Next.js + Shopify toolkit with zero‑code JSON pages, shortcodes, component showcase, and production‑grade SEO.

## Project Overview

This platform helps you build multiple storefronts from a single codebase, where each storefront can focus on a specific Shopify collection. Perfect for brands with distinct product lines, seasonal collections, or targeted marketing campaigns.

**What makes this special?**
- **Config-driven architecture** using `website.config.ts` - change your entire site without touching component code
- **Collection-focused storefronts** - each deployment can target a specific Shopify collection
- **Modular component system** - reusable UI components with multiple variants
- **Theme switching** - different visual styles using CSS variables
- **SEO-optimized** with automatic JSON-LD schema generation

**Technologies used:**
- Next.js 15+ with App Router
- TypeScript for type safety
- Tailwind CSS for styling
- shadcn/ui component library
- Shopify Storefront API for data
- Vercel/Netlify ready deployment

The entire page structure, theming, and content is controlled through `website.config.ts`, making it incredibly easy to create new storefronts or rebrand existing ones.

## Getting Started

### Prerequisites
- Node.js 18+ installed
- A Shopify store with products and collections
- Shopify Storefront API access token

### Quick Setup (CLI)

1. **Clone and install:**
   ```bash
   npx @parallaxis-innovations/storesprint create --dir ./my-store
   cd my-store
   npm install
   ```

2. **Environment setup:**
   Create a `.env.local` file in the root directory:
   ```env
   # Required: Your Shopify store domain (without https://)
   NEXT_PUBLIC_DOMAIN_NAME=your-store.myshopify.com
   
   # Required: Shopify Storefront Access Token
   NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN=your_storefront_access_token_here
   
   # Optional: API version
    NEXT_PUBLIC_SHOPIFY_API_VERSION=2025-07
    NEXT_PUBLIC_SITE_URL=http://localhost:3000
   
   # Collection-specific storefront (leave empty for general store)
   NEXT_PUBLIC_COLLECTION_HANDLE=summer-collection
   NEXT_PUBLIC_COLLECTION_ID=gid://shopify/Collection/123456789
   
   # Storefront branding
   NEXT_PUBLIC_STOREFRONT_NAME=Summer Store
   NEXT_PUBLIC_STOREFRONT_BRAND_COLOR=#ff6b6b
   ```

3. **Run the development server:**
   ```bash
    npm run dev
   ```

4. **Visit your storefront:**
   Open [http://localhost:3000](http://localhost:3000) to see your store in action!

## Shopify Admin Setup

### Setting Up Your Store

1. **Create collections in Shopify Admin:**
   - Go to Products > Collections
   - Click "Create collection"
   - Add a descriptive title and handle (e.g., "summer-collection")
   - Set collection type (Manual or Automated)

2. **Assign products to collections:**
   - For manual collections: Add products individually
   - For automated collections: Set conditions (tags, price, etc.)

3. **Get your Storefront Access Token:**
   - Go to Apps > App and sales channel settings
   - Click "Develop apps"
   - Create a new app or select existing one
   - Configure Storefront API access with these permissions:
     - Read products
     - Read collections
     - Read customer tags
     - Read inventory
   - Generate and copy the Storefront access token

4. **Find collection handles and IDs:**
   - In your collection settings, the handle is shown in the URL field
   - Or check the collection URL: `your-store.com/collections/[handle]`
   - Use this handle in your `NEXT_PUBLIC_COLLECTION_HANDLE` environment variable

5. **Get your Collection ID (Required):**
   - In Shopify Admin, go to your collection
   - Copy the collection ID from the URL (the number after `/collections/`)
   - Format it as: `gid://shopify/Collection/[ID_NUMBER]`
   - Example: If URL shows `/collections/123456789`, use `gid://shopify/Collection/123456789`
   - Add this to your `NEXT_PUBLIC_COLLECTION_ID` environment variable

### Required Permissions
Your Shopify app needs these Storefront API permissions:
- `unauthenticated_read_product_listings`
- `unauthenticated_read_product_inventory`
- `unauthenticated_read_product_tags`
- `unauthenticated_read_collection_listings`

## Creating a New Storefront (Collection-Based)

### The Collection-First Approach

Each storefront deployment can focus on a specific collection, giving you incredible flexibility:

**Example use cases:**
- **Seasonal stores**: Summer collection, Winter collection, Holiday specials
- **Brand lines**: Premium products, Budget-friendly items, New arrivals
- **Target audiences**: Kids products, Professional tools, Home essentials

### Setting Up a Collection Storefront

1. **Choose your collection:**
   Update your `.env.local`:
   ```env
   NEXT_PUBLIC_COLLECTION_HANDLE=winter-essentials
   NEXT_PUBLIC_STOREFRONT_NAME=Winter Essentials Store
   NEXT_PUBLIC_STOREFRONT_BRAND_COLOR=#2563eb
   ```

2. **Customize the config:**
   Edit `website.config.ts` to match your collection's theme:
   ```typescript
   export const websiteConfig: WebsiteConfig = {
     name: "Winter Essentials",
     theme: {
       colors: {
         primary: "#2563eb",    // Winter blue
         accent: "#f1f5f9",     // Light snow
         // ... more colors
       }
     },
     pages: {
       home: {
         sections: [
           {
             component: "hero-section",
             props: {
               title: "Stay Warm This Winter",
               backgroundImage: "/images/winter-hero.jpg",
               // ... more props
             }
           }
         ]
       }
     }
   }
   ```

3. **Deploy with different configs:**
   For multiple storefronts, you can:
   - Deploy to different domains with different environment variables
   - Use branch-based deployments (each branch = different collection/store)
   - Create multiple Vercel/Netlify projects

### Building Different UIs

The beauty of this system is that you can create completely different experiences:

**Option 1: Environment-based theming:**
```env
# .env.local for luxury storefront
NEXT_PUBLIC_STOREFRONT_NAME=Luxury Collection
NEXT_PUBLIC_STOREFRONT_BRAND_COLOR=#d4af37
```

**Option 2: Config-based layouts:**
```typescript
// Different hero sections for different collections
const luxuryHero = {
  component: "hero-section",
  props: {
    title: "Luxury Redefined",
    className: "min-h-screen bg-gradient-to-r from-amber-50 to-amber-100"
  }
}

const casualHero = {
  component: "hero-section", 
  props: {
    title: "Everyday Comfort",
    className: "min-h-96 bg-blue-50"
  }
}
```

## Component System

### How Components Are Organized

Components live in `/components/library/` following this structure:
```
components/library/
├── HeroBanner/
│   ├── Variant1.tsx    # Minimal hero
│   ├── Variant2.tsx    # With background image
│   └── Variant3.tsx    # Video background
├── ProductCard/
│   ├── Variant1.tsx    # Basic card
│   ├── Variant2.tsx    # With quick actions
│   └── Variant3.tsx    # Detailed card
└── TestimonialSection/
    ├── Variant1.tsx    # Single testimonial
    ├── Variant2.tsx    # Carousel
    └── Variant3.tsx    # Grid layout
```

### Using Components in Config

Reference components in your `website.config.ts`:
```typescript
sections: [
  {
    id: "hero",
    component: "hero-section",     // Maps to HeroBanner/Variant1
    props: {
      title: "Welcome to Our Store",
      subtitle: "Find amazing products",
      ctaText: "Shop Now",
      backgroundImage: "/hero-bg.jpg"
    }
  },
  {
    id: "testimonials", 
    component: "testimonial-section-variant2",  // Maps to TestimonialSection/Variant2
    props: {
      testimonials: [
        { name: "John Doe", text: "Amazing products!" },
        // ... more testimonials
      ]
    }
  }
]
```

### Component Showcase

Visit `/component-showcase` to see all available components and their variants. This page helps you:
- Preview components with sample data
- Copy component names for your config
- See all available props for each variant
- Test responsive behavior

### Adding New Component Variants

1. **Create the component file:**
   ```typescript
   // components/library/ProductCard/Variant4.tsx
   interface ProductCardVariant4Props {
     product: {
       title: string;
       price: string;
       image: string;
     };
     showReviews?: boolean;
   }
   
   export default function ProductCardVariant4({ product, showReviews }: ProductCardVariant4Props) {
     return (
       <div className="border rounded-lg p-4">
         {/* Your component JSX */}
       </div>
     );
   }
   ```

2. **Register in the showcase:**
   Add to `/lib/component-showcase-registry.ts`:
   ```typescript
   {
     name: "ProductCard",
     category: "E-commerce",
     variants: [
       // ... existing variants
       {
         name: "Variant4",
         description: "Product card with reviews"
       }
     ],
     previewProps: {
       product: {
         title: "Sample Product",
         price: "$99.99",
         image: "https://via.placeholder.com/300"
       },
       showReviews: true
     }
   }
   ```

## Configuration-Driven Pages

### The Power of website.config.ts

The entire site structure is defined in one file. Here's how it works:

**Page definition:**
```typescript
pages: {
  home: {
    title: "Welcome to Our Store",
    route: "/",
    seo: {
      title: "Home - Amazing Store",
      description: "Shop the best products online",
      schema: "WebSite",
      keywords: ["ecommerce", "shopping", "products"]
    },
    sections: [
      {
        id: "hero",
        component: "hero-section",
        props: {
          title: "Welcome to Our Amazing Store",
          subtitle: "Discover products that will change your life"
        }
      },
      {
        id: "featured-products",
        component: "product-grid-section",
        dataBinding: {
          products: "featuredProducts"  // Pulls from Shopify
        }
      }
    ]
  }
}
```

### SEO Automation

SEO is handled automatically through the config:

**Basic SEO:**
```typescript
seo: {
  title: "Summer Collection - Beach Essentials",
  description: "Find the perfect summer gear for your beach adventures",
  keywords: ["summer", "beach", "swimwear", "vacation"],
  openGraph: {
    title: "Summer Collection",
    description: "Beach essentials for your perfect vacation",
    image: "/images/summer-og.jpg"
  }
}
```

**JSON-LD Schema:**
The system automatically generates structured data:
```typescript
seoGenerator: {
  type: "Product",
  data: {
    name: "Summer Collection",
    description: "Beach essentials...",
    brand: "Your Store",
    offers: {
      priceCurrency: "USD",
      availability: "InStock"
    }
  }
}
```

### Dynamic Data Binding

Connect your sections to Shopify data:
```typescript
{
  component: "product-grid-section",
  dataBinding: {
    products: "featuredProducts",     // Auto-fetches from Shopify
    collections: "allCollections"    // Auto-fetches collections
  },
  props: {
    title: "Featured Products",
    columns: 4
  }
}
```

## Theming

### CSS Variables Approach

Themes are defined using CSS custom properties:

```typescript
// website.config.ts
theme: {
  name: "modern",
  colors: {
    primary: "#3b82f6",      // Becomes --color-primary
    secondary: "#64748b",    // Becomes --color-secondary
    background: "#ffffff",   // Becomes --color-background
    text: "#1f2937",        // Becomes --color-text
    accent: "#f59e0b",      // Becomes --color-accent
  },
  spacing: {
    xs: "0.25rem",          // Becomes --spacing-xs
    sm: "0.5rem",           // Becomes --spacing-sm
    // ... more spacing
  }
}
```

### Using Theme Variables

In your Tailwind classes and custom CSS:
```css
/* Automatically available as CSS variables */
.hero-section {
  background-color: var(--color-primary);
  color: var(--color-text);
  padding: var(--spacing-xl);
}
```

```jsx
// In Tailwind (after configuring theme in tailwind.config.ts)
<div className="bg-primary text-primary-foreground p-xl">
  Content using theme colors
</div>
```

### Environment-Based Theming

Switch themes based on environment:
```typescript
// lib/storefront-config.ts
const getThemeColors = () => {
  const brandColor = process.env.NEXT_PUBLIC_STOREFRONT_BRAND_COLOR;
  
  if (brandColor === '#ff6b6b') {
    return {
      primary: '#ff6b6b',
      secondary: '#ffeaa7',
      accent: '#fd79a8'
    };
  }
  
  return defaultColors;
}
```

## Contributing

We love contributions! Here's how to get involved:

### Opening Issues

Before opening an issue, please:
1. Check existing issues to avoid duplicates
2. Use our issue templates
3. Provide clear reproduction steps
4. Include environment details (Node version, browser, etc.)

### Pull Requests

1. **Fork the repository**
2. **Create a feature branch:**
   ```bash
   git checkout -b feature/amazing-new-component
   ```
3. **Follow our coding standards:**
   - Use TypeScript for all new code
   - Follow existing naming conventions
   - Add JSDoc comments for public APIs
   - Test your changes thoroughly

4. **Component contributions:**
   When adding new components:
   ```typescript
   // Always include proper TypeScript interfaces
   interface ComponentProps {
     title: string;
     description?: string;
     className?: string;
   }
   
   // Add JSDoc documentation
   /**
    * A reusable component for displaying product information
    * @param title - The product title
    * @param description - Optional product description
    * @param className - Additional CSS classes
    */
   export default function Component({ title, description, className }: ComponentProps) {
     // Component implementation
   }
   ```

5. **Update documentation:**
   - Add component to showcase registry
   - Update README if needed
   - Include usage examples

### Code Standards

- **File naming**: Use PascalCase for components, kebab-case for utils
- **Import order**: External packages → internal modules → relative imports
- **CSS**: Use Tailwind classes, avoid custom CSS unless necessary
- **TypeScript**: Prefer interfaces over types, use proper generics

### Adding New Sections

1. **Create the component:**
   ```bash
   mkdir components/library/YourComponent
   touch components/library/YourComponent/Variant1.tsx
   ```

2. **Register in showcase:**
   Add to `lib/component-showcase-registry.ts`

3. **Update types:**
   Add to `types/website-config.ts` if needed

4. **Document usage:**
   Add examples to README or component comments

## Deployment

### Vercel (Recommended)

1. **Connect repository:**
   - Go to Vercel dashboard
   - Click "New Project"
   - Import your repository

2. **Configure environment variables:**
   ```
   NEXT_PUBLIC_DOMAIN_NAME=your-store.myshopify.com
   NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN=your_token
   NEXT_PUBLIC_COLLECTION_HANDLE=your-collection
   NEXT_PUBLIC_STOREFRONT_NAME=Your Store Name
   NEXT_PUBLIC_STOREFRONT_BRAND_COLOR=#your-color
   ```

3. **Deploy:**
   - Automatic deployment on git push
   - Preview deployments for PRs
   - Production deployment from your created branch

### Netlify

1. **Build settings:**
   ```
   Build command: npm run build
   Publish directory: .next
   ```

2. **Environment variables:**
   Same as Vercel, add in Netlify dashboard

### Multiple Storefronts

Deploy multiple storefronts from the same codebase:

**Strategy 1: Branch-based deployment**
```bash
# Create collection-specific branches
git checkout -b summer-collection
# Update config and environment for summer theme
git push origin summer-collection
# Deploy summer-collection branch to summer.yourstore.com
```

**Strategy 2: Multiple Vercel projects**
- Create separate Vercel projects
- Each with different environment variables
- All pointing to the same repository

**Strategy 3: Subdomain deployment**
```
main.yourstore.com     (general store)
summer.yourstore.com   (summer collection)
winter.yourstore.com   (winter collection)
```

## FAQ

### Common Issues

**Q: Components not loading in showcase**
A: Check that your component exports are default exports and file names match the registry.

**Q: Shopify data not showing**
A: Verify your Storefront API token has the correct permissions and your collection handle exists.

**Q: Styles not applying**
A: Ensure Tailwind is properly configured and CSS variables are defined in your theme config.

**Q: Environment variables not working**
A: Remember to restart your development server after changing `.env.local` files.

### Debugging Shopify Data

1. **Check API responses:**
   ```typescript
   // Add this to any page to debug
   console.log('Collection data:', await getCollections());
   console.log('Products:', await getFeaturedProducts());
   ```

2. **Verify collection exists:**
   - Check collection handle in Shopify admin
   - Ensure collection has products
   - Verify collection is published

3. **API token troubleshooting:**
   - Token must have Storefront API access
   - Check token permissions in Shopify admin
   - Ensure token hasn't expired

### Handling Empty Collections

```typescript
// In your page components
async function ProductSection() {
  const { products } = await getFeaturedProducts();
  
  if (products.length === 0) {
    return (
      <div className="text-center py-16">
        <h2>No products found</h2>
        <p>Check back soon for new arrivals!</p>
      </div>
    );
  }
  
  return <ProductGrid products={products} />;
}
```

### Performance Optimization

- Use Next.js Image component for all images
- Implement proper loading states
- Cache Shopify API responses
- Use static generation where possible

## License

MIT License - feel free to use this project for personal or commercial purposes.

---

**Questions?** Open an issue or start a discussion. We're here to help you build amazing storefronts!