From 5bb69300f521eb89cb70308c5a0cbb8a19525d6c Mon Sep 17 00:00:00 2001 From: Luke Hagar Date: Fri, 30 May 2025 08:56:12 -0500 Subject: [PATCH] adjusted name, updated lockfile, updated readme, adjusted styles, adjusted blog, testing glob --- README.md | 411 +++++++++++++++++- package-lock.json | 4 +- .../(marketing)/blog/[slug]/+page.svelte | 4 +- src/routes/+layout.svelte | 4 +- 4 files changed, 409 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 1668f9f..835b305 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,50 @@ + # 🚀 Sveltey - SvelteKit SaaS Template ![Sveltey SaaS Template](https://github.com/user-attachments/assets/5dc91129-ebc7-4458-98b6-1862c6de4428) A modern, production-ready SaaS template built with SvelteKit 2, Svelte 5, Supabase, and Skeleton UI. Get your SaaS project up and running in hours, not months. +- [🚀 Sveltey - SvelteKit SaaS Template](#-sveltey---sveltekit-saas-template) + - [✨ Features](#-features) + - [🔐 Authentication \& User Management](#-authentication--user-management) + - [🎨 Modern UI/UX](#-modern-uiux) + - [📝 Content Management](#-content-management) + - [📊 Dashboard \& Analytics - Planned](#-dashboard--analytics---planned) + - [💳 Payments \& Subscriptions - Planned](#-payments--subscriptions---planned) + - [🚀 Quick Start](#-quick-start) + - [📦 Tech Stack](#-tech-stack) + - [📁 Project Structure](#-project-structure) + - [🔧 Configuration](#-configuration) + - [Environment Variables](#environment-variables) + - [Supabase Setup](#supabase-setup) + - [Stripe Setup](#stripe-setup) + - [🎯 Customization](#-customization) + - [Branding](#branding) + - [Components](#components) + - [🔍 SEO \& Meta Tags](#-seo--meta-tags) + - [Understanding the Meta Tag System](#understanding-the-meta-tag-system) + - [Base Meta Tags Structure](#base-meta-tags-structure) + - [Customizing Page Meta Tags](#customizing-page-meta-tags) + - [Dynamic Meta Tags](#dynamic-meta-tags) + - [Robot Control](#robot-control) + - [🖼️ OpenGraph Images](#️-opengraph-images) + - [Setting Up OpenGraph Images](#setting-up-opengraph-images) + - [1. Default Site Image](#1-default-site-image) + - [2. Page-Specific Images](#2-page-specific-images) + - [3. Dynamic Images for Blog Posts](#3-dynamic-images-for-blog-posts) + - [OpenGraph Image Best Practices](#opengraph-image-best-practices) + - [Image Specifications](#image-specifications) + - [Design Guidelines](#design-guidelines) + - [Dynamic Image Generation](#dynamic-image-generation) + - [Testing OpenGraph Images](#testing-opengraph-images) + - [Common OpenGraph Properties](#common-opengraph-properties) + - [🤝 Contributing](#-contributing) + - [📄 License](#-license) + - [🆘 Support](#-support) + - [🙏 Acknowledgments](#-acknowledgments) + + ## ✨ Features ### 🔐 Authentication & User Management @@ -20,21 +61,21 @@ A modern, production-ready SaaS template built with SvelteKit 2, Svelte 5, Supab - **Loading States**: Elegant loading indicators and transitions - **Toast Notifications**: User-friendly feedback system -### 📊 Dashboard & Analytics +### 📝 Content Management +- **Blog System**: Built-in blog with markdown support +- **SEO Optimized**: Meta tags, Open Graph, and structured data + +### 📊 Dashboard & Analytics - Planned - **Admin Dashboard**: Clean, intuitive admin interface - **User Analytics**: Basic user metrics and insights - **Real-time Updates**: Live data updates using Supabase real-time - **Data Visualization**: Charts and graphs for key metrics -### 📝 Content Management -- **Blog System**: Built-in blog with markdown support -- **SEO Optimized**: Meta tags, Open Graph, and structured data - - +- **Webhook Handling**: Secure webhook processing ## 🚀 Quick Start @@ -137,6 +178,362 @@ STRIPE_WEBHOOK_SECRET=your_webhook_secret - Skeleton UI provides the base component library - Easy to theme and customize with CSS variables +## 🔍 SEO & Meta Tags + +Sveltey comes with a comprehensive SEO system built on top of `svelte-meta-tags` that provides automatic meta tag management, OpenGraph support, and Twitter Card integration. + +### Understanding the Meta Tag System + +The meta tag system in Sveltey uses a two-level approach: + +1. **Base Meta Tags** (`src/routes/+layout.ts`) - Global defaults for your entire site +2. **Page Meta Tags** (`src/routes/*/+page.ts`) - Page-specific overrides and additions + +#### Base Meta Tags Structure + +The base meta tags are defined in `src/routes/+layout.ts` and include: + +```typescript +const baseMetaTags = Object.freeze({ + title: 'Sveltey - SvelteKit SaaS Template', + titleTemplate: '%s | Sveltey', + description: 'Your default site description...', + canonical: new URL(url.pathname, url.origin).href, + robots: 'index,follow', + keywords: ['SvelteKit', 'SaaS', 'template'], + + openGraph: { + type: 'website', + url: new URL(url.pathname, url.origin).href, + title: 'Sveltey - SvelteKit SaaS Template', + description: 'Your OpenGraph description...', + siteName: 'Sveltey', + locale: 'en_US', + images: [ + { + url: `${url.origin}/og-image.jpg`, + width: 1200, + height: 630, + alt: 'Sveltey - SvelteKit SaaS Template', + type: 'image/jpeg' + } + ] + }, + + twitter: { + cardType: 'summary_large_image', + site: '@sveltey_dev', + creator: '@sveltey_dev', + title: 'Sveltey - SvelteKit SaaS Template', + description: 'Your Twitter description...', + image: `${url.origin}/og-image.jpg`, + imageAlt: 'Sveltey - SvelteKit SaaS Template' + } +}) satisfies MetaTagsProps; +``` + +### Customizing Page Meta Tags + +Each page can override and extend the base meta tags by exporting a `load` function in its `+page.ts` file: + +```typescript +// src/routes/your-page/+page.ts +import type { MetaTagsProps } from 'svelte-meta-tags'; + +export const load = () => { + const pageMetaTags = Object.freeze({ + title: 'Your Page Title', + description: 'Specific description for this page', + keywords: ['additional', 'keywords', 'for', 'this', 'page'], + + openGraph: { + title: 'Your Page Title - Brand Name', + description: 'OpenGraph description for social sharing', + type: 'article', // or 'website', 'product', etc. + images: [ + { + url: 'https://your-domain.com/specific-og-image.jpg', + width: 1200, + height: 630, + alt: 'Description of your image' + } + ] + }, + + twitter: { + title: 'Twitter-specific title', + description: 'Twitter-specific description' + }, + + // Additional meta tags + additionalMetaTags: [ + { + name: 'author', + content: 'Your Name' + }, + { + property: 'article:published_time', + content: '2024-01-01T00:00:00Z' + } + ] + }) satisfies MetaTagsProps; + + return { + pageMetaTags + }; +}; +``` + +### Dynamic Meta Tags + +For dynamic pages (like blog posts), you can generate meta tags based on content: + +```typescript +// src/routes/blog/[slug]/+page.server.ts +export const load = async ({ params, url }) => { + const post = await getPostBySlug(params.slug); + + const pageMetaTags = Object.freeze({ + title: post.title, + description: post.excerpt, + canonical: new URL(`/blog/${params.slug}`, url.origin).href, + + openGraph: { + type: 'article', + title: post.title, + description: post.excerpt, + url: new URL(`/blog/${params.slug}`, url.origin).href, + images: post.featuredImage ? [ + { + url: post.featuredImage, + width: 1200, + height: 630, + alt: post.title + } + ] : undefined, + article: { + publishedTime: post.publishedAt, + authors: [post.author], + section: 'Technology', + tags: post.tags + } + } + }) satisfies MetaTagsProps; + + return { post, pageMetaTags }; +}; +``` + +### Robot Control + +Control search engine indexing per page: + +```typescript +const pageMetaTags = { + robots: 'noindex,nofollow', // Don't index this page + // or + robots: 'index,follow', // Index this page (default) + // or + robots: 'index,nofollow' // Index but don't follow links +}; +``` + +## 🖼️ OpenGraph Images + +OpenGraph images are crucial for social media sharing and SEO. Sveltey provides a flexible system for managing these images. + +### Setting Up OpenGraph Images + +#### 1. Default Site Image + +Place your default OpenGraph image in the `static` folder: + +``` +static/ +├── og-image.jpg # Default 1200x630 image +├── og-image-square.jpg # Optional square variant +└── favicon.png +``` + +The default image is automatically referenced in your base meta tags: + +```typescript +// src/routes/+layout.ts +openGraph: { + images: [ + { + url: `${url.origin}/og-image.jpg`, + width: 1200, + height: 630, + alt: 'Sveltey - SvelteKit SaaS Template', + type: 'image/jpeg' + } + ] +} +``` + +#### 2. Page-Specific Images + +Override the default image for specific pages: + +```typescript +// src/routes/pricing/+page.ts +const pageMetaTags = { + openGraph: { + images: [ + { + url: `${url.origin}/og-pricing.jpg`, + width: 1200, + height: 630, + alt: 'Sveltey Pricing Plans', + type: 'image/jpeg' + } + ] + } +}; +``` + +#### 3. Dynamic Images for Blog Posts + +For blog posts or dynamic content, you can generate or specify images dynamically: + +```typescript +// src/routes/blog/[slug]/+page.server.ts +const pageMetaTags = { + openGraph: { + images: post.featuredImage ? [ + { + url: post.featuredImage, + width: 1200, + height: 630, + alt: post.title, + type: 'image/jpeg' + } + ] : [ + { + url: `${url.origin}/og-blog-default.jpg`, + width: 1200, + height: 630, + alt: 'Sveltey Blog', + type: 'image/jpeg' + } + ] + } +}; +``` + +### OpenGraph Image Best Practices + +#### Image Specifications + +- **Recommended Size**: 1200x630 pixels (1.91:1 aspect ratio) +- **Minimum Size**: 600x315 pixels +- **Maximum Size**: 8MB +- **Format**: JPG or PNG (JPG preferred for smaller file size) + +#### Design Guidelines + +```typescript +// Example with multiple image variants +openGraph: { + images: [ + { + url: `${url.origin}/og-image-large.jpg`, + width: 1200, + height: 630, + alt: 'Large image for Facebook, LinkedIn', + type: 'image/jpeg' + }, + { + url: `${url.origin}/og-image-square.jpg`, + width: 1080, + height: 1080, + alt: 'Square image for Instagram, Twitter', + type: 'image/jpeg' + } + ] +} +``` + +#### Dynamic Image Generation + +For advanced use cases, you can generate images dynamically: + +```typescript +// src/routes/api/og/[slug]/+server.ts +export async function GET({ params, url }) { + const post = await getPostBySlug(params.slug); + + // Generate image using libraries like @vercel/og or canvas + const image = await generateOGImage({ + title: post.title, + author: post.author, + template: 'blog-post' + }); + + return new Response(image, { + headers: { + 'Content-Type': 'image/png', + 'Cache-Control': 'public, max-age=31536000, immutable' + } + }); +} +``` + +Then reference it in your meta tags: + +```typescript +openGraph: { + images: [ + { + url: `${url.origin}/api/og/${params.slug}`, + width: 1200, + height: 630, + alt: post.title, + type: 'image/png' + } + ] +} +``` + +### Testing OpenGraph Images + +Use these tools to test your OpenGraph implementation: + +- **Facebook Debugger**: https://developers.facebook.com/tools/debug/ +- **Twitter Card Validator**: https://cards-dev.twitter.com/validator +- **LinkedIn Post Inspector**: https://www.linkedin.com/post-inspector/ + +### Common OpenGraph Properties + +```typescript +openGraph: { + type: 'website', // website, article, product, etc. + title: 'Page Title', // Specific title for social sharing + description: 'Description', // Social media description + url: 'https://example.com', // Canonical URL + siteName: 'Site Name', // Your site/brand name + locale: 'en_US', // Language and region + + // For articles + article: { + publishedTime: '2024-01-01T00:00:00Z', + modifiedTime: '2024-01-02T00:00:00Z', + authors: ['Author Name'], + section: 'Technology', + tags: ['svelte', 'sveltekit'] + }, + + // For products + product: { + price: { + amount: '29.99', + currency: 'USD' + } + } +} +``` + ## 🤝 Contributing Contributions are welcome! Please feel free to submit a Pull Request. diff --git a/package-lock.json b/package-lock.json index 75b1c35..92fa434 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "saasy", + "name": "sveltey", "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "saasy", + "name": "sveltey", "version": "0.0.1", "devDependencies": { "@eslint/compat": "^1.2.5", diff --git a/src/routes/(marketing)/blog/[slug]/+page.svelte b/src/routes/(marketing)/blog/[slug]/+page.svelte index ec69e28..51cd4a9 100644 --- a/src/routes/(marketing)/blog/[slug]/+page.svelte +++ b/src/routes/(marketing)/blog/[slug]/+page.svelte @@ -1,6 +1,4 @@