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
4 changes: 4 additions & 0 deletions templates/ecommerce/nextjs-monolith/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"root": true,
"extends": "next/core-web-vitals"
}
59 changes: 59 additions & 0 deletions templates/ecommerce/nextjs-monolith/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

/* ===== Base Theme: Minimal Clean (Default) ===== */
:root {
--bg-color: #ffffff;
--bg-secondary: #f9fafb;
--text-color: #111827;
--text-secondary: #6b7280;
--primary: #2563eb;
--primary-hover: #1d4ed8;
--border-color: #e5e7eb;
--card-bg: #ffffff;
--font-family: 'Inter', system-ui, sans-serif;
--radius: 0.5rem;
}

/* ===== Glassmorphism Theme ===== */
[data-theme="Glassmorphism"] {
--bg-color: #0f172a;
--bg-secondary: rgba(255, 255, 255, 0.05);
--text-color: #f1f5f9;
--text-secondary: #94a3b8;
--primary: #8b5cf6;
--primary-hover: #7c3aed;
--border-color: rgba(255, 255, 255, 0.1);
--card-bg: rgba(255, 255, 255, 0.08);
--font-family: 'Inter', system-ui, sans-serif;
--radius: 1rem;
}

[data-theme="Glassmorphism"] .glass {
background: rgba(255, 255, 255, 0.08);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.1);
}

/* ===== Dark Terminal Theme ===== */
[data-theme="Dark Terminal"] {
--bg-color: #000000;
--bg-secondary: #0a0a0a;
--text-color: #3fb950;
--text-secondary: #8b949e;
--primary: #3fb950;
--primary-hover: #2ea043;
--border-color: #21262d;
--card-bg: #0d1117;
--font-family: 'JetBrains Mono', 'Fira Code', monospace;
--radius: 0.25rem;
}

/* ===== Apply variables globally ===== */
body {
background-color: var(--bg-color);
color: var(--text-color);
font-family: var(--font-family);
}
89 changes: 89 additions & 0 deletions templates/ecommerce/nextjs-monolith/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import type { Metadata } from 'next';
import Link from 'next/link';
import './globals.css';

export const metadata: Metadata = {
title: '{{projectName}} - Store',
description: 'A {{variant}} e-commerce store built with Opusify CLI.',
};

const navLinks = [
{ label: 'Home', href: '/' },
{ label: 'Products', href: '/products' },
{ label: 'Cart', href: '/cart' },
{ label: 'Account', href: '/account' },
];

function Navbar() {
return (
<header className="border-b border-border bg-card">
<nav className="max-w-7xl mx-auto px-6 h-16 flex items-center justify-between">
<Link href="/" className="text-xl font-bold text-primary">
{{projectName}}
</Link>
<ul className="flex gap-6">
{navLinks.map((link) => (
<li key={link.href}>
<Link
href={link.href}
className="text-text-secondary hover:text-foreground transition"
>
{link.label}
</Link>
</li>
))}
</ul>
</nav>
</header>
);
}

function Sidebar() {
return (
<aside className="w-64 border-r border-border bg-card min-h-screen p-6">
<Link href="/" className="text-xl font-bold text-primary block mb-8">
{{projectName}}
</Link>
<nav>
<ul className="space-y-2">
{navLinks.map((link) => (
<li key={link.href}>
<Link
href={link.href}
className="block px-4 py-2 rounded-theme text-text-secondary hover:bg-bg-secondary hover:text-foreground transition"
>
{link.label}
</Link>
</li>
))}
</ul>
</nav>
</aside>
);
}

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const useSidebar = '{{includeSidebar}}' === 'true';

return (
<html lang="en" data-theme="{{design}}">
<body>
{useSidebar ? (
<div className="flex">
<Sidebar />
<main className="flex-1">{children}</main>
</div>
) : (
<>
<Navbar />
<main>{children}</main>
</>
)}
</body>
</html>
);
}
45 changes: 45 additions & 0 deletions templates/ecommerce/nextjs-monolith/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import Link from 'next/link';

