Sveltey Svelte Themes

Sveltey

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 SaaS Template logo

🚀 Sveltey - 基于 SvelteKit 构建的 SaaS 模板

一个现代化、可用于生产环境的 SaaS 模板,基于 SvelteKit 2Svelte 5SupabaseSkeleton UI 构建。让您的 SaaS 项目在几小时内启动并运行,而不是几个月。

✨ 功能特性

🔐 身份验证和用户管理

  • Supabase Auth 集成: 完整的电子邮件/密码和 OAuth 提供商身份验证流程
  • 受保护的路由: 自动路由保护和会话管理
  • 用户个人资料: 可自定义的用户个人资料管理
  • 密码重置: 安全的密码重置功能

🎨 现代 UI/UX

  • Skeleton UI: 开箱即用的美观、可访问组件
  • 深色/浅色模式: 内置模式切换
  • 丰富的主题: 22 个精美的手工制作主题
  • 响应式设计: 移动优先的响应式布局
  • 加载状态: 优雅的加载指示器和过渡效果
  • Toast 通知: 用户友好的反馈系统

📝 内容管理

  • 博客系统: 内置支持 Markdown 的博客
  • SEO 优化: Meta 标签、Open Graph 和结构化数据

📊 仪表盘与数据分析 - 计划中

  • 管理仪表盘: 简洁直观的管理界面
  • 用户分析: 基本用户指标和洞察
  • 实时更新: 使用 Supabase real-time 进行实时数据更新
  • 数据可视化: 关键指标的图表展示
  • 隐私优先分析: 内置 Plausible Analytics 集成,符合 GDPR 规范的追踪

💳 支付与订阅 - 计划中

  • Stripe 集成: 即插即用的支付处理
  • 订阅计划: 灵活的定价层级
  • 计费管理: 客户计费门户
  • Webhook 处理: 安全的 Webhook 处理

🚀 快速开始

# 克隆仓库
git clone https://github.com/yourusername/sveltey.git
cd sveltey

# 安装依赖
npm install

# 设置环境变量
cp .env.example .env
# 编辑 .env 文件,填入您的 Supabase 和 Stripe 密钥

# 启动开发服务器
npm run dev

访问 http://localhost:5173 并开始构建您的 SaaS!

📦 技术栈

  • 框架: SvelteKit 2 与 Svelte 5
  • 数据库: Supabase (PostgreSQL)
  • 身份验证: Supabase Auth
  • UI 组件: Skeleton UI
  • 样式: Tailwind CSS
  • 数据分析: Plausible Analytics
  • 电子邮件: Resend
  • 部署: 准备好支持 Vercel/Netlify
  • 语言: TypeScript

📁 项目结构

src/
├── lib/
│   ├── components/     # 可复用的 UI 组件
│   ├── stores/         # Svelte 状态管理 stores
│   ├── utils/          # 工具函数
│   └── types/          # TypeScript 类型定义
├── routes/
│   ├── (app)/          # 应用路由
|   |   ├── api         # API 路由,安全性在端点级别处理
|   |   ├── app         # 应用路由,全局处理安全性,所有子路由均受保护
|   |   └── auth        # 身份验证路由,用于登录、注销和密码重置功能
│   └── (marketing)/    # 公开营销页面
|       ├── blog        # 博客路由
|       ├── contact     # 联系我们页面
|       ├── pricing     # 定价页面
|       ├── privacy     # 隐私政策页面
|       └── terms       # 服务条款页面
├── app.html            # 应用外壳
├── app.css             # 全局样式
└── hooks.server.ts     # 服务器钩子

🔧 配置

环境变量

在根目录创建一个 .env 文件:

# Supabase
PUBLIC_SUPABASE_URL=your_supabase_url
PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key

# Resend (用于电子邮件)
RESEND_API_KEY=your_resend_api_key

# Stripe // 即将推出
PUBLIC_STRIPE_PUBLISHABLE_KEY=your_stripe_publishable_key
STRIPE_SECRET_KEY=your_stripe_secret_key
STRIPE_WEBHOOK_SECRET=your_webhook_secret

