+ + {post.title} + +
+ +{post.excerpt}
+ +diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..be36636
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,2 @@
+PUBLIC_SUPABASE_URL="YOUR_SUPABASE_URL"
+PUBLIC_SUPABASE_ANON_KEY="YOUR_SUPABASE_ANON_KEY"
diff --git a/my-saas-template/.gitignore b/.gitignore
similarity index 100%
rename from my-saas-template/.gitignore
rename to .gitignore
diff --git a/my-saas-template/.npmrc b/.npmrc
similarity index 100%
rename from my-saas-template/.npmrc
rename to .npmrc
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..6562bcb
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,6 @@
+# Package Managers
+package-lock.json
+pnpm-lock.yaml
+yarn.lock
+bun.lock
+bun.lockb
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..7ebb855
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,15 @@
+{
+ "useTabs": true,
+ "singleQuote": true,
+ "trailingComma": "none",
+ "printWidth": 100,
+ "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
+ "overrides": [
+ {
+ "files": "*.svelte",
+ "options": {
+ "parser": "svelte"
+ }
+ }
+ ]
+}
diff --git a/README.md b/README.md
index 03012e5..b5b2950 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,38 @@
-# Sassy
+# sv
+
+Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
+
+## Creating a project
+
+If you're seeing this, you've probably already done this step. Congrats!
+
+```bash
+# create a new project in the current directory
+npx sv create
+
+# create a new project in my-app
+npx sv create my-app
+```
+
+## Developing
+
+Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
+
+```bash
+npm run dev
+
+# or start the server and open the app in a new browser tab
+npm run dev -- --open
+```
+
+## Building
+
+To create a production version of your app:
+
+```bash
+npm run build
+```
+
+You can preview the production build with `npm run preview`.
+
+> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
diff --git a/docs/AUTHENTICATION_SETUP.md b/docs/AUTHENTICATION_SETUP.md
new file mode 100644
index 0000000..32ea28c
--- /dev/null
+++ b/docs/AUTHENTICATION_SETUP.md
@@ -0,0 +1,191 @@
+# SvelteKit Supabase Authentication Setup
+
+This project uses Supabase for authentication with full server-side rendering (SSR) support through SvelteKit hooks.
+
+## Features
+
+- ✅ Email/Password authentication
+- ✅ GitHub OAuth integration
+- ✅ Server-side authentication with `hooks.server.ts`
+- ✅ Protected routes with automatic redirects
+- ✅ Session management across client and server
+- ✅ TypeScript support with proper types
+
+## Setup Instructions
+
+### 1. Environment Variables
+
+Create a `.env.local` file in your project root:
+
+```bash
+PUBLIC_SUPABASE_URL=your_supabase_project_url
+PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
+```
+
+Get these values from your Supabase project dashboard under Settings > API.
+
+### 2. Supabase Configuration
+
+#### Enable GitHub OAuth Provider
+
+1. Go to your Supabase project dashboard
+2. Navigate to **Authentication > Providers**
+3. Enable the **GitHub** provider
+4. Add your GitHub OAuth credentials:
+ - **Client ID**: From your GitHub OAuth app
+ - **Client Secret**: From your GitHub OAuth app
+
+#### GitHub OAuth App Setup
+
+1. Go to GitHub Settings > Developer settings > OAuth Apps
+2. Click "New OAuth App"
+3. Fill in the details:
+ - **Application name**: Your app name
+ - **Homepage URL**: `http://localhost:5173` (for development)
+ - **Authorization callback URL**: `https://your-project-ref.supabase.co/auth/v1/callback`
+4. Note the Client ID and Client Secret for Supabase configuration
+
+### 3. Supabase Authentication Settings
+
+In your Supabase project settings:
+
+1. Go to **Authentication > Settings**
+2. Add your site URLs:
+ - **Site URL**: `http://localhost:5173` (development) / `https://yourdomain.com` (production)
+ - **Redirect URLs**: Add both your local and production URLs
+
+## Architecture Overview
+
+### Server-Side Authentication (`hooks.server.ts`)
+
+The authentication is handled through SvelteKit hooks:
+
+```typescript
+// src/hooks.server.ts
+export const handle: Handle = sequence(supabase, authGuard);
+```
+
+#### Features:
+- **`supabase` hook**: Creates server-side Supabase client with cookie management
+- **`authGuard` hook**: Protects routes and handles redirects
+- **Session validation**: Validates JWTs on every request
+- **Cookie management**: Automatic token refresh and cookie handling
+
+### Protected Routes
+
+Routes are automatically protected based on path patterns:
+
+- **`/dashboard/*`**: Requires authentication, redirects to `/auth/login` if not authenticated
+- **`/auth/*`**: Redirects authenticated users to `/dashboard`
+
+### Client-Side Integration (`+layout.svelte`)
+
+The root layout handles client-side authentication state:
+
+```typescript
+// Syncs server-side session with client-side
+$effect(() => {
+ session = data.session;
+});
+
+// Handles auth state changes
+supabase.auth.onAuthStateChange((event, newSession) => {
+ if (newSession?.expires_at !== session?.expires_at) {
+ invalidateAll();
+ }
+});
+```
+
+## File Structure
+
+```
+src/
+├── hooks.server.ts # Server-side authentication hooks
+├── app.d.ts # TypeScript definitions for Supabase
+├── lib/
+│ ├── index.ts # Exports (toaster)
+│ └── supabaseClient.ts # Browser Supabase client
+├── routes/
+│ ├── +layout.svelte # Root layout with auth state
+│ ├── +layout.server.ts # Server layout with session data
+│ ├── auth/
+│ │ ├── login/+page.svelte # Login page with GitHub OAuth
+│ │ ├── signup/+page.svelte # Signup page with GitHub OAuth
+│ │ └── logout/+page.server.ts # Logout action
+│ └── dashboard/
+│ ├── +layout.server.ts # Dashboard layout (protected)
+│ └── +page.svelte # Dashboard page
+```
+
+## Usage Examples
+
+### Login Page Features
+
+- Email/password authentication
+- GitHub OAuth login
+- Form validation and error handling
+- Loading states
+- Automatic redirect after login
+
+### Signup Page Features
+
+- Email/password registration
+- GitHub OAuth signup
+- Email confirmation handling
+- Error handling with toast notifications
+
+### Dashboard Protection
+
+The dashboard is automatically protected and will:
+- Redirect unauthenticated users to login
+- Display user information for authenticated users
+- Handle session expiration gracefully
+
+## TypeScript Support
+
+Full TypeScript support with proper types:
+
+```typescript
+// app.d.ts
+interface Locals {
+ supabase: SupabaseClient;
+ safeGetSession(): Promise<{ session: Session | null; user: User | null }>;
+ session: Session | null;
+ user: User | null;
+}
+```
+
+## Development
+
+1. Start your development server:
+```bash
+npm run dev
+```
+
+2. Test authentication:
+ - Visit `/auth/signup` to create an account
+ - Try GitHub OAuth login
+ - Visit `/dashboard` to see protected content
+ - Test logout functionality
+
+## Security Features
+
+- **JWT validation**: Server-side validation of authentication tokens
+- **Automatic refresh**: Tokens are refreshed automatically
+- **Secure cookies**: HTTP-only cookies for session management
+- **Route protection**: Server-side route guards
+- **CSRF protection**: Built into Supabase auth flow
+
+## Troubleshooting
+
+### Common Issues
+
+1. **"Cannot redirect during render"**: Usually caused by trying to redirect in a `load` function without throwing the redirect
+2. **OAuth callback errors**: Check your GitHub OAuth app callback URL matches Supabase settings
+3. **Session not persisting**: Ensure cookies are configured correctly in `hooks.server.ts`
+
+### Debug Tips
+
+- Check browser Network tab for auth requests
+- Verify Supabase project settings match your configuration
+- Test OAuth flow in incognito mode to avoid cached sessions
\ No newline at end of file
diff --git a/docs/BLOG_SETUP.md b/docs/BLOG_SETUP.md
new file mode 100644
index 0000000..0243f37
--- /dev/null
+++ b/docs/BLOG_SETUP.md
@@ -0,0 +1,392 @@
+# Markdown Blog Setup with MDSvex (Svelte 5 Compatible)
+
+This project uses a static markdown-based blog system powered by MDSvex for SvelteKit. This implementation is optimized for Svelte 5 and uses component-based rendering instead of HTML content strings.
+
+## Features
+
+- ✅ **Markdown Support**: Write posts in markdown with full syntax support
+- ✅ **Frontmatter Metadata**: YAML frontmatter for post metadata
+- ✅ **Featured Posts**: Mark posts as featured for special display
+- ✅ **Tags & Categories**: Organize posts with tags
+- ✅ **SEO Optimized**: Automatic meta tags and Open Graph support
+- ✅ **Responsive Design**: Mobile-friendly blog layout
+- ✅ **Syntax Highlighting**: Code blocks with Shiki highlighting
+- ✅ **Table of Contents**: Automatic TOC generation
+- ✅ **Svelte 5 Compatible**: Uses component-based rendering
+
+## File Structure
+
+```
+src/
+├── lib/
+│ ├── posts/ # Markdown blog posts
+│ │ ├── getting-started.md
+│ │ ├── advanced-features.md
+│ │ └── building-integrations.md
+│ ├── components/
+│ │ └── MDXLayout.svelte # Layout for mdx content
+│ ├── blog.ts # Blog utilities and types
+│ └── blog-utils.ts # Helper functions
+├── routes/
+│ └── blog/
+│ ├── +page.svelte # Blog index page
+│ ├── +page.server.ts # Load all posts
+│ └── [slug]/
+│ ├── +page.svelte # Individual post page
+│ └── +page.server.ts # Load single post
+└── docs/
+ └── BLOG_SETUP.md # This documentation
+```
+
+## Creating Blog Posts
+
+### 1. Create a New Markdown File
+
+Create a new `.md` file in `src/lib/posts/`:
+
+```bash
+touch src/lib/posts/my-new-post.md
+```
+
+### 2. Add Frontmatter
+
+Start your post with YAML frontmatter:
+
+```markdown
+---
+title: "My Awesome Blog Post"
+slug: "my-awesome-blog-post"
+excerpt: "A compelling description of your blog post that will appear in listings and meta tags."
+publishedAt: "2024-01-30"
+author: "Your Name"
+tags: ["tutorial", "sveltekit", "web-development"]
+featured: true
+---
+
+# My Awesome Blog Post
+
+Your content goes here...
+```
+
+### 3. Write Your Content
+
+Use standard Markdown syntax for your blog post content:
+
+```markdown
+## Section Heading
+
+This is a paragraph with **bold** and *italic* text.
+
+### Code Examples
+
+```javascript
+const example = () => {
+ console.log('Hello from my blog!');
+};
+```
+
+### Lists
+
+- Item 1
+- Item 2
+- Item 3
+
+### Links
+
+Check out [SvelteKit](https://kit.svelte.dev) for more information.
+```
+
+## Frontmatter Reference
+
+| Field | Type | Required | Description |
+|-------|------|----------|-------------|
+| `title` | string | ✅ | Post title displayed in listings and page title |
+| `slug` | string | ✅ | URL-friendly identifier for the post |
+| `excerpt` | string | ✅ | Short description for listings and meta tags |
+| `publishedAt` | string | ✅ | Publication date in YYYY-MM-DD format |
+| `author` | string | ✅ | Author name |
+| `tags` | array | ✅ | Array of tags for categorization |
+| `featured` | boolean | ❌ | Whether to feature this post (default: false) |
+
+## Svelte 5 Integration
+
+### Component-Based Rendering
+
+This implementation uses Svelte 5's component system. Each markdown file is compiled to a Svelte component:
+
+```typescript
+export interface BlogPost {
+ title: string;
+ slug: string;
+ excerpt: string;
+ publishedAt: string;
+ author: string;
+ tags: string[];
+ featured: boolean;
+ component?: any; // The Svelte component for rendering
+}
+```
+
+### Rendering Posts
+
+Posts are rendered using `svelte:component`:
+
+```svelte
+
+{#if post.component}
+
Content not available.
+{/if} +``` + +## Blog Utilities + +### Available Functions + +The blog system provides several utility functions in `src/lib/blog.ts`: + +```typescript +// Get all published posts +const posts = await getAllPosts(); + +// Get a specific post by slug +const post = await getPostBySlug('my-post-slug'); + +// Get featured posts only +const featured = await getFeaturedPosts(); + +// Get posts with a specific tag +const tagged = await getPostsByTag('tutorial'); + +// Get all unique tags +const tags = await getAllTags(); +``` + +### Helper Functions + +Additional utilities in `src/lib/blog-utils.ts`: + +```typescript +// Generate URL-friendly slug from title +const slug = generateSlug('My Blog Post Title'); + +// Create a new post template +const template = createPostTemplate('New Post', 'Author Name'); + +// Validate post metadata +const errors = validatePostMetadata(postData); + +// Search posts +const results = searchPosts(allPosts, 'keyword'); + +// Get related posts +const related = getRelatedPosts(currentPost, allPosts, 3); +``` + +## Styling and Layout + +### Custom Prose Styles + +The blog uses Tailwind's typography plugin with custom styling: + +```css +.prose { + @apply text-surface-900-50-token max-w-none; +} + +.prose h1 { + @apply text-3xl font-bold mb-6; +} + +.prose code { + @apply bg-surface-200 dark:bg-surface-700 px-1 py-0.5 rounded; +} +``` + +### MDX Layout Component + +The `MDXLayout.svelte` component provides consistent styling for markdown content and can be customized for your design needs. + +## Configuration + +### MDSvex Configuration + +The markdown processing is configured in `svelte.config.js`: + +```javascript +const mdsvexOptions = { + extensions: ['.md'], + layout: { + _: './src/lib/components/MDXLayout.svelte' + }, + remarkPlugins: [remarkUnwrapImages, remarkToc, remarkAbbr], + rehypePlugins: [rehypeSlug], + highlight: { + highlighter: async (code, lang) => { + const shiki = await import('shiki'); + const highlighter = await shiki.getHighlighter({ + themes: ['github-dark', 'github-light'], + langs: ['javascript', 'typescript', 'html', 'css', 'svelte', 'bash', 'json', 'yaml', 'python', 'rust', 'go'] + }); + + const html = highlighter.codeToHtml(code, { + lang, + themes: { + light: 'github-light', + dark: 'github-dark' + } + }); + + return html; + } + } +}; +``` + +### Available Plugins + +- **remark-unwrap-images**: Removes paragraph wrappers around images +- **remark-toc**: Generates table of contents from headings +- **remark-abbr**: Processes abbreviation definitions +- **rehype-slug**: Adds IDs to headings for anchor links +- **shiki**: Syntax highlighting for code blocks + +## SEO Features + +### Automatic Meta Tags + +Each blog post automatically generates: + +- Page title with post title +- Meta description from excerpt +- Open Graph tags for social sharing +- Article metadata (published date, author, tags) + +### Example Generated Meta Tags + +```html +Beautiful, consistent styling throughout.
+{errorInfo.description}
+ {#if message} +{message}
+Still having trouble? Here are some helpful links:
+ ++ The complete SvelteKit & Supabase template with authentication, payments, and beautiful UI components. + Skip the boilerplate and focus on what matters most. +
+Faster Development
+Components Ready
+Type Safe
+Possibilities
++ Authentication, real-time database, and file storage configured out of the box. + Just add your Supabase credentials and you're ready to go. +
++ Built with SvelteKit for maximum performance. Server-side rendering, + optimistic updates, and blazing fast navigation included. +
++ TypeScript, ESLint, Prettier, and comprehensive documentation. + Built by developers, for developers with love and attention to detail. +
+SvelteKit
+Supabase
+TypeScript
+Skeleton UI
+Join thousands of developers who trust our template to kickstart their SaaS projects.
++ Manage your account, monitor usage, and access all your SaaS features from your personalized + dashboard. +
+{stat.label}
+{action.description}
+ + {#if action.available} + + {action.action} + + {:else} + + {/if} ++ You're currently on our free Starter plan. Upgrade to unlock advanced features, higher + limits, and priority support. +
++ Start using our services to see your activity here. Create your first project or make an + API call to get started. +
++ You need to be logged in to access your dashboard. Please sign in to continue. +
+ +Please wait while we prepare your personalized experience.
++ {#if activeTab === 'login'} + Sign in to your account to access your dashboard and manage your projects. + {:else} + Create your account to start building with our comprehensive SaaS template. + {/if} +
+{message}
++ By creating an account, you agree to our + Terms of Service + and + Privacy Policy. +
+ {/if} + + + {#if activeTab === 'login'} + + {/if} + + ++ Don't have an account? + +
+ {:else} ++ Already have an account? + +
+ {/if} + ++ Enter your email address and we'll send you a link to reset your password. +
++ We've sent password reset instructions to {email} +
++ Didn't receive the email? Check your spam folder or try again. +
+ ++ Choose a strong password to secure your account. +
++ Insights, tutorials, and updates from our team. Stay up to date with the latest in SaaS development and best practices. +
+{data.error}
+{post.excerpt}
+ +{post.excerpt}
+ ++ We're working on some great content for you. Check back soon for insights, tutorials, and updates! +
+{post.excerpt}
+Failed to load blog post content.
+ +Content not available.
++ Have questions? We'd love to hear from you. Send us a message and we'll respond as soon as possible. +
+support@sassy.dev
++1 (555) 123-4567
+San Francisco, CA
++ We typically respond within 24 hours during business days. +
+Fill out the form below and we'll get back to you.
+Quick answers to common questions.
++ Simply sign up for an account and you'll have immediate access to our platform. Check out our pricing page for plan details. +
++ Yes! We provide comprehensive technical support via email and our help center. Premium plans include priority support. +
++ Absolutely. You can cancel your subscription at any time from your dashboard. Your access will continue until the end of your billing period. +
++ Yes! We offer a 14-day free trial for all new users. No credit card required to get started. +
++ Choose the perfect plan for your needs. Start free and scale as you grow. + No hidden fees, no surprises. +
+{plan.description}
+Billed monthly
+ {/if} ++ Yes! You can upgrade, downgrade, or cancel your subscription at any time. + Changes take effect on your next billing cycle. +
++ Our Starter plan is completely free forever. Pro plans include a 14-day free trial + with no credit card required. +
++ We accept all major credit cards, PayPal, and bank transfers for Enterprise plans. + All payments are processed securely through Stripe. +
++ Yes! We offer a 30-day money-back guarantee for all paid plans. + No questions asked. +
++ Enterprise teams with specific requirements can get in touch for custom pricing and features. +
++ We take your privacy seriously. This policy explains how we collect, use, and protect your personal information. +
++ We collect information you provide directly to us, such as when you create an account, + update your profile, or contact us for support. +
++ We use the information we collect to provide, maintain, and improve our services. +
++ We do not sell, trade, or otherwise transfer your personal information to third parties + except as described in this policy. +
++ We implement appropriate security measures to protect your personal information against + unauthorized access, alteration, disclosure, or destruction. +
++ You have certain rights regarding your personal information: +
++ We retain your personal information for as long as necessary to provide our services + and fulfill the purposes outlined in this policy, unless a longer retention period + is required by law. +
++ We use cookies and similar technologies to enhance your experience, analyze usage, + and provide personalized content. +
++ You can control cookie settings through your browser preferences. However, + disabling cookies may affect the functionality of our service. +
++ Your information may be transferred to and processed in countries other than your own. + We ensure appropriate safeguards are in place to protect your data. +
++ We may update this privacy policy from time to time. We will notify you of any + material changes by posting the new policy on this page and updating the + "last updated" date. +
++ If you have any questions about this privacy policy or our data practices, + please don't hesitate to contact us. +
+ ++ These terms govern your use of our platform. Please read them carefully before using our services. +
++ By accessing or using our SaaS platform ("Service"), you agree to be bound by these + Terms of Service ("Terms"). If you disagree with any part of these terms, you may not access the Service. +
++ Our platform provides software-as-a-service solutions including but not limited to: +
++ You must provide accurate and complete information when creating an account. + You are responsible for maintaining the confidentiality of your account credentials. +
+ ++ You agree not to use the Service for any unlawful purpose or in any way that could damage, + disable, overburden, or impair the Service. +
++ Subscription fees are billed in advance on a monthly or annual basis. + All fees are non-refundable except as expressly stated in these Terms. +
+ ++ We respect your privacy and handle your data in accordance with our Privacy Policy. + By using the Service, you consent to our collection and use of information as described. +
++ The Service and its original content, features, and functionality are owned by us and + are protected by international copyright, trademark, patent, and other intellectual property laws. +
++ We grant you a limited, non-exclusive, non-transferable license to use the Service + for your internal business purposes in accordance with these Terms. +
++ We strive to maintain high availability but do not guarantee uninterrupted access to the Service. + We may perform maintenance, updates, or modifications that temporarily affect availability. +
++ You may terminate your account at any time through your account settings. + Your access will continue until the end of your current billing period. +
+ ++ We may terminate or suspend your account immediately for violations of these Terms, + illegal activities, or non-payment of fees. +
++ To the maximum extent permitted by law, we shall not be liable for any indirect, + incidental, special, consequential, or punitive damages arising from your use of the Service. +
++ You agree to indemnify and hold us harmless from any claims, damages, or expenses + arising from your use of the Service or violation of these Terms. +
++ These Terms shall be governed by and construed in accordance with the laws of + [Your Jurisdiction], without regard to its conflict of law provisions. +
++ We reserve the right to modify these Terms at any time. We will notify users of + material changes via email or through the Service. Continued use constitutes acceptance of updated Terms. +
++ If you have any questions about these Terms of Service, please contact our legal team. +
+ +