export default function Home() {
return (
<div className="min-h-screen bg-background">
{/* Hero Section */}
<section className="max-w-7xl mx-auto px-6 py-24 text-center">
<h1 className="text-5xl font-bold tracking-tight text-foreground">
Welcome to <span className="text-primary">{{projectName}}</span>
</h1>
<p className="mt-4 text-xl text-text-secondary max-w-2xl mx-auto">
Your <strong>{{variant}}</strong> store, powered by Next.js 14 and scaffolded by Opusify CLI.
</p>
<div className="mt-8 flex gap-4 justify-center">
<Link
href="/products"
className="rounded-theme bg-primary px-8 py-3 text-white font-medium hover:bg-primary-hover transition"
>
Browse Products
</Link>
<Link
href="/cart"
className="rounded-theme border border-border px-8 py-3 font-medium text-foreground hover:bg-bg-secondary transition"
>
View Cart
</Link>
</div>
</section>

{/* Featured Section */}
<section className="max-w-7xl mx-auto px-6 py-16">
<h2 className="text-2xl font-bold text-foreground mb-8">Featured Products</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{[1, 2, 3].map((i) => (
<div key={i} className="border border-border rounded-theme p-6 bg-card hover:shadow-lg transition">
<div className="h-48 bg-bg-secondary rounded-theme mb-4" />
<h3 className="font-semibold text-foreground">Product {i}</h3>
<p className="text-text-secondary mt-1">$29.99</p>
</div>
))}
</div>
</section>
</div>
);
}
38 changes: 38 additions & 0 deletions templates/ecommerce/nextjs-monolith/app/products/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Link from 'next/link';

export default function ProductDetailPage({
params,
}: {
params: { slug: string };
}) {
return (
<div className="max-w-4xl mx-auto px-6 py-12">
<Link
href="/products"
className="text-primary hover:underline mb-6 inline-block"
>
&larr; Back to Products
</Link>

<div className="grid grid-cols-1 md:grid-cols-2 gap-12 mt-6">
{/* Product Image Placeholder */}
<div className="h-96 bg-bg-secondary rounded-theme" />

{/* Product Info */}
<div>
<h1 className="text-3xl font-bold text-foreground capitalize">
{params.slug.replace(/-/g, ' ')}
</h1>
<p className="text-2xl text-primary font-bold mt-4">$99.99</p>
<p className="text-text-secondary mt-4 leading-relaxed">
This is a placeholder product page for <strong>{params.slug}</strong>.
When connected to a CMS or database, this page will display real product data.
</p>
<button className="mt-8 w-full rounded-theme bg-primary px-6 py-3 text-white font-medium hover:bg-primary-hover transition">
Add to Cart
</button>
</div>
</div>
</div>
);
}
31 changes: 31 additions & 0 deletions templates/ecommerce/nextjs-monolith/app/products/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Link from 'next/link';

const products = [
{ slug: 'product-1', name: 'Classic T-Shirt', price: '$29.99' },
{ slug: 'product-2', name: 'Denim Jacket', price: '$89.99' },
{ slug: 'product-3', name: 'Running Shoes', price: '$119.99' },
{ slug: 'product-4', name: 'Leather Bag', price: '$149.99' },
{ slug: 'product-5', name: 'Sunglasses', price: '$59.99' },
{ slug: 'product-6', name: 'Watch', price: '$199.99' },
];

export default function ProductsPage() {
return (
<div className="max-w-7xl mx-auto px-6 py-12">
<h1 className="text-3xl font-bold text-foreground mb-8">All Products</h1>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{products.map((product) => (
<Link
key={product.slug}
href={`/products/${product.slug}`}
className="border border-border rounded-theme p-6 bg-card hover:shadow-lg transition block"
>
<div className="h-48 bg-bg-secondary rounded-theme mb-4" />
<h2 className="font-semibold text-foreground">{product.name}</h2>
<p className="text-primary font-bold mt-1">{product.price}</p>
</Link>
))}
</div>
</div>
);
}
4 changes: 4 additions & 0 deletions templates/ecommerce/nextjs-monolith/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};

module.exports = nextConfig;
27 changes: 27 additions & 0 deletions templates/ecommerce/nextjs-monolith/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "{{projectName}}",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"next": "14.2.3",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/node": "^20.12.0",
"@types/react": "^18.3.0",
"@types/react-dom": "^18.3.0",
"autoprefixer": "^10.4.19",
"eslint": "^8.57.0",
"eslint-config-next": "14.2.3",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.3",
"typescript": "^5.4.5"
}
}
6 changes: 6 additions & 0 deletions templates/ecommerce/nextjs-monolith/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
31 changes: 31 additions & 0 deletions templates/ecommerce/nextjs-monolith/tailwind.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Config } from 'tailwindcss';

const config: Config = {
content: [
'./app/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
],
theme: {
extend: {
colors: {
background: 'var(--bg-color)',
'bg-secondary': 'var(--bg-secondary)',
foreground: 'var(--text-color)',
'text-secondary': 'var(--text-secondary)',
primary: 'var(--primary)',
'primary-hover': 'var(--primary-hover)',
border: 'var(--border-color)',
card: 'var(--card-bg)',
},
borderRadius: {
theme: 'var(--radius)',
},
fontFamily: {
theme: 'var(--font-family)',
},
},
},
plugins: [],
};

export default config;
26 changes: 26 additions & 0 deletions templates/ecommerce/nextjs-monolith/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
Loading
Loading