diff --git a/templates/blog/nextjs-monolith/.eslintrc.json b/templates/blog/nextjs-monolith/.eslintrc.json
new file mode 100644
index 0000000..a2569c2
--- /dev/null
+++ b/templates/blog/nextjs-monolith/.eslintrc.json
@@ -0,0 +1,4 @@
+{
+ "root": true,
+ "extends": "next/core-web-vitals"
+}
diff --git a/templates/blog/nextjs-monolith/app/articles/page.tsx b/templates/blog/nextjs-monolith/app/articles/page.tsx
new file mode 100644
index 0000000..9e3043f
--- /dev/null
+++ b/templates/blog/nextjs-monolith/app/articles/page.tsx
@@ -0,0 +1,72 @@
+import Link from 'next/link';
+
+export default function ArticlesPage() {
+ const articles = [
+ { slug: 'getting-started-with-nextjs-14', title: 'Getting Started with Next.js 14: A Complete Guide', excerpt: 'Learn how to build modern web applications with Next.js 14 App Router and Server Components.', author: 'Jane Smith', date: 'Jun 15, 2024', readTime: '8 min', category: 'Tutorial' },
+ { slug: 'tailwind-css-best-practices', title: 'Tailwind CSS Best Practices for Large Projects', excerpt: 'Discover patterns and strategies for maintaining clean Tailwind CSS in enterprise applications.', author: 'Alex Chen', date: 'Jun 12, 2024', readTime: '6 min', category: 'CSS' },
+ { slug: 'typescript-generics-explained', title: 'TypeScript Generics Explained Simply', excerpt: 'A practical guide to understanding and using TypeScript generics in your everyday code.', author: 'Maria Garcia', date: 'Jun 10, 2024', readTime: '10 min', category: 'TypeScript' },
+ { slug: 'react-server-components', title: 'Understanding React Server Components', excerpt: 'Deep dive into how React Server Components work and when to use them.', author: 'David Park', date: 'Jun 8, 2024', readTime: '7 min', category: 'React' },
+ { slug: 'building-design-systems', title: 'Building a Design System from Scratch', excerpt: 'Step-by-step guide to creating a cohesive design system for your team.', author: 'Sarah Johnson', date: 'Jun 5, 2024', readTime: '12 min', category: 'Design' },
+ { slug: 'api-design-patterns', title: 'REST API Design Patterns You Should Know', excerpt: 'Essential patterns for building robust and scalable REST APIs.', author: 'James Wilson', date: 'Jun 3, 2024', readTime: '9 min', category: 'Backend' },
+ { slug: 'state-management-2024', title: 'State Management in 2024: What to Use', excerpt: 'Comparing Zustand, Jotai, Redux Toolkit, and React Context for modern apps.', author: 'Emily Rodriguez', date: 'Jun 1, 2024', readTime: '11 min', category: 'React' },
+ { slug: 'web-performance-optimization', title: 'Web Performance Optimization Checklist', excerpt: 'A comprehensive checklist for making your web applications blazing fast.', author: 'Tom Anderson', date: 'May 28, 2024', readTime: '14 min', category: 'Performance' },
+ ];
+
+ const categories = ['All', 'Tutorial', 'React', 'TypeScript', 'CSS', 'Design', 'Backend', 'Performance'];
+
+ return (
+
+
+
+
All Articles
+
Browse our collection of tutorials, guides, and insights
+
+
+ {/* Category Filter */}
+
+ {categories.map((cat, i) => (
+
+ ))}
+
+
+ {/* Articles List */}
+
+ {articles.map((article) => (
+
+
+
+ {article.category}
+
+ {article.readTime} read
+
+
+ {article.title}
+
+
+ {article.excerpt}
+
+
+ {article.author}
+ ·
+ {article.date}
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/templates/blog/nextjs-monolith/app/authors/page.tsx b/templates/blog/nextjs-monolith/app/authors/page.tsx
new file mode 100644
index 0000000..1e9c30a
--- /dev/null
+++ b/templates/blog/nextjs-monolith/app/authors/page.tsx
@@ -0,0 +1,43 @@
+import Link from 'next/link';
+
+export default function AuthorsPage() {
+ const authors = [
+ { slug: 'jane-smith', name: 'Jane Smith', role: 'Senior Frontend Engineer', articles: 12, bio: 'Passionate about React, accessibility, and building great developer experiences.' },
+ { slug: 'alex-chen', name: 'Alex Chen', role: 'Design Engineer', articles: 9, bio: 'Bridging the gap between design and engineering with CSS and design systems.' },
+ { slug: 'maria-garcia', name: 'Maria Garcia', role: 'TypeScript Advocate', articles: 8, bio: 'Making TypeScript approachable for developers of all skill levels.' },
+ { slug: 'david-park', name: 'David Park', role: 'Full-Stack Developer', articles: 7, bio: 'Building scalable applications with Next.js and modern backend technologies.' },
+ { slug: 'sarah-johnson', name: 'Sarah Johnson', role: 'UI/UX Designer', articles: 6, bio: 'Creating beautiful, functional interfaces that users love.' },
+ { slug: 'james-wilson', name: 'James Wilson', role: 'Backend Architect', articles: 5, bio: 'Designing robust APIs and distributed systems at scale.' },
+ ];
+
+ return (
+
+
+
+
Authors
+
Meet the people behind the articles
+
+
+
+ {authors.map((author) => (
+
+
+ {author.name.split(' ').map((n) => n[0]).join('')}
+
+
+ {author.name}
+
+
{author.role}
+
{author.bio}
+
{author.articles} articles published
+
+ ))}
+
+
+
+ );
+}
diff --git a/templates/blog/nextjs-monolith/app/categories/page.tsx b/templates/blog/nextjs-monolith/app/categories/page.tsx
new file mode 100644
index 0000000..26bc28b
--- /dev/null
+++ b/templates/blog/nextjs-monolith/app/categories/page.tsx
@@ -0,0 +1,47 @@
+import Link from 'next/link';
+
+export default function CategoriesPage() {
+ const categories = [
+ { name: 'React', slug: 'react', count: 24, description: 'Components, hooks, patterns, and best practices for React development.' },
+ { name: 'TypeScript', slug: 'typescript', count: 18, description: 'Type safety, generics, utility types, and advanced TypeScript patterns.' },
+ { name: 'Next.js', slug: 'nextjs', count: 15, description: 'App Router, Server Components, API routes, and deployment strategies.' },
+ { name: 'CSS & Design', slug: 'css-design', count: 12, description: 'Tailwind CSS, animations, responsive design, and design systems.' },
+ { name: 'Backend', slug: 'backend', count: 10, description: 'APIs, databases, authentication, and server-side architecture.' },
+ { name: 'DevOps', slug: 'devops', count: 8, description: 'CI/CD, Docker, deployment, monitoring, and infrastructure.' },
+ { name: 'Performance', slug: 'performance', count: 7, description: 'Core Web Vitals, optimization techniques, and benchmarking.' },
+ { name: 'Career', slug: 'career', count: 5, description: 'Job hunting, interviews, growth, and developer life.' },
+ ];
+
+ return (
+
+
+
+
Categories
+
Browse articles by topic
+
+
+
+ {categories.map((category) => (
+
+
+
+ {category.name}
+
+
+ {category.count} articles
+
+
+
+ {category.description}
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/templates/blog/nextjs-monolith/app/globals.css b/templates/blog/nextjs-monolith/app/globals.css
new file mode 100644
index 0000000..283fef5
--- /dev/null
+++ b/templates/blog/nextjs-monolith/app/globals.css
@@ -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);
+}
diff --git a/templates/blog/nextjs-monolith/app/layout.tsx b/templates/blog/nextjs-monolith/app/layout.tsx
new file mode 100644
index 0000000..e3c4d71
--- /dev/null
+++ b/templates/blog/nextjs-monolith/app/layout.tsx
@@ -0,0 +1,122 @@
+import type { Metadata } from 'next';
+import Link from 'next/link';
+import './globals.css';
+import AnimationProvider from '../components/AnimationProvider';
+{{#if (eq design "Dark Terminal")}}
+import { Terminal } from 'lucide-react';
+{{/if}}
+
+export const metadata: Metadata = {
+ title: '{{projectName}} - Blog',
+ description: 'A {{variant}} blog built with Opusify CLI.',
+};
+
+const navLinks = [
+ { label: 'Home', href: '/' },
+ { label: 'Articles', href: '/articles' },
+ { label: 'Categories', href: '/categories' },
+ { label: 'Authors', href: '/authors' },
+];
+
+function Navbar() {
+ return (
+
+
+
+ );
+}
+
+function Sidebar() {
+ return (
+
+ );
+}
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ const useSidebar = '{{includeSidebar}}' === 'true';
+
+ return (
+
+
+ {useSidebar ? (
+
+ ) : (
+ <>
+
+
+
+ {children}
+
+
+ >
+ )}
+
+
+ );
+}
diff --git a/templates/blog/nextjs-monolith/app/page.tsx b/templates/blog/nextjs-monolith/app/page.tsx
new file mode 100644
index 0000000..2d9bbff
--- /dev/null
+++ b/templates/blog/nextjs-monolith/app/page.tsx
@@ -0,0 +1,105 @@
+import Link from 'next/link';
+
+export default function Home() {
+ const featuredPost = {
+ slug: 'getting-started-with-nextjs-14',
+ title: 'Getting Started with Next.js 14: A Complete Guide',
+ excerpt: 'Learn how to build modern web applications with Next.js 14 App Router, Server Components, and the latest React features.',
+ author: 'Jane Smith',
+ date: 'Jun 15, 2024',
+ readTime: '8 min read',
+ category: 'Tutorial',
+ };
+
+ const recentPosts = [
+ { slug: 'tailwind-css-best-practices', title: 'Tailwind CSS Best Practices for Large Projects', author: 'Alex Chen', date: 'Jun 12, 2024', readTime: '6 min', category: 'CSS' },
+ { slug: 'typescript-generics-explained', title: 'TypeScript Generics Explained Simply', author: 'Maria Garcia', date: 'Jun 10, 2024', readTime: '10 min', category: 'TypeScript' },
+ { slug: 'react-server-components', title: 'Understanding React Server Components', author: 'David Park', date: 'Jun 8, 2024', readTime: '7 min', category: 'React' },
+ { slug: 'building-design-systems', title: 'Building a Design System from Scratch', author: 'Sarah Johnson', date: 'Jun 5, 2024', readTime: '12 min', category: 'Design' },
+ { slug: 'api-design-patterns', title: 'REST API Design Patterns You Should Know', author: 'James Wilson', date: 'Jun 3, 2024', readTime: '9 min', category: 'Backend' },
+ { slug: 'state-management-2024', title: 'State Management in 2024: What to Use', author: 'Emily Rodriguez', date: 'Jun 1, 2024', readTime: '11 min', category: 'React' },
+ ];
+
+ return (
+
+ {/* Hero */}
+
+
+ Welcome to {{projectName}}
+
+
+ A {{variant}} publication — stories, tutorials, and insights for developers.
+
+
+
+ {/* Featured Post */}
+
+
+
+ Featured
+
+
+ {featuredPost.title}
+
+
+ {featuredPost.excerpt}
+
+
+ {featuredPost.author}
+ ·
+ {featuredPost.date}
+ ·
+ {featuredPost.readTime}
+
+
+
+
+ {/* Recent Posts */}
+
+ Recent Articles
+
+ {recentPosts.map((post) => (
+
+
+
+ {post.category}
+
+ {post.readTime}
+
+
+ {post.title}
+
+
+ {post.author}
+ ·
+ {post.date}
+
+
+ ))}
+
+
+
+ {/* Newsletter */}
+
+
+
Subscribe to our newsletter
+
Get the latest articles delivered straight to your inbox.
+
+
+
+
+
+
+
+ );
+}
diff --git a/templates/blog/nextjs-monolith/components/AnimationProvider.tsx b/templates/blog/nextjs-monolith/components/AnimationProvider.tsx
new file mode 100644
index 0000000..feaf51c
--- /dev/null
+++ b/templates/blog/nextjs-monolith/components/AnimationProvider.tsx
@@ -0,0 +1,32 @@
+{{#if (eq design "Glassmorphism")}}
+'use client';
+
+import { AnimatePresence, motion } from 'framer-motion';
+
+export default function AnimationProvider({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+
+
+ {children}
+
+
+ );
+}
+{{else}}
+export default function AnimationProvider({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}
+{{/if}}
diff --git a/templates/blog/nextjs-monolith/next.config.js b/templates/blog/nextjs-monolith/next.config.js
new file mode 100644
index 0000000..658404a
--- /dev/null
+++ b/templates/blog/nextjs-monolith/next.config.js
@@ -0,0 +1,4 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {};
+
+module.exports = nextConfig;
diff --git a/templates/blog/nextjs-monolith/package.json b/templates/blog/nextjs-monolith/package.json
new file mode 100644
index 0000000..5dfa145
--- /dev/null
+++ b/templates/blog/nextjs-monolith/package.json
@@ -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"
+ }
+}
diff --git a/templates/blog/nextjs-monolith/postcss.config.js b/templates/blog/nextjs-monolith/postcss.config.js
new file mode 100644
index 0000000..12a703d
--- /dev/null
+++ b/templates/blog/nextjs-monolith/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/templates/blog/nextjs-monolith/tailwind.config.ts b/templates/blog/nextjs-monolith/tailwind.config.ts
new file mode 100644
index 0000000..b2e02d3
--- /dev/null
+++ b/templates/blog/nextjs-monolith/tailwind.config.ts
@@ -0,0 +1,43 @@
+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)',
+ },
+ typography: {
+ DEFAULT: {
+ css: {
+ color: 'var(--text-color)',
+ a: { color: 'var(--primary)' },
+ h1: { color: 'var(--text-color)' },
+ h2: { color: 'var(--text-color)' },
+ h3: { color: 'var(--text-color)' },
+ strong: { color: 'var(--text-color)' },
+ },
+ },
+ },
+ },
+ },
+ plugins: [],
+};
+
+export default config;
diff --git a/templates/blog/nextjs-monolith/tsconfig.json b/templates/blog/nextjs-monolith/tsconfig.json
new file mode 100644
index 0000000..455bf35
--- /dev/null
+++ b/templates/blog/nextjs-monolith/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "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"]
+}
diff --git a/templates/saas/nextjs-monolith/.eslintrc.json b/templates/saas/nextjs-monolith/.eslintrc.json
new file mode 100644
index 0000000..a2569c2
--- /dev/null
+++ b/templates/saas/nextjs-monolith/.eslintrc.json
@@ -0,0 +1,4 @@
+{
+ "root": true,
+ "extends": "next/core-web-vitals"
+}
diff --git a/templates/saas/nextjs-monolith/app/analytics/page.tsx b/templates/saas/nextjs-monolith/app/analytics/page.tsx
new file mode 100644
index 0000000..502bf63
--- /dev/null
+++ b/templates/saas/nextjs-monolith/app/analytics/page.tsx
@@ -0,0 +1,133 @@
+export default function AnalyticsPage() {
+ const trafficSources = [
+ { source: 'Organic Search', visitors: 4521, percentage: 38, color: 'bg-blue-500' },
+ { source: 'Direct', visitors: 2847, percentage: 24, color: 'bg-green-500' },
+ { source: 'Social Media', visitors: 1923, percentage: 16, color: 'bg-purple-500' },
+ { source: 'Referral', visitors: 1456, percentage: 12, color: 'bg-orange-500' },
+ { source: 'Email', visitors: 1100, percentage: 10, color: 'bg-pink-500' },
+ ];
+
+ const pageViews = [
+ { page: '/dashboard', views: 12450, avgTime: '3m 24s', bounceRate: '18%' },
+ { page: '/analytics', views: 8920, avgTime: '5m 12s', bounceRate: '12%' },
+ { page: '/users', views: 6340, avgTime: '2m 48s', bounceRate: '24%' },
+ { page: '/billing', views: 4210, avgTime: '4m 06s', bounceRate: '15%' },
+ { page: '/settings', views: 3180, avgTime: '1m 52s', bounceRate: '32%' },
+ { page: '/integrations', views: 2890, avgTime: '6m 30s', bounceRate: '8%' },
+ ];
+
+ const conversionFunnel = [
+ { stage: 'Visitors', count: 45000, width: '100%' },
+ { stage: 'Sign Ups', count: 12800, width: '72%' },
+ { stage: 'Activated', count: 8400, width: '48%' },
+ { stage: 'Subscribed', count: 3200, width: '28%' },
+ { stage: 'Enterprise', count: 420, width: '12%' },
+ ];
+
+ return (
+
+
+
+
Analytics
+
Deep dive into your platform metrics
+
+
+
+
+
+
+
+
+ {/* Summary Row */}
+
+
+
Total Page Views
+
284,920
+
+18.3% vs last period
+
+
+
Unique Visitors
+
11,847
+
+9.7% vs last period
+
+
+
Conversion Rate
+
7.1%
+
-0.4% vs last period
+
+
+
+
+ {/* Traffic Sources */}
+
+
Traffic Sources
+
+ {trafficSources.map((source) => (
+
+
+ {source.source}
+ {source.visitors.toLocaleString()} ({source.percentage}%)
+
+
+
+ ))}
+
+
+
+ {/* Conversion Funnel */}
+
+
Conversion Funnel
+
+ {conversionFunnel.map((stage) => (
+
+
{stage.stage}
+
+
+ {stage.count.toLocaleString()}
+
+
+
+ ))}
+
+
+
+
+ {/* Top Pages */}
+
+
+
Top Pages
+
+
+
+
+
+ | Page |
+ Views |
+ Avg. Time |
+ Bounce Rate |
+
+
+
+ {pageViews.map((page) => (
+
+ | {page.page} |
+ {page.views.toLocaleString()} |
+ {page.avgTime} |
+ {page.bounceRate} |
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/templates/saas/nextjs-monolith/app/billing/page.tsx b/templates/saas/nextjs-monolith/app/billing/page.tsx
new file mode 100644
index 0000000..b28f88a
--- /dev/null
+++ b/templates/saas/nextjs-monolith/app/billing/page.tsx
@@ -0,0 +1,149 @@
+export default function BillingPage() {
+ const plans = [
+ {
+ name: 'Starter',
+ price: '$29',
+ period: '/month',
+ features: ['Up to 5 users', '10GB storage', 'Basic analytics', 'Email support'],
+ current: false,
+ },
+ {
+ name: 'Pro',
+ price: '$99',
+ period: '/month',
+ features: ['Up to 25 users', '100GB storage', 'Advanced analytics', 'Priority support', 'API access', 'Custom integrations'],
+ current: true,
+ },
+ {
+ name: 'Enterprise',
+ price: '$2,400',
+ period: '/year',
+ features: ['Unlimited users', '1TB storage', 'Full analytics suite', 'Dedicated support', 'SSO & SAML', 'Custom SLA', 'On-premise option'],
+ current: false,
+ },
+ ];
+
+ const invoices = [
+ { id: 'INV-2024-006', date: 'Jun 1, 2024', amount: '$99.00', status: 'Paid' },
+ { id: 'INV-2024-005', date: 'May 1, 2024', amount: '$99.00', status: 'Paid' },
+ { id: 'INV-2024-004', date: 'Apr 1, 2024', amount: '$99.00', status: 'Paid' },
+ { id: 'INV-2024-003', date: 'Mar 1, 2024', amount: '$99.00', status: 'Paid' },
+ { id: 'INV-2024-002', date: 'Feb 1, 2024', amount: '$99.00', status: 'Paid' },
+ ];
+
+ return (
+
+
+
Billing
+
Manage your subscription and payment methods
+
+
+ {/* Current Plan */}
+
+
+
+
Current Plan
+
Pro Plan
+
$99/month · Renews on Jul 1, 2024
+
+
+
+
+
+
+
+
+ Storage used
+ 67GB / 100GB
+
+
+
+
+
+ {/* Plans Comparison */}
+
Available Plans
+
+ {plans.map((plan) => (
+
+ {plan.current && (
+
+ Current Plan
+
+ )}
+
{plan.name}
+
+ {plan.price}
+ {plan.period}
+
+
+ {plan.features.map((feature) => (
+ -
+ ✓
+ {feature}
+
+ ))}
+
+
+
+ ))}
+
+
+ {/* Invoice History */}
+
+
+
Invoice History
+
+
+
+
+
+ | Invoice |
+ Date |
+ Amount |
+ Status |
+ Action |
+
+
+
+ {invoices.map((inv) => (
+
+ | {inv.id} |
+ {inv.date} |
+ {inv.amount} |
+
+
+ {inv.status}
+
+ |
+
+
+ |
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/templates/saas/nextjs-monolith/app/globals.css b/templates/saas/nextjs-monolith/app/globals.css
new file mode 100644
index 0000000..283fef5
--- /dev/null
+++ b/templates/saas/nextjs-monolith/app/globals.css
@@ -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);
+}
diff --git a/templates/saas/nextjs-monolith/app/layout.tsx b/templates/saas/nextjs-monolith/app/layout.tsx
new file mode 100644
index 0000000..0399294
--- /dev/null
+++ b/templates/saas/nextjs-monolith/app/layout.tsx
@@ -0,0 +1,126 @@
+import type { Metadata } from 'next';
+import Link from 'next/link';
+import './globals.css';
+import AnimationProvider from '../components/AnimationProvider';
+{{#if (eq design "Dark Terminal")}}
+import { Terminal } from 'lucide-react';
+{{/if}}
+
+export const metadata: Metadata = {
+ title: '{{projectName}} - Dashboard',
+ description: 'A {{variant}} SaaS dashboard built with Opusify CLI.',
+};
+
+const navLinks = [
+ { label: 'Dashboard', href: '/' },
+ { label: 'Analytics', href: '/analytics' },
+ { label: 'Users', href: '/users' },
+ { label: 'Billing', href: '/billing' },
+ { label: 'Settings', href: '/settings' },
+];
+
+function Navbar() {
+ return (
+
+
+
+ );
+}
+
+function Sidebar() {
+ return (
+
+ );
+}
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ const useSidebar = '{{includeSidebar}}' === 'true';
+
+ return (
+
+
+ {useSidebar ? (
+
+ ) : (
+ <>
+
+
+
+ {children}
+
+
+ >
+ )}
+
+
+ );
+}
diff --git a/templates/saas/nextjs-monolith/app/page.tsx b/templates/saas/nextjs-monolith/app/page.tsx
new file mode 100644
index 0000000..72c8189
--- /dev/null
+++ b/templates/saas/nextjs-monolith/app/page.tsx
@@ -0,0 +1,122 @@
+export default function Dashboard() {
+ const metrics = [
+ { label: 'Monthly Revenue', value: '$48,295', change: '+12.5%', positive: true },
+ { label: 'Active Users', value: '12,847', change: '+8.2%', positive: true },
+ { label: 'Churn Rate', value: '2.4%', change: '-0.3%', positive: true },
+ { label: 'Avg. Session', value: '4m 32s', change: '-12s', positive: false },
+ ];
+
+ const chartData = [
+ { month: 'Jan', revenue: 32000, users: 8400 },
+ { month: 'Feb', revenue: 35000, users: 9200 },
+ { month: 'Mar', revenue: 38500, users: 9800 },
+ { month: 'Apr', revenue: 41000, users: 10500 },
+ { month: 'May', revenue: 44200, users: 11300 },
+ { month: 'Jun', revenue: 48295, users: 12847 },
+ ];
+
+ const recentTransactions = [
+ { id: 'TXN-001', customer: 'Acme Corp', plan: 'Enterprise', amount: '$2,400', status: 'Completed', date: 'Today' },
+ { id: 'TXN-002', customer: 'StartupXYZ', plan: 'Pro', amount: '$99', status: 'Completed', date: 'Today' },
+ { id: 'TXN-003', customer: 'DevTeam Inc', plan: 'Enterprise', amount: '$2,400', status: 'Pending', date: 'Yesterday' },
+ { id: 'TXN-004', customer: 'Solo Dev', plan: 'Starter', amount: '$29', status: 'Completed', date: 'Yesterday' },
+ { id: 'TXN-005', customer: 'BigCo Ltd', plan: 'Enterprise', amount: '$2,400', status: 'Failed', date: '2 days ago' },
+ ];
+
+ const maxRevenue = Math.max(...chartData.map((d) => d.revenue));
+
+ return (
+
+ {/* Header */}
+
+
+ Welcome to {{projectName}}
+
+
+ Your {{variant}} dashboard — real-time metrics at a glance.
+
+
+
+ {/* Metrics Cards */}
+
+ {metrics.map((metric) => (
+
+
{metric.label}
+
{metric.value}
+
+ {metric.change} from last month
+
+
+ ))}
+
+
+ {/* Revenue Chart */}
+
+
Revenue Overview
+
+ {chartData.map((point) => (
+
+ ))}
+
+
+
+
Total Revenue (6mo)
+
$238,995
+
+
+
+
+
+ {/* Recent Transactions */}
+
+
+
Recent Transactions
+
+
+
+
+
+
+ | ID |
+ Customer |
+ Plan |
+ Amount |
+ Status |
+ Date |
+
+
+
+ {recentTransactions.map((txn) => (
+
+ | {txn.id} |
+ {txn.customer} |
+ {txn.plan} |
+ {txn.amount} |
+
+
+ {txn.status}
+
+ |
+ {txn.date} |
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/templates/saas/nextjs-monolith/app/settings/page.tsx b/templates/saas/nextjs-monolith/app/settings/page.tsx
new file mode 100644
index 0000000..bdcb83d
--- /dev/null
+++ b/templates/saas/nextjs-monolith/app/settings/page.tsx
@@ -0,0 +1,97 @@
+export default function SettingsPage() {
+ return (
+
+
+
Settings
+
Manage your account and application preferences
+
+
+
+ {/* Profile Section */}
+
+
Profile
+
+
+ A
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Notifications */}
+
+
Notifications
+
+ {[
+ { label: 'Email notifications', description: 'Receive email updates about your account activity', enabled: true },
+ { label: 'Push notifications', description: 'Get push notifications in your browser', enabled: true },
+ { label: 'Weekly digest', description: 'Receive a weekly summary of your analytics', enabled: false },
+ { label: 'Marketing emails', description: 'Receive product updates and announcements', enabled: false },
+ ].map((item) => (
+
+
+
{item.label}
+
{item.description}
+
+
+
+ ))}
+
+
+
+ {/* Danger Zone */}
+
+
Danger Zone
+
+ Once you delete your account, there is no going back. Please be certain.
+
+
+
+
+
+ );
+}
diff --git a/templates/saas/nextjs-monolith/app/users/page.tsx b/templates/saas/nextjs-monolith/app/users/page.tsx
new file mode 100644
index 0000000..625fde6
--- /dev/null
+++ b/templates/saas/nextjs-monolith/app/users/page.tsx
@@ -0,0 +1,117 @@
+export default function UsersPage() {
+ const users = [
+ { id: 1, name: 'Sarah Johnson', email: 'sarah@acmecorp.com', role: 'Admin', plan: 'Enterprise', status: 'Active', lastSeen: '2 min ago' },
+ { id: 2, name: 'Michael Chen', email: 'mchen@startupxyz.io', role: 'Owner', plan: 'Pro', status: 'Active', lastSeen: '15 min ago' },
+ { id: 3, name: 'Emily Rodriguez', email: 'emily.r@devteam.co', role: 'Member', plan: 'Enterprise', status: 'Active', lastSeen: '1 hour ago' },
+ { id: 4, name: 'James Wilson', email: 'jwilson@solodev.me', role: 'Owner', plan: 'Starter', status: 'Active', lastSeen: '3 hours ago' },
+ { id: 5, name: 'Priya Patel', email: 'priya@bigco.com', role: 'Admin', plan: 'Enterprise', status: 'Inactive', lastSeen: '2 days ago' },
+ { id: 6, name: 'Alex Thompson', email: 'alex.t@freelance.dev', role: 'Owner', plan: 'Pro', status: 'Active', lastSeen: '5 hours ago' },
+ { id: 7, name: 'Lisa Wang', email: 'lwang@techfirm.io', role: 'Member', plan: 'Pro', status: 'Suspended', lastSeen: '1 week ago' },
+ { id: 8, name: 'David Kim', email: 'dkim@agency.co', role: 'Owner', plan: 'Enterprise', status: 'Active', lastSeen: '30 min ago' },
+ ];
+
+ const stats = [
+ { label: 'Total Users', value: '12,847' },
+ { label: 'Active Now', value: '1,234' },
+ { label: 'New This Week', value: '89' },
+ ];
+
+ return (
+
+
+
+
Users
+
Manage your platform users and permissions
+
+
+
+
+ {/* Stats */}
+
+ {stats.map((stat) => (
+
+
{stat.label}
+
{stat.value}
+
+ ))}
+
+
+ {/* Search & Filters */}
+
+
+
+
+
+
+ {/* Users Table */}
+
+
+
+
+
+ | User |
+ Role |
+ Plan |
+ Status |
+ Last Seen |
+ Actions |
+
+
+
+ {users.map((user) => (
+
+
+
+
+ {user.name.split(' ').map((n) => n[0]).join('')}
+
+
+ {user.name}
+ {user.email}
+
+
+ |
+ {user.role} |
+
+
+ {user.plan}
+
+ |
+
+
+ {user.status}
+
+ |
+ {user.lastSeen} |
+
+
+ |
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/templates/saas/nextjs-monolith/components/AnimationProvider.tsx b/templates/saas/nextjs-monolith/components/AnimationProvider.tsx
new file mode 100644
index 0000000..feaf51c
--- /dev/null
+++ b/templates/saas/nextjs-monolith/components/AnimationProvider.tsx
@@ -0,0 +1,32 @@
+{{#if (eq design "Glassmorphism")}}
+'use client';
+
+import { AnimatePresence, motion } from 'framer-motion';
+
+export default function AnimationProvider({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+
+
+ {children}
+
+
+ );
+}
+{{else}}
+export default function AnimationProvider({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}
+{{/if}}
diff --git a/templates/saas/nextjs-monolith/next.config.js b/templates/saas/nextjs-monolith/next.config.js
new file mode 100644
index 0000000..658404a
--- /dev/null
+++ b/templates/saas/nextjs-monolith/next.config.js
@@ -0,0 +1,4 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {};
+
+module.exports = nextConfig;
diff --git a/templates/saas/nextjs-monolith/package.json b/templates/saas/nextjs-monolith/package.json
new file mode 100644
index 0000000..5dfa145
--- /dev/null
+++ b/templates/saas/nextjs-monolith/package.json
@@ -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"
+ }
+}
diff --git a/templates/saas/nextjs-monolith/postcss.config.js b/templates/saas/nextjs-monolith/postcss.config.js
new file mode 100644
index 0000000..12a703d
--- /dev/null
+++ b/templates/saas/nextjs-monolith/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/templates/saas/nextjs-monolith/tailwind.config.ts b/templates/saas/nextjs-monolith/tailwind.config.ts
new file mode 100644
index 0000000..c763011
--- /dev/null
+++ b/templates/saas/nextjs-monolith/tailwind.config.ts
@@ -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;
diff --git a/templates/saas/nextjs-monolith/tsconfig.json b/templates/saas/nextjs-monolith/tsconfig.json
new file mode 100644
index 0000000..455bf35
--- /dev/null
+++ b/templates/saas/nextjs-monolith/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "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"]
+}
diff --git a/templates/saas/vite-react/index.html b/templates/saas/vite-react/index.html
new file mode 100644
index 0000000..a904173
--- /dev/null
+++ b/templates/saas/vite-react/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ {{projectName}} - Dashboard
+
+
+
+
+
+
diff --git a/templates/saas/vite-react/package.json b/templates/saas/vite-react/package.json
new file mode 100644
index 0000000..f89623c
--- /dev/null
+++ b/templates/saas/vite-react/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "{{projectName}}",
+ "version": "1.0.0",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "preview": "vite preview",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
+ },
+ "dependencies": {
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "react-router-dom": "^6.23.0"
+ },
+ "devDependencies": {
+ "@types/react": "^18.3.0",
+ "@types/react-dom": "^18.3.0",
+ "@vitejs/plugin-react": "^4.2.1",
+ "autoprefixer": "^10.4.19",
+ "postcss": "^8.4.38",
+ "tailwindcss": "^3.4.3",
+ "typescript": "^5.4.5",
+ "vite": "^5.2.11"
+ }
+}
diff --git a/templates/saas/vite-react/postcss.config.js b/templates/saas/vite-react/postcss.config.js
new file mode 100644
index 0000000..2aa7205
--- /dev/null
+++ b/templates/saas/vite-react/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/templates/saas/vite-react/src/App.tsx b/templates/saas/vite-react/src/App.tsx
new file mode 100644
index 0000000..064e4c3
--- /dev/null
+++ b/templates/saas/vite-react/src/App.tsx
@@ -0,0 +1,23 @@
+import { BrowserRouter, Routes, Route } from 'react-router-dom';
+import Layout from './components/Layout';
+import Dashboard from './pages/Dashboard';
+import Analytics from './pages/Analytics';
+import Users from './pages/Users';
+import Billing from './pages/Billing';
+import Settings from './pages/Settings';
+
+export default function App() {
+ return (
+
+
+ }>
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+
+ );
+}
diff --git a/templates/saas/vite-react/src/components/Layout.tsx b/templates/saas/vite-react/src/components/Layout.tsx
new file mode 100644
index 0000000..bcb44ba
--- /dev/null
+++ b/templates/saas/vite-react/src/components/Layout.tsx
@@ -0,0 +1,97 @@
+import { Link, Outlet } from 'react-router-dom';
+
+const navLinks = [
+ { label: 'Dashboard', href: '/' },
+ { label: 'Analytics', href: '/analytics' },
+ { label: 'Users', href: '/users' },
+ { label: 'Billing', href: '/billing' },
+ { label: 'Settings', href: '/settings' },
+];
+
+function Navbar() {
+ return (
+
+
+
+ );
+}
+
+function Sidebar() {
+ return (
+
+ );
+}
+
+export default function Layout() {
+ const useSidebar = '{{includeSidebar}}' === 'true';
+
+ if (useSidebar) {
+ return (
+
+
+
+
+
+
+ );
+ }
+
+ return (
+ <>
+
+
+
+
+ >
+ );
+}
diff --git a/templates/saas/vite-react/src/index.css b/templates/saas/vite-react/src/index.css
new file mode 100644
index 0000000..7a2f894
--- /dev/null
+++ b/templates/saas/vite-react/src/index.css
@@ -0,0 +1,48 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+: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;
+}
+
+[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="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;
+}
+
+body {
+ background-color: var(--bg-color);
+ color: var(--text-color);
+ font-family: var(--font-family);
+}
diff --git a/templates/saas/vite-react/src/main.tsx b/templates/saas/vite-react/src/main.tsx
new file mode 100644
index 0000000..9aa52ff
--- /dev/null
+++ b/templates/saas/vite-react/src/main.tsx
@@ -0,0 +1,10 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import App from './App';
+import './index.css';
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+ ,
+);
diff --git a/templates/saas/vite-react/src/pages/Analytics.tsx b/templates/saas/vite-react/src/pages/Analytics.tsx
new file mode 100644
index 0000000..ec8250c
--- /dev/null
+++ b/templates/saas/vite-react/src/pages/Analytics.tsx
@@ -0,0 +1,56 @@
+export default function Analytics() {
+ const trafficSources = [
+ { source: 'Organic Search', visitors: 4521, percentage: 38, color: 'bg-blue-500' },
+ { source: 'Direct', visitors: 2847, percentage: 24, color: 'bg-green-500' },
+ { source: 'Social Media', visitors: 1923, percentage: 16, color: 'bg-purple-500' },
+ { source: 'Referral', visitors: 1456, percentage: 12, color: 'bg-orange-500' },
+ { source: 'Email', visitors: 1100, percentage: 10, color: 'bg-pink-500' },
+ ];
+
+ return (
+
+
+
Analytics
+
Deep dive into your platform metrics
+
+
+
+
+
Total Page Views
+
284,920
+
+18.3% vs last period
+
+
+
Unique Visitors
+
11,847
+
+9.7% vs last period
+
+
+
Conversion Rate
+
7.1%
+
-0.4% vs last period
+
+
+
+
+
Traffic Sources
+
+ {trafficSources.map((source) => (
+
+
+ {source.source}
+ {source.visitors.toLocaleString()} ({source.percentage}%)
+
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/templates/saas/vite-react/src/pages/Billing.tsx b/templates/saas/vite-react/src/pages/Billing.tsx
new file mode 100644
index 0000000..2be5b8f
--- /dev/null
+++ b/templates/saas/vite-react/src/pages/Billing.tsx
@@ -0,0 +1,50 @@
+export default function Billing() {
+ const plans = [
+ { name: 'Starter', price: '$29', features: ['5 users', '10GB storage', 'Basic analytics'], current: false },
+ { name: 'Pro', price: '$99', features: ['25 users', '100GB storage', 'Advanced analytics', 'API access'], current: true },
+ { name: 'Enterprise', price: '$249', features: ['Unlimited users', '1TB storage', 'Full suite', 'SSO', 'Dedicated support'], current: false },
+ ];
+
+ return (
+
+
+
Billing
+
Manage your subscription
+
+
+
+ {plans.map((plan) => (
+
+ {plan.current && (
+
+ Current
+
+ )}
+
{plan.name}
+
{plan.price}/mo
+
+ {plan.features.map((f) => (
+ -
+ ✓ {f}
+
+ ))}
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/templates/saas/vite-react/src/pages/Dashboard.tsx b/templates/saas/vite-react/src/pages/Dashboard.tsx
new file mode 100644
index 0000000..5efd44c
--- /dev/null
+++ b/templates/saas/vite-react/src/pages/Dashboard.tsx
@@ -0,0 +1,59 @@
+export default function Dashboard() {
+ const metrics = [
+ { label: 'Monthly Revenue', value: '$48,295', change: '+12.5%', positive: true },
+ { label: 'Active Users', value: '12,847', change: '+8.2%', positive: true },
+ { label: 'Churn Rate', value: '2.4%', change: '-0.3%', positive: true },
+ { label: 'Avg. Session', value: '4m 32s', change: '-12s', positive: false },
+ ];
+
+ const chartData = [
+ { month: 'Jan', revenue: 32000 },
+ { month: 'Feb', revenue: 35000 },
+ { month: 'Mar', revenue: 38500 },
+ { month: 'Apr', revenue: 41000 },
+ { month: 'May', revenue: 44200 },
+ { month: 'Jun', revenue: 48295 },
+ ];
+
+ const maxRevenue = Math.max(...chartData.map((d) => d.revenue));
+
+ return (
+
+
+
+ Welcome to {{projectName}}
+
+
+ Your {{variant}} dashboard — real-time metrics at a glance.
+
+
+
+
+ {metrics.map((metric) => (
+
+
{metric.label}
+
{metric.value}
+
+ {metric.change} from last month
+
+
+ ))}
+
+
+
+
Revenue Overview
+
+ {chartData.map((point) => (
+
+ ))}
+
+
+
+ );
+}
diff --git a/templates/saas/vite-react/src/pages/Settings.tsx b/templates/saas/vite-react/src/pages/Settings.tsx
new file mode 100644
index 0000000..aeaafe5
--- /dev/null
+++ b/templates/saas/vite-react/src/pages/Settings.tsx
@@ -0,0 +1,45 @@
+export default function Settings() {
+ return (
+
+
+
Settings
+
Manage your account preferences
+
+
+
+
+
Profile
+
+
+
+
+
+
Danger Zone
+
Permanently delete your account and all data.
+
+
+
+
+ );
+}
diff --git a/templates/saas/vite-react/src/pages/Users.tsx b/templates/saas/vite-react/src/pages/Users.tsx
new file mode 100644
index 0000000..0c7daa1
--- /dev/null
+++ b/templates/saas/vite-react/src/pages/Users.tsx
@@ -0,0 +1,58 @@
+export default function Users() {
+ const users = [
+ { id: 1, name: 'Sarah Johnson', email: 'sarah@acmecorp.com', role: 'Admin', status: 'Active' },
+ { id: 2, name: 'Michael Chen', email: 'mchen@startupxyz.io', role: 'Owner', status: 'Active' },
+ { id: 3, name: 'Emily Rodriguez', email: 'emily.r@devteam.co', role: 'Member', status: 'Active' },
+ { id: 4, name: 'James Wilson', email: 'jwilson@solodev.me', role: 'Owner', status: 'Inactive' },
+ { id: 5, name: 'Priya Patel', email: 'priya@bigco.com', role: 'Admin', status: 'Active' },
+ { id: 6, name: 'Alex Thompson', email: 'alex.t@freelance.dev', role: 'Member', status: 'Active' },
+ ];
+
+ return (
+
+
+
+
Users
+
Manage your platform users
+
+
+
+
+
+
+
+
+ | User |
+ Role |
+ Status |
+ Actions |
+
+
+
+ {users.map((user) => (
+
+ |
+ {user.name}
+ {user.email}
+ |
+ {user.role} |
+
+
+ {user.status}
+
+ |
+
+
+ |
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/templates/saas/vite-react/tailwind.config.ts b/templates/saas/vite-react/tailwind.config.ts
new file mode 100644
index 0000000..c677f76
--- /dev/null
+++ b/templates/saas/vite-react/tailwind.config.ts
@@ -0,0 +1,28 @@
+import type { Config } from 'tailwindcss';
+
+const config: Config = {
+ content: ['./index.html', './src/**/*.{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;
diff --git a/templates/saas/vite-react/tsconfig.json b/templates/saas/vite-react/tsconfig.json
new file mode 100644
index 0000000..3934b8f
--- /dev/null
+++ b/templates/saas/vite-react/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/templates/saas/vite-react/tsconfig.node.json b/templates/saas/vite-react/tsconfig.node.json
new file mode 100644
index 0000000..42872c5
--- /dev/null
+++ b/templates/saas/vite-react/tsconfig.node.json
@@ -0,0 +1,10 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/templates/saas/vite-react/vite.config.ts b/templates/saas/vite-react/vite.config.ts
new file mode 100644
index 0000000..0466183
--- /dev/null
+++ b/templates/saas/vite-react/vite.config.ts
@@ -0,0 +1,6 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+});
diff --git a/templates/school/nextjs-monolith/.eslintrc.json b/templates/school/nextjs-monolith/.eslintrc.json
new file mode 100644
index 0000000..a2569c2
--- /dev/null
+++ b/templates/school/nextjs-monolith/.eslintrc.json
@@ -0,0 +1,4 @@
+{
+ "root": true,
+ "extends": "next/core-web-vitals"
+}
diff --git a/templates/school/nextjs-monolith/app/attendance/page.tsx b/templates/school/nextjs-monolith/app/attendance/page.tsx
new file mode 100644
index 0000000..cf6069f
--- /dev/null
+++ b/templates/school/nextjs-monolith/app/attendance/page.tsx
@@ -0,0 +1,148 @@
+export default function AttendancePage() {
+ const summaryCards = [
+ { label: 'Present', value: 142, color: 'bg-green-100 text-green-800' },
+ { label: 'Absent', value: 12, color: 'bg-red-100 text-red-800' },
+ { label: 'Late', value: 8, color: 'bg-yellow-100 text-yellow-800' },
+ { label: 'Excused', value: 5, color: 'bg-blue-100 text-blue-800' },
+ ];
+
+ const classes = [
+ {
+ name: 'Advanced Mathematics - Period 1',
+ instructor: 'Dr. Patricia Williams',
+ students: [
+ { id: 1, name: 'Sarah Johnson', status: 'Present' },
+ { id: 2, name: 'Michael Chen', status: 'Present' },
+ { id: 3, name: 'Emily Rodriguez', status: 'Late' },
+ { id: 4, name: 'James Wilson', status: 'Absent' },
+ { id: 5, name: 'Aisha Patel', status: 'Present' },
+ ],
+ },
+ {
+ name: 'English Literature - Period 2',
+ instructor: 'Prof. Robert Davis',
+ students: [
+ { id: 6, name: 'David Kim', status: 'Present' },
+ { id: 7, name: 'Olivia Brown', status: 'Present' },
+ { id: 8, name: 'Lucas Martinez', status: 'Excused' },
+ { id: 9, name: 'Sophia Lee', status: 'Present' },
+ { id: 10, name: 'Noah Taylor', status: 'Present' },
+ ],
+ },
+ {
+ name: 'Physics 101 - Period 3',
+ instructor: 'Dr. James Anderson',
+ students: [
+ { id: 11, name: 'Isabella White', status: 'Present' },
+ { id: 12, name: 'Ethan Harris', status: 'Absent' },
+ { id: 13, name: 'Mia Clark', status: 'Present' },
+ { id: 14, name: 'Alexander Lewis', status: 'Late' },
+ { id: 15, name: 'Charlotte Walker', status: 'Present' },
+ ],
+ },
+ ];
+
+ function getStatusStyle(status: string): string {
+ switch (status) {
+ case 'Present':
+ return 'bg-green-100 text-green-800';
+ case 'Absent':
+ return 'bg-red-100 text-red-800';
+ case 'Late':
+ return 'bg-yellow-100 text-yellow-800';
+ case 'Excused':
+ return 'bg-blue-100 text-blue-800';
+ default:
+ return 'bg-gray-100 text-gray-800';
+ }
+ }
+
+ return (
+
+ {/* Page Header */}
+
+
+
Attendance
+
Track and manage daily attendance records
+
+
+
+
+ {/* Date Selector */}
+
+
+
+
+
+
+
+
+
+ {/* Summary Cards */}
+
+ {summaryCards.map((card) => (
+
+
{card.label}
+
{card.value}
+
+ {card.label}
+
+
+ ))}
+
+
+ {/* Class-by-Class Attendance */}
+
+ {classes.map((cls) => (
+
+
+
{cls.name}
+
{cls.instructor}
+
+
+ {cls.students.map((student) => (
+
+
{student.name}
+
+
+ {student.status}
+
+
+
+
+ ))}
+
+
+ ))}
+
+
+ );
+}
diff --git a/templates/school/nextjs-monolith/app/courses/page.tsx b/templates/school/nextjs-monolith/app/courses/page.tsx
new file mode 100644
index 0000000..dbaa850
--- /dev/null
+++ b/templates/school/nextjs-monolith/app/courses/page.tsx
@@ -0,0 +1,136 @@
+export default function CoursesPage() {
+ const tabs = ['All', 'Active', 'Completed', 'Upcoming'];
+
+ const courses = [
+ {
+ id: 1,
+ name: 'Advanced Mathematics',
+ instructor: 'Dr. Patricia Williams',
+ students: 34,
+ progress: 72,
+ status: 'Active',
+ },
+ {
+ id: 2,
+ name: 'English Literature',
+ instructor: 'Prof. Robert Davis',
+ students: 28,
+ progress: 85,
+ status: 'Active',
+ },
+ {
+ id: 3,
+ name: 'Physics 101',
+ instructor: 'Dr. James Anderson',
+ students: 31,
+ progress: 60,
+ status: 'Active',
+ },
+ {
+ id: 4,
+ name: 'World History',
+ instructor: 'Ms. Linda Thompson',
+ students: 26,
+ progress: 100,
+ status: 'Completed',
+ },
+ {
+ id: 5,
+ name: 'Computer Science',
+ instructor: 'Mr. Kevin Park',
+ students: 22,
+ progress: 45,
+ status: 'Active',
+ },
+ {
+ id: 6,
+ name: 'Biology Lab',
+ instructor: 'Dr. Maria Garcia',
+ students: 0,
+ progress: 0,
+ status: 'Upcoming',
+ },
+ ];
+
+ return (
+
+ {/* Page Header */}
+
+
+
Courses
+
Browse and manage all courses
+
+
+
+
+ {/* Filter Tabs */}
+
+ {tabs.map((tab, index) => (
+
+ ))}
+
+
+ {/* Course Cards Grid */}
+
+ {courses.map((course) => (
+
+
+
{course.name}
+
+ {course.status}
+
+
+
+
{course.instructor}
+
{course.students} students enrolled
+
+ {/* Progress Bar */}
+
+
+ Progress
+ {course.progress}%
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/templates/school/nextjs-monolith/app/globals.css b/templates/school/nextjs-monolith/app/globals.css
new file mode 100644
index 0000000..283fef5
--- /dev/null
+++ b/templates/school/nextjs-monolith/app/globals.css
@@ -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);
+}
diff --git a/templates/school/nextjs-monolith/app/grades/page.tsx b/templates/school/nextjs-monolith/app/grades/page.tsx
new file mode 100644
index 0000000..aeb10d4
--- /dev/null
+++ b/templates/school/nextjs-monolith/app/grades/page.tsx
@@ -0,0 +1,111 @@
+export default function GradesPage() {
+ const summaryStats = [
+ { label: 'Class Average', value: '78.4%' },
+ { label: 'Highest Score', value: '98%' },
+ { label: 'Submissions', value: '1,243' },
+ ];
+
+ const grades = [
+ { id: 1, student: 'Sarah Johnson', course: 'Advanced Mathematics', assignment: 'Midterm Exam', score: 92, letter: 'A', date: '2024-03-15' },
+ { id: 2, student: 'Michael Chen', course: 'Physics 101', assignment: 'Lab Report 4', score: 87, letter: 'B+', date: '2024-03-14' },
+ { id: 3, student: 'Emily Rodriguez', course: 'English Literature', assignment: 'Essay: Modern Poetry', score: 95, letter: 'A', date: '2024-03-14' },
+ { id: 4, student: 'James Wilson', course: 'World History', assignment: 'Chapter 8 Quiz', score: 68, letter: 'D+', date: '2024-03-13' },
+ { id: 5, student: 'Aisha Patel', course: 'Computer Science', assignment: 'Project: Sorting Algorithms', score: 98, letter: 'A+', date: '2024-03-13' },
+ { id: 6, student: 'David Kim', course: 'Advanced Mathematics', assignment: 'Homework Set 7', score: 74, letter: 'C', date: '2024-03-12' },
+ { id: 7, student: 'Olivia Brown', course: 'Biology Lab', assignment: 'Dissection Report', score: 89, letter: 'B+', date: '2024-03-12' },
+ { id: 8, student: 'Lucas Martinez', course: 'Physics 101', assignment: 'Problem Set 5', score: 81, letter: 'B-', date: '2024-03-11' },
+ ];
+
+ function getScoreColor(score: number): string {
+ if (score >= 90) return 'text-green-600';
+ if (score >= 80) return 'text-blue-600';
+ if (score >= 70) return 'text-yellow-600';
+ return 'text-red-600';
+ }
+
+ return (
+
+ {/* Page Header */}
+
+
+
Grades
+
View and manage student grades and assessments
+
+
+
+
+ {/* Summary Stats */}
+
+ {summaryStats.map((stat) => (
+
+
{stat.label}
+
{stat.value}
+
+ ))}
+
+
+ {/* Filters */}
+
+
+
+
+
+
+ {/* Grades Table */}
+
+
+
+
+ | Student |
+ Course |
+ Assignment |
+ Score |
+ Grade |
+ Date |
+
+
+
+ {grades.map((entry) => (
+
+ | {entry.student} |
+ {entry.course} |
+ {entry.assignment} |
+
+ {entry.score}%
+ |
+
+
+ {entry.letter}
+
+ |
+ {entry.date} |
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/templates/school/nextjs-monolith/app/layout.tsx b/templates/school/nextjs-monolith/app/layout.tsx
new file mode 100644
index 0000000..ce575d6
--- /dev/null
+++ b/templates/school/nextjs-monolith/app/layout.tsx
@@ -0,0 +1,122 @@
+import type { Metadata } from 'next';
+import Link from 'next/link';
+import './globals.css';
+import AnimationProvider from '../components/AnimationProvider';
+{{#if (eq design "Dark Terminal")}}
+import { Terminal } from 'lucide-react';
+{{/if}}
+
+export const metadata: Metadata = {
+ title: '{{projectName}} - School Management',
+ description: 'A {{variant}} school management system built with Opusify CLI.',
+};
+
+const navLinks = [
+ { label: 'Dashboard', href: '/' },
+ { label: 'Students', href: '/students' },
+ { label: 'Courses', href: '/courses' },
+ { label: 'Grades', href: '/grades' },
+ { label: 'Attendance', href: '/attendance' },
+ { label: 'Schedule', href: '/schedule' },
+];
+
+function Navbar() {
+ return (
+
+
+
+ );
+}
+
+function Sidebar() {
+ return (
+
+ );
+}
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ const useSidebar = '{{includeSidebar}}' === 'true';
+
+ return (
+
+
+ {useSidebar ? (
+
+ ) : (
+ <>
+
+
+
+ {children}
+
+
+ >
+ )}
+
+
+ );
+}
diff --git a/templates/school/nextjs-monolith/app/page.tsx b/templates/school/nextjs-monolith/app/page.tsx
new file mode 100644
index 0000000..5ce178d
--- /dev/null
+++ b/templates/school/nextjs-monolith/app/page.tsx
@@ -0,0 +1,83 @@
+export default function Dashboard() {
+ const stats = [
+ { label: 'Total Students', value: '2,847', change: '+12%' },
+ { label: 'Active Courses', value: '156', change: '+3%' },
+ { label: 'Attendance Rate', value: '94.2%', change: '+1.5%' },
+ { label: 'Upcoming Exams', value: '23', change: 'This week' },
+ ];
+
+ const recentActivity = [
+ { id: 1, text: 'Sarah Johnson submitted Assignment 3 for Advanced Mathematics', time: '2 min ago' },
+ { id: 2, text: 'New student enrollment: Michael Chen (Grade 10)', time: '15 min ago' },
+ { id: 3, text: 'Dr. Williams posted grades for Physics 101 midterm', time: '1 hour ago' },
+ { id: 4, text: 'Attendance alert: 5 students absent from Period 3', time: '2 hours ago' },
+ { id: 5, text: 'Course schedule updated for Spring semester', time: '3 hours ago' },
+ { id: 6, text: 'Parent-teacher conference scheduled for next Friday', time: '5 hours ago' },
+ ];
+
+ const quickActions = [
+ { label: 'Add Student', description: 'Register a new student' },
+ { label: 'Create Course', description: 'Set up a new course' },
+ { label: 'Take Attendance', description: 'Mark today\'s attendance' },
+ { label: 'Generate Report', description: 'Export data reports' },
+ ];
+
+ return (
+
+ {/* Welcome Header */}
+
+
+ Welcome to {{projectName}}
+
+
+ Your {{variant}} dashboard — here's what's happening today.
+
+
+
+ {/* Stats Cards */}
+
+ {stats.map((stat) => (
+
+
{stat.label}
+
{stat.value}
+
{stat.change}
+
+ ))}
+
+
+
+ {/* Recent Activity */}
+
+
Recent Activity
+
+ {recentActivity.map((item) => (
+
+
{item.text}
+
{item.time}
+
+ ))}
+
+
+
+ {/* Quick Actions */}
+
+
Quick Actions
+
+ {quickActions.map((action) => (
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/templates/school/nextjs-monolith/app/students/page.tsx b/templates/school/nextjs-monolith/app/students/page.tsx
new file mode 100644
index 0000000..1d89f95
--- /dev/null
+++ b/templates/school/nextjs-monolith/app/students/page.tsx
@@ -0,0 +1,121 @@
+export default function StudentsPage() {
+ const students = [
+ { id: 'STU-001', name: 'Sarah Johnson', grade: 'Grade 11', status: 'Active', email: 'sarah.j@school.edu' },
+ { id: 'STU-002', name: 'Michael Chen', grade: 'Grade 10', status: 'Active', email: 'michael.c@school.edu' },
+ { id: 'STU-003', name: 'Emily Rodriguez', grade: 'Grade 12', status: 'Active', email: 'emily.r@school.edu' },
+ { id: 'STU-004', name: 'James Wilson', grade: 'Grade 9', status: 'Probation', email: 'james.w@school.edu' },
+ { id: 'STU-005', name: 'Aisha Patel', grade: 'Grade 11', status: 'Active', email: 'aisha.p@school.edu' },
+ { id: 'STU-006', name: 'David Kim', grade: 'Grade 10', status: 'Active', email: 'david.k@school.edu' },
+ { id: 'STU-007', name: 'Olivia Brown', grade: 'Grade 12', status: 'Graduated', email: 'olivia.b@school.edu' },
+ { id: 'STU-008', name: 'Lucas Martinez', grade: 'Grade 9', status: 'Active', email: 'lucas.m@school.edu' },
+ ];
+
+ return (
+
+ {/* Page Header */}
+
+
+
Students
+
Manage and view all enrolled students
+
+
+
+
+ {/* Search & Filter Bar */}
+
+
+
+
+
+
+
+
+ {/* Students Table */}
+
+
+
+
+ | Name |
+ ID |
+ Grade/Level |
+ Status |
+ Actions |
+
+
+
+ {students.map((student) => (
+
+
+
+ {student.name}
+ {student.email}
+
+ |
+ {student.id} |
+ {student.grade} |
+
+
+ {student.status}
+
+ |
+
+
+
+
+
+ |
+
+ ))}
+
+
+
+
+ {/* Pagination */}
+
+
Showing 1-8 of 2,847 students
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/templates/school/nextjs-monolith/components/AnimationProvider.tsx b/templates/school/nextjs-monolith/components/AnimationProvider.tsx
new file mode 100644
index 0000000..feaf51c
--- /dev/null
+++ b/templates/school/nextjs-monolith/components/AnimationProvider.tsx
@@ -0,0 +1,32 @@
+{{#if (eq design "Glassmorphism")}}
+'use client';
+
+import { AnimatePresence, motion } from 'framer-motion';
+
+export default function AnimationProvider({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+
+
+ {children}
+
+
+ );
+}
+{{else}}
+export default function AnimationProvider({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}
+{{/if}}
diff --git a/templates/school/nextjs-monolith/next.config.js b/templates/school/nextjs-monolith/next.config.js
new file mode 100644
index 0000000..658404a
--- /dev/null
+++ b/templates/school/nextjs-monolith/next.config.js
@@ -0,0 +1,4 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {};
+
+module.exports = nextConfig;
diff --git a/templates/school/nextjs-monolith/package.json b/templates/school/nextjs-monolith/package.json
new file mode 100644
index 0000000..5dfa145
--- /dev/null
+++ b/templates/school/nextjs-monolith/package.json
@@ -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"
+ }
+}
diff --git a/templates/school/nextjs-monolith/postcss.config.js b/templates/school/nextjs-monolith/postcss.config.js
new file mode 100644
index 0000000..12a703d
--- /dev/null
+++ b/templates/school/nextjs-monolith/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/templates/school/nextjs-monolith/tailwind.config.ts b/templates/school/nextjs-monolith/tailwind.config.ts
new file mode 100644
index 0000000..c763011
--- /dev/null
+++ b/templates/school/nextjs-monolith/tailwind.config.ts
@@ -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;
diff --git a/templates/school/nextjs-monolith/tsconfig.json b/templates/school/nextjs-monolith/tsconfig.json
new file mode 100644
index 0000000..e7ff90f
--- /dev/null
+++ b/templates/school/nextjs-monolith/tsconfig.json
@@ -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"]
+}