Supabase 设置

  1. 创建一个新的 Supabase 项目
  2. 复制项目 URL 和 anon key
  3. 运行包含的 SQL 迁移文件
  4. 设置您的身份验证提供商

电子邮件设置 (Resend)

Sveltey 使用 Resend 提供可靠的电子邮件发送和卓越的开发者体验。

  1. resend.com 创建 Resend 账户
  2. 从 Resend 仪表盘 获取您的 API 密钥
  3. 添加到环境变量:
    RESEND_API_KEY=re_your_api_key_here
    
  4. 验证您的域名 (可选,但在生产环境中推荐):
    • 在 Resend 仪表盘中添加您的域名
    • 按照说明配置 DNS 记录
    • 这会移除 "via resend.com" 品牌标识并提高送达率

电子邮件功能

  • 事务性邮件: 密码重置、欢迎邮件、通知
  • 模板支持: 精美的 HTML 电子邮件模板
  • 投递追踪: 监控电子邮件的投递和参与度
  • 高送达率: 卓越的收件箱到达率
  • 简单的 API: 轻松集成 SvelteKit API 路由

使用示例

// src/routes/api/send-email/+server.ts
import { RESEND_API_KEY } from '$env/static/private';
import { Resend } from 'resend';

const resend = new Resend(RESEND_API_KEY);

export async function POST({ request }) {
    const { to, subject, html } = await request.json();

    try {
        const data = await resend.emails.send({
            from: '[email protected]',
            to,
            subject,
            html
        });

        return new Response(JSON.stringify({ success: true, data }), {
            headers: { 'Content-Type': 'application/json' }
        });
    } catch (error) {
        return new Response(JSON.stringify({ error: error.message }), {
            status: 500,
            headers: { 'Content-Type': 'application/json' }
        });
    }
}

电子邮件模板示例

src/lib/emails/ 中创建可复用的电子邮件模板:

// src/lib/emails/welcome.ts
export const welcomeEmail = (userName: string) => `
  <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
    <h1 style="color: #333;">欢迎来到 Sveltey, ${userName}!</h1>
    <p>感谢您加入我们的平台。我们很高兴您的加入。</p>
    <a href="https://yourdomain.com/dashboard" 
       style="background: #007bff; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px;">
      开始使用
    </a>
  </div>
`;

Stripe 设置

  1. 创建 Stripe 账户
  2. 复制您的 API 密钥
  3. 配置您的产品和定价
  4. 为订阅事件设置 webhooks

数据分析设置 (Plausible)

Sveltey 预配置了 Plausible Analytics - 一个轻量级、注重隐私的分析解决方案,默认符合 GDPR 规范。

当前配置

分析脚本已集成在 src/app.html 中:

<script defer data-domain="sveltey.dev" src="https://events.plygrnd.org/js/script.js"></script>

针对您的域名进行定制

  1. 自托管 Plausible: 如果使用您自己的 Plausible 实例,请更新脚本来源
  2. Plausible Cloud: 更改为官方的 Plausible 脚本:
    <script defer data-domain="yourdomain.com" src="https://plausible.io/js/script.js"></script>
    
  3. 更新域名: 将 data-domain="sveltey.dev" 替换为您实际的域名

数据分析功能

  • 隐私优先: 不使用 cookie,不收集个人数据
  • 符合 GDPR: 不需要同意横幅
  • 轻量级: 脚本大小不到 1KB
  • 实时: 实时访客追踪
  • 目标追踪: 可用自定义事件追踪

自定义事件 (可选)

添加用户行为的自定义事件追踪:

// 追踪自定义事件
plausible('signup', { props: { plan: 'premium' } });
plausible('purchase', { props: { amount: 99 } });

其他数据分析工具

要使用不同的数据分析提供商:

  1. src/app.html 移除 Plausible 脚本
  2. 添加您首选的数据分析脚本 (Google Analytics, Fathom 等)
  3. 相应更新隐私政策

