Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/shoploop-studio-site/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
.next
qa*.png
59 changes: 59 additions & 0 deletions apps/shoploop-studio-site/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# shoploop.studio (v0 landing)

The OSS marketing site — first of three reference sites (see `POSITIONING.md` at repo root).

## Positioning

**Full-funnel positionless AI marketing for tabletop pharma products — Ayurveda-first.**

The moat (verbatim, matches POSITIONING.md):

> Vagon.io + grip.tools + Postiz + PostHog + Google Ads feedback + NVIDIA Omniverse + Blender with materials — Hindi/Marathi/English support — targeting Ayurvedic tabletop category.

## Stack

- Next.js 15 (static export) · TypeScript · Tailwind CSS
- React Three Fiber + drei for the 9-component moat orbit + molecular atlas
- Framer Motion for scroll reveals
- Google Fonts `<link>` (Noto Serif Devanagari + IBM Plex Serif + IBM Plex Sans). `next/font/google` was intentionally not used — it breaks under the relative `assetPrefix` we need for nested-path hosting.
- Trilingual hi/en/mr toggle on the H1 + primary CTA only; other sections default English for v0.

## Local dev

```bash
pnpm install
pnpm dev
```

## Build (static export)

```bash
pnpm build
# Output in ./out
```

## A2UI ships

- `public/llms.txt`
- `public/sitemap.xml`
- `public/robots.txt`
- `public/.well-known/a2ui.json`
- JSON-LD WebPage + Product + 3 Offer schema in `<head>`
- `data-a2ui-action` on every interactive element

## Known deviations (documented for the record)

1. **Wishlist is in-memory only.** Preview iframes block `localStorage`; a marked swap point exists to switch back once we're on a proper domain.
2. **Fonts via `<link>` not `next/font/google`.** Reason above; same three families load.
3. **No real Nango / Postiz / PostHog wiring.** Mocks only; buttons show toasts. Real integration lands with `apps/studio` and `apps/ashwagandha` (separate PRs).

## Deploy target

Static export lives at `./out`. Deployable to:
- Vercel (primary; requires domain configured separately)
- Cloudflare Pages
- Any static host

## Design-partner boundary

No references to Sandu Pharmaceuticals anywhere. This is Shoploop's own reference implementation, not any partner's site.
78 changes: 78 additions & 0 deletions apps/shoploop-studio-site/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
--font-deva: 'Noto Serif Devanagari', serif;
--font-display: 'IBM Plex Serif', Georgia, serif;
--font-body: 'IBM Plex Sans', system-ui, sans-serif;
--ease: cubic-bezier(0.22, 1, 0.36, 1);
}

html {
scroll-behavior: smooth;
background: #0b2523;
}

body {
background: #0b2523;
color: #f7f2e7;
font-family: var(--font-body);
-webkit-font-smoothing: antialiased;
overflow-x: hidden;
}

::selection {
background: #e8a33d;
color: #0b2523;
}

*:focus-visible {
outline: 2px solid #e8a33d;
outline-offset: 3px;
border-radius: 2px;
}

.sec-label {
font-family: ui-monospace, SFMono-Regular, monospace;
font-size: 0.7rem;
letter-spacing: 0.22em;
text-transform: uppercase;
color: #e8a33d;
}

.grain::before {
content: '';
position: absolute;
inset: 0;
pointer-events: none;
opacity: 0.05;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E");
}

.hairline {
border-color: rgba(247, 242, 231, 0.12);
}

@keyframes marquee {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
.marquee-track {
animation: marquee 38s linear infinite;
}
.marquee-track:hover { animation-play-state: paused; }

@keyframes dashflow {
to { stroke-dashoffset: -1000; }
}

@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
.marquee-track { animation: none; }
*, *::before, *::after {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
}
}
111 changes: 111 additions & 0 deletions apps/shoploop-studio-site/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import type { Metadata } from 'next';
import './globals.css';


export const metadata: Metadata = {
title: 'Shoploop — Full-funnel positionless AI marketing for tabletop pharma',
description:
'Full-funnel positionless AI marketing for tabletop pharma products — Ayurveda-first. $0 OSS forever, $0 trial 30 days, $299/mo managed. AGPL-3.0.',
metadataBase: new URL('https://shoploop.studio'),
openGraph: {
title: 'Shoploop',
description:
'Full-funnel positionless AI marketing for tabletop pharma products — Ayurveda-first.',
type: 'website',
},
};

const jsonLd = {
'@context': 'https://schema.org',
'@graph': [
{
'@type': 'WebPage',
'@id': 'https://shoploop.studio/#webpage',
name: 'Shoploop — Full-funnel positionless AI marketing for tabletop pharma',
description:
'Full-funnel positionless AI marketing for tabletop pharma products — Ayurveda-first.',
inLanguage: ['en', 'hi', 'mr'],
mainEntity: { '@id': 'https://shoploop.studio/#product' },
potentialAction: [
{
'@type': 'Action',
name: 'preview-embed',
target: 'https://shoploop.studio/#hero',
},
{
'@type': 'Action',
name: 'join-wishlist',
target: 'https://shoploop.studio/#wishlist',
},
],
},
{
'@type': 'Product',
'@id': 'https://shoploop.studio/#product',
name: 'Shoploop',
description:
'Positionless AI marketing loop for tabletop pharma: connect, read, mutate, render, publish, update, measure, compound.',
brand: { '@type': 'Brand', name: 'Shoploop' },
license: 'https://www.gnu.org/licenses/agpl-3.0.html',
offers: [
{
'@type': 'Offer',
'@id': 'https://shoploop.studio/#offer-oss',
name: 'OSS',
price: '0',
priceCurrency: 'USD',
description: 'Self-host AGPL-3.0. Everything above, in your infra.',
availability: 'https://schema.org/InStock',
url: 'https://github.com/ninan-versioning/shoploop',
},
{
'@type': 'Offer',
'@id': 'https://shoploop.studio/#offer-trial',
name: 'Trial',
price: '0',
priceCurrency: 'USD',
description: 'Managed hosting for 30 days. No card required. Full features.',
availability: 'https://schema.org/PreOrder',
},
{
'@type': 'Offer',
'@id': 'https://shoploop.studio/#offer-managed',
name: 'Managed',
price: '299',
priceCurrency: 'USD',
description:
'Hosted embed CDN + Nango + Studio + Postiz + 10 loops on your data.',
availability: 'https://schema.org/InStock',
priceSpecification: {
'@type': 'UnitPriceSpecification',
price: '299',
priceCurrency: 'USD',
billingDuration: 1,
billingIncrement: 1,
unitCode: 'MON',
},
},
],
},
],
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600&family=IBM+Plex+Serif:ital,wght@0,400;0,500;0,600;1,400&family=Noto+Serif+Devanagari:wght@400;600;700&display=swap"
/>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
</head>
<body>{children}</body>
</html>
);
}
Loading
Loading