🎯 个性化定制

品牌

  • 更新 app.html 以修改 favicon 和 meta 标签
  • 修改 src/lib/config.ts 进行应用配置
  • 通过 自定义 Skeleton UI 主题 来自定义颜色
  • 替换 logo

组件

  • 所有组件均在 src/lib/components/ 目录下
  • Skeleton UI 提供基础组件库
  • 易于使用 CSS 变量进行主题化和自定义

🔍 SEO 和 Meta 标签

Sveltey 附带基于 svelte-meta-tags 构建的全面 SEO 系统,提供自动的 meta 标签管理、OpenGraph 支持和 Twitter Card 集成。

了解 Meta 标签系统

Sveltey 中的 Meta 标签系统使用两级方法:

  1. 基础 Meta 标签 (src/routes/+layout.ts) - 整个站点的全局默认设置
  2. 页面 Meta 标签 (src/routes/*/+page.ts) - 页面特定的覆盖和添加

基础 Meta 标签结构

基础 meta 标签定义在 src/routes/+layout.ts 中,包括:

const baseMetaTags = Object.freeze({
    title: 'Sveltey - SvelteKit SaaS 模板',
    titleTemplate: '%s | Sveltey',
    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 模板',
        description: '您的 OpenGraph 描述...',
        siteName: 'Sveltey',
        locale: 'zh_CN',
        images: [
            {
                url: `${url.origin}/og-image.jpg`,
                width: 1200,
                height: 630,
                alt: 'Sveltey - SvelteKit SaaS 模板',
                type: 'image/jpeg'
            }
        ]
    },

    twitter: {
        cardType: 'summary_large_image',
        site: '@sveltey_dev',
        creator: '@sveltey_dev',
        title: 'Sveltey - SvelteKit SaaS 模板',
        description: '您的 Twitter 描述...',
        image: `${url.origin}/og-image.jpg`,
        imageAlt: 'Sveltey - SvelteKit SaaS 模板'
    }
}) satisfies MetaTagsProps;

自定义页面 Meta 标签

每个页面可以通过在其 +page.ts 文件中导出一个 load 函数来覆盖和扩展基础 meta 标签:

// src/routes/your-page/+page.ts
import type { MetaTagsProps } from 'svelte-meta-tags';

export const load = () => {
    const pageMetaTags = Object.freeze({
        title: '您的页面标题',
        description: '此页面的具体描述',
        keywords: ['此', '页面', '的', '额外', '关键字'],

        openGraph: {
            title: '您的页面标题 - 品牌名',
            description: '用于社交分享的 OpenGraph 描述',
            type: 'article', // 或 'website', 'product' 等
            images: [
                {
                    url: 'https://your-domain.com/specific-og-image.jpg',
                    width: 1200,
                    height: 630,
                    alt: '图片描述'
                }
            ]
        },

        twitter: {
            title: 'Twitter 特有的标题',
            description: 'Twitter 特有的描述'
        },

        // 额外的 meta 标签
        additionalMetaTags: [
            {
                name: 'author',
                content: '您的名字'
            },
            {
                property: 'article:published_time',
                content: '2024-01-01T00:00:00Z'
            }
        ]
    }) satisfies MetaTagsProps;

    return {
        pageMetaTags
    };
};

动态 Meta 标签

对于动态页面 (如博客文章),您可以根据内容生成 meta 标签:

// 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: '技术',
                tags: post.tags
            }
        }
    }) satisfies MetaTagsProps;

    return { post, pageMetaTags };
};

机器人控制

控制搜索引擎对每个页面的索引:

const pageMetaTags = {
    robots: 'noindex,nofollow', // 不索引此页面
    // 或
    robots: 'index,follow', // 索引此页面 (默认)
    // 或
    robots: 'index,nofollow' // 索引但不跟踪链接
};

🖼️ OpenGraph 图片

OpenGraph 图片对于社交媒体分享和 SEO 至关重要。Sveltey 提供了一个灵活的系统来管理这些图片。

设置 OpenGraph 图片

1. 默认站点图片

将默认的 OpenGraph 图片放置在 static 文件夹中:

static/
├── og-image.jpg        # 默认 1200x630 图片
├── og-image-square.jpg # 可选的方形变体
└── favicon.png

默认图片会在您的基础 meta 标签中被自动引用:

// src/routes/+layout.ts
openGraph: {
    images: [
        {
            url: `${url.origin}/og-image.jpg`,
            width: 1200,
            height: 630,
            alt: 'Sveltey - SvelteKit SaaS 模板',
            type: 'image/jpeg'
        }
    ];
}

2. 特定页面图片

覆盖特定页面的默认图片:

// src/routes/pricing/+page.ts
const pageMetaTags = {
    openGraph: {
        images: [
            {
                url: `${url.origin}/og-pricing.jpg`,
                width: 1200,
                height: 630,
                alt: 'Sveltey 定价计划',
                type: 'image/jpeg'
            }
        ]
    }
};

3. 博客文章的动态图片

对于博客文章或动态内容,您可以动态生成或指定图片:

// 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 博客',
                        type: 'image/jpeg'
                    }
                ]
    }
};

OpenGraph 图片最佳实践

图片规格

  • 推荐尺寸: 1200x630 像素 (1.91:1 宽高比)
  • 最小尺寸: 600x315 像素
  • 最大尺寸: 8MB
  • 格式: JPG 或 PNG (推荐 JPG 以减小文件大小)

设计指南

// 包含多个图片变体的示例
openGraph: {
    images: [
        {
            url: `${url.origin}/og-image-large.jpg`,
            width: 1200,
            height: 630,
            alt: '用于 Facebook、LinkedIn 的大图',
            type: 'image/jpeg'
        },
        {
            url: `${url.origin}/og-image-square.jpg`,
            width: 1080,
            height: 1080,
            alt: '用于 Instagram、Twitter 的方图',
            type: 'image/jpeg'
        }
    ];
}

动态生成图片

对于高级用例,您可以动态生成图片:

// src/routes/api/og/[slug]/+server.ts
export async function GET({ params, url }) {
    const post = await getPostBySlug(params.slug);

    // 使用像 @vercel/og 或 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'
        }
    });
}

然后在您的 meta 标签中引用它:

openGraph: {
    images: [
        {
            url: `${url.origin}/api/og/${params.slug}`,
            width: 1200,
            height: 630,
            alt: post.title,
            type: 'image/png'
        }
    ];
}

测试 OpenGraph 图片

使用这些工具测试您的 OpenGraph 实现:

常见的 OpenGraph 属性

openGraph: {
  type: 'website',           // website, article, product 等
  title: '页面标题',         // 社交分享的特定标题
  description: '描述',       // 社交媒体描述
  url: 'https://example.com', // 规范 URL
  siteName: '站点名称',      // 您的站点/品牌名称
  locale: 'zh_CN',           // 语言和地区

  // 针对文章
  article: {
    publishedTime: '2024-01-01T00:00:00Z',
    modifiedTime: '2024-01-02T00:00:00Z',
    authors: ['作者名'],
    section: '技术',
    tags: ['svelte', 'sveltekit']
  },

  // 针对产品
  product: {
    price: {
      amount: '29.99',
      currency: 'USD'
    }
  }
}

🤝 参与贡献

欢迎贡献!请随时提交 Pull Request。

  1. Fork 该仓库
  2. 创建您的特性分支 (git checkout -b feature/AmazingFeature)
  3. 提交您的修改 (git commit -m 'Add some AmazingFeature')
  4. 推送到分支 (git push origin feature/AmazingFeature)
  5. 打开 Pull Request

📄 许可证

本项目基于 MIT 许可证 - 有关详情,请参见 LICENSE 文件。

🆘 获取支持

🙏 致谢


准备好发布您的 SaaS 了吗?今天就开始使用 Sveltey!

Top categories

Loading Svelte Themes