mirror of
https://github.com/LukeHagar/Sveltey.git
synced 2025-12-06 04:21:38 +00:00
Styling and breaking out the components, also readme updates
This commit is contained in:
81
README.md
81
README.md
@@ -25,6 +25,10 @@ A modern, production-ready SaaS template built with [SvelteKit 2](https://kit.sv
|
||||
- [🔧 Configuration](#-configuration)
|
||||
- [Environment Variables](#environment-variables)
|
||||
- [Supabase Setup](#supabase-setup)
|
||||
- [Email Setup (Resend)](#email-setup-resend)
|
||||
- [Email Features](#email-features)
|
||||
- [Example Usage](#example-usage)
|
||||
- [Email Template example](#email-template-example)
|
||||
- [Stripe Setup](#stripe-setup)
|
||||
- [Analytics Setup (Plausible)](#analytics-setup-plausible)
|
||||
- [Current Configuration](#current-configuration)
|
||||
@@ -119,6 +123,7 @@ Visit `http://localhost:5173` and start building your SaaS!
|
||||
- **UI Components**: Skeleton UI
|
||||
- **Styling**: Tailwind CSS
|
||||
- **Analytics**: Plausible Analytics
|
||||
- **Email**: Resend
|
||||
<!-- - **Payments**: Stripe -->
|
||||
- **Deployment**: Vercel/Netlify ready
|
||||
- **Language**: TypeScript
|
||||
@@ -159,6 +164,9 @@ Create a `.env` file in the root directory:
|
||||
PUBLIC_SUPABASE_URL=your_supabase_url
|
||||
PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
|
||||
|
||||
# Resend (for email)
|
||||
RESEND_API_KEY=your_resend_api_key
|
||||
|
||||
# Stripe // coming soon
|
||||
PUBLIC_STRIPE_PUBLISHABLE_KEY=your_stripe_publishable_key
|
||||
STRIPE_SECRET_KEY=your_stripe_secret_key
|
||||
@@ -173,6 +181,79 @@ STRIPE_WEBHOOK_SECRET=your_webhook_secret
|
||||
3. Run the included SQL migrations
|
||||
4. Set up your authentication providers
|
||||
|
||||
### Email Setup (Resend)
|
||||
|
||||
Sveltey uses [Resend](https://resend.com/) for reliable email delivery with excellent developer experience.
|
||||
|
||||
1. **Create a Resend account** at [resend.com](https://resend.com/)
|
||||
2. **Get your API key** from the Resend dashboard
|
||||
3. **Add to environment variables**:
|
||||
```env
|
||||
RESEND_API_KEY=re_your_api_key_here
|
||||
```
|
||||
4. **Verify your domain** (optional but recommended for production):
|
||||
- Add your domain in the Resend dashboard
|
||||
- Configure DNS records as instructed
|
||||
- This removes the "via resend.com" branding and improves deliverability
|
||||
|
||||
#### Email Features
|
||||
|
||||
- **Transactional Emails**: Password resets, welcome emails, notifications
|
||||
- **Template Support**: Beautiful HTML email templates
|
||||
- **Delivery Tracking**: Monitor email delivery and engagement
|
||||
- **High Deliverability**: Excellent inbox placement rates
|
||||
- **Simple API**: Easy integration with SvelteKit API routes
|
||||
|
||||
#### Example Usage
|
||||
|
||||
```typescript
|
||||
// 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: 'noreply@yourdomain.com',
|
||||
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' }
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Email Template example
|
||||
|
||||
Create reusable email templates in `src/lib/emails/`:
|
||||
|
||||
```typescript
|
||||
// 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;">Welcome to Sveltey, ${userName}!</h1>
|
||||
<p>Thank you for joining our platform. We're excited to have you on board.</p>
|
||||
<a href="https://yourdomain.com/dashboard"
|
||||
style="background: #007bff; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px;">
|
||||
Get Started
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
```
|
||||
|
||||
### Stripe Setup
|
||||
|
||||
1. Create a Stripe account
|
||||
|
||||
90
src/lib/components/Footer.svelte
Normal file
90
src/lib/components/Footer.svelte
Normal file
@@ -0,0 +1,90 @@
|
||||
<script>
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<footer class="bg-surface-100-850-token border-surface-500 mt-20 border-t">
|
||||
<div class="container mx-auto px-4 py-12 md:px-6">
|
||||
<div class="grid grid-cols-1 gap-8 md:grid-cols-4">
|
||||
<!-- Brand Column -->
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="bg-primary-500 flex h-8 w-8 items-center justify-center rounded-lg">
|
||||
<span class="text-lg font-bold text-white">S</span>
|
||||
</div>
|
||||
<span class="text-xl font-bold">Sveltey</span>
|
||||
</div>
|
||||
<p class="text-sm opacity-75">
|
||||
The complete SvelteKit & Supabase SaaS template. Launch your next project in minutes, not
|
||||
months.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Product Links -->
|
||||
<div class="space-y-4">
|
||||
<h3 class="font-semibold">Product</h3>
|
||||
<div class="space-y-2 text-sm">
|
||||
<a href="/pricing" class="block opacity-75 transition-opacity hover:opacity-100"
|
||||
>Pricing</a
|
||||
>
|
||||
<a href="/blog" class="block opacity-75 transition-opacity hover:opacity-100">Blog</a>
|
||||
<a href="/dashboard" class="block opacity-75 transition-opacity hover:opacity-100"
|
||||
>Dashboard</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Support Links -->
|
||||
<div class="space-y-4">
|
||||
<h3 class="font-semibold">Support</h3>
|
||||
<div class="space-y-2 text-sm">
|
||||
<a
|
||||
href="https://github.com/LukeHagar/sveltey"
|
||||
class="block opacity-75 transition-opacity hover:opacity-100"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
<a href="/contact" class="block opacity-75 transition-opacity hover:opacity-100">
|
||||
Contact
|
||||
</a>
|
||||
<a href="/help" class="block opacity-75 transition-opacity hover:opacity-100">
|
||||
Help Center
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Legal Links -->
|
||||
<div class="space-y-4">
|
||||
<h3 class="font-semibold">Legal</h3>
|
||||
<div class="space-y-2 text-sm">
|
||||
<a href="/privacy" class="block opacity-75 transition-opacity hover:opacity-100">
|
||||
Privacy Policy
|
||||
</a>
|
||||
<a href="/terms" class="block opacity-75 transition-opacity hover:opacity-100">
|
||||
Terms of Service
|
||||
</a>
|
||||
<a href="/cookies" class="block opacity-75 transition-opacity hover:opacity-100">
|
||||
Cookie Policy
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer Bottom -->
|
||||
<div
|
||||
class="border-surface-300-600-token mt-8 flex flex-col items-center justify-between border-t pt-8 md:flex-row"
|
||||
>
|
||||
<p class="text-sm opacity-50">© 2025 Sveltey. All rights reserved.</p>
|
||||
<div class="mt-4 flex flex-wrap items-center justify-center gap-4 md:mt-0">
|
||||
<span class="text-sm opacity-50">Built with</span>
|
||||
<div class="flex items-center gap-2 text-sm opacity-75">
|
||||
<a class="anchor" href="https://kit.svelte.dev/" target="_blank">SvelteKit</a>
|
||||
<span>•</span>
|
||||
<a class="anchor" href="https://supabase.com/" target="_blank">Supabase</a>
|
||||
<span>•</span>
|
||||
<a class="anchor" href="https://skeleton.dev/" target="_blank">Skeleton UI</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -9,11 +9,6 @@
|
||||
|
||||
let { session } = $derived(data);
|
||||
|
||||
// Helper function to check if a path is active
|
||||
function isActivePath(path: string): boolean {
|
||||
return page.url.pathname === path;
|
||||
}
|
||||
|
||||
// Helper function to get navigation link classes
|
||||
function getNavClasses(path: string): string {
|
||||
return `btn btn-sm flex items-center gap-2 ${page.url.pathname === path ? 'cursor-default disabled' : ''}`;
|
||||
@@ -23,7 +18,7 @@
|
||||
<header
|
||||
class="bg-surface-50-950-token border-surface-200-700-token sticky top-0 z-50 border-b backdrop-blur-2xl"
|
||||
>
|
||||
<nav class="container mx-auto px-6 py-4">
|
||||
<nav class="container mx-auto px-2 py-2 md:py-4 md:px-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<!-- Left side - Brand and Main navigation -->
|
||||
<div class="flex items-center gap-8">
|
||||
@@ -95,7 +90,7 @@
|
||||
</div>
|
||||
{:else}
|
||||
<!-- Authentication Buttons -->
|
||||
<div class="hidden md:flex items-center gap-1 md:gap-3 ">
|
||||
<div class="hidden items-center gap-1 md:flex md:gap-3">
|
||||
<a href="/auth" class={getNavClasses('/auth')} aria-label="Sign in or register">
|
||||
<User class="size-4" aria-hidden="true" />
|
||||
<span class="">Sign In / Register</span>
|
||||
@@ -104,12 +99,12 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="block pt-4 md:hidden">
|
||||
<nav class="flex flex-wrap items-center justify-center gap-4">
|
||||
<div class="block pt-2 md:hidden">
|
||||
<nav class="flex flex-wrap items-center justify-center gap-1">
|
||||
<a href="/" class={getNavClasses('/')} aria-label="Go to homepage">
|
||||
<Home class="size-4" aria-hidden="true" />
|
||||
Home
|
||||
</a>
|
||||
<Home class="size-4" aria-hidden="true" />
|
||||
Home
|
||||
</a>
|
||||
<a href="/pricing" class={getNavClasses('/pricing')} aria-label="View pricing plans">
|
||||
<DollarSign class="size-4" aria-hidden="true" />
|
||||
Pricing
|
||||
@@ -131,7 +126,7 @@
|
||||
{:else}
|
||||
<a href="/auth" class={getNavClasses('/auth')} aria-label="Sign in or register">
|
||||
<User class="size-4" aria-hidden="true" />
|
||||
Sign In / Register
|
||||
Sign In / Up
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
</div>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
{#each featuredPosts as post}
|
||||
<a href="/blog/{post.slug}" class="card preset-outlined-primary-500 p-6 md:p-8 space-y-4 hover:scale-105 hover:shadow-2xl transition-all duration-300 group">
|
||||
<a href="/blog/{post.slug}" class="card preset-outlined-primary-500 p-6 md:p-8 space-y-4 hover:scale-105 hover:shadow-2xl transition-all duration-300 group flex flex-col">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-1 text-sm opacity-75">
|
||||
<Calendar class="size-4" />
|
||||
@@ -52,7 +52,7 @@
|
||||
</div>
|
||||
</h3>
|
||||
|
||||
<p class="opacity-75">{post.excerpt}</p>
|
||||
<p class="opacity-75 grow">{post.excerpt}</p>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-1">
|
||||
{#each post.tags.slice(0, 2) as tag}
|
||||
<span class="badge preset-outlined-surface-200-800 text-xs flex items-center gap-1">
|
||||
<span class="badge preset-outlined-surface-500 text-xs flex items-center gap-1">
|
||||
<Tag class="size-3" />
|
||||
{tag}
|
||||
</span>
|
||||
@@ -105,7 +105,7 @@
|
||||
{#if post.tags.length > 0}
|
||||
<div class="flex flex-wrap gap-1">
|
||||
{#each post.tags.slice(0, 3) as tag}
|
||||
<span class="badge preset-outlined-surface-200-800 text-xs flex items-center gap-1">
|
||||
<span class="badge preset-outlined-surface-500 text-xs flex items-center gap-1">
|
||||
<Tag class="size-3" />
|
||||
{tag}
|
||||
</span>
|
||||
@@ -119,7 +119,7 @@
|
||||
</section>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="card preset-outlined-surface-200-800 p-8 md:p-12 text-center max-w-2xl mx-auto space-y-4">
|
||||
<div class="card preset-outlined-surface-500 p-8 md:p-12 text-center max-w-2xl mx-auto space-y-4">
|
||||
<BookOpen class="size-16 mx-auto text-primary-500 opacity-50" />
|
||||
<h2 class="h3">No blog posts yet</h2>
|
||||
<p class="opacity-75">
|
||||
|
||||
@@ -188,7 +188,7 @@
|
||||
Enterprise teams with specific requirements can get in touch for custom pricing and features.
|
||||
</p>
|
||||
</div>
|
||||
<a href="mailto:sales@example.com" class="btn btn-lg preset-filled-secondary-500 text-surface-50-950">
|
||||
<a href="mailto:sales@example.com" class="btn btn-lg preset-filled-secondary-500">
|
||||
<Mail class="size-5" />
|
||||
<span>Contact Sales</span>
|
||||
</a>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Error Description -->
|
||||
<div class="card preset-outlined-surface-200-800 p-8 space-y-4">
|
||||
<div class="card preset-outlined-surface-500 p-8 space-y-4">
|
||||
<p class="text-lg opacity-75">{errorInfo.description}</p>
|
||||
{#if message}
|
||||
<div class="card preset-outlined-error-500 p-4">
|
||||
@@ -73,7 +73,7 @@
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<button
|
||||
onclick={() => window.history.back()}
|
||||
class="btn preset-outlined-surface-200-800 flex items-center gap-2"
|
||||
class="btn preset-outlined-surface-500 flex items-center gap-2"
|
||||
aria-label="Go back to previous page"
|
||||
title="Go back to previous page"
|
||||
>
|
||||
@@ -83,7 +83,7 @@
|
||||
|
||||
<button
|
||||
onclick={() => window.location.reload()}
|
||||
class="btn preset-outlined-surface-200-800 flex items-center gap-2"
|
||||
class="btn preset-outlined-surface-500 flex items-center gap-2"
|
||||
aria-label="Reload current page"
|
||||
title="Reload current page"
|
||||
>
|
||||
@@ -103,14 +103,14 @@
|
||||
</div>
|
||||
|
||||
<!-- Help Section -->
|
||||
<div class="text-sm opacity-50 space-y-2">
|
||||
<div class="text-sm space-y-2">
|
||||
<p>Still having trouble? Here are some helpful links:</p>
|
||||
<div class="flex items-center justify-center gap-4">
|
||||
<a href="/blog" class="hover:opacity-75 transition-opacity">Blog</a>
|
||||
<a href="/blog" class="anchor">Blog</a>
|
||||
<span>•</span>
|
||||
<a href="/contact" class="hover:opacity-75 transition-opacity">Contact Support</a>
|
||||
<a href="/contact" class="anchor">Contact Support</a>
|
||||
<span>•</span>
|
||||
<a href="/help" class="hover:opacity-75 transition-opacity">Help Center</a>
|
||||
<a href="/help" class="anchor">Help Center</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { injectSpeedInsights } from '@vercel/speed-insights/sveltekit';
|
||||
import { Modal, Toaster } from '@skeletonlabs/skeleton-svelte';
|
||||
import { MetaTags, deepMerge } from 'svelte-meta-tags';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { page } from '$app/state';
|
||||
import { toaster } from '$lib';
|
||||
import Header from '$lib/components/Header.svelte';
|
||||
import { Modal, Toaster } from '@skeletonlabs/skeleton-svelte';
|
||||
import { injectSpeedInsights } from '@vercel/speed-insights/sveltekit';
|
||||
import 'prism-themes/themes/prism-vsc-dark-plus.css';
|
||||
import { onMount } from 'svelte';
|
||||
import { MetaTags, deepMerge } from 'svelte-meta-tags';
|
||||
import { toaster } from '$lib';
|
||||
|
||||
import Footer from '$lib/components/Footer.svelte';
|
||||
import Header from '$lib/components/Header.svelte';
|
||||
|
||||
import 'prism-themes/themes/prism-vsc-dark-plus.css';
|
||||
import '../app.css';
|
||||
|
||||
injectSpeedInsights();
|
||||
try {
|
||||
injectSpeedInsights();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
let { data, children } = $props();
|
||||
let { session, supabase } = $derived(data);
|
||||
@@ -37,16 +44,6 @@
|
||||
return `${baseClasses} preset-ghost-surface-200-800`;
|
||||
}
|
||||
|
||||
// Helper function to get mobile navigation link classes
|
||||
function getMobileNavLinkClasses(path: string): string {
|
||||
const isActive = isActivePath(path);
|
||||
const baseClasses = 'btn flex items-center justify-start gap-2';
|
||||
|
||||
if (isActive) {
|
||||
return `${baseClasses} preset-filled-primary-500 text-on-primary-500 cursor-default`;
|
||||
}
|
||||
return `${baseClasses} preset-ghost-surface-200-800`;
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
// Sync client-side session with server-side on mount
|
||||
@@ -67,97 +64,13 @@
|
||||
<Toaster {toaster}></Toaster>
|
||||
<Modal />
|
||||
|
||||
<!-- Header -->
|
||||
<Header {data} />
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="min-h-screen p-4">
|
||||
{@render children()}
|
||||
<!-- Pass session to child pages -->
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="bg-surface-100-850-token border-surface-200-700-token mt-20 border-t">
|
||||
<div class="container mx-auto px-6 py-12">
|
||||
<div class="grid grid-cols-1 gap-8 md:grid-cols-4">
|
||||
<!-- Brand Column -->
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="bg-primary-500 flex h-8 w-8 items-center justify-center rounded-lg">
|
||||
<span class="text-lg font-bold text-white">S</span>
|
||||
</div>
|
||||
<span class="text-xl font-bold">Sveltey</span>
|
||||
</div>
|
||||
<p class="text-sm opacity-75">
|
||||
The complete SvelteKit & Supabase SaaS template. Launch your next project in minutes, not
|
||||
months.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Product Links -->
|
||||
<div class="space-y-4">
|
||||
<h3 class="font-semibold">Product</h3>
|
||||
<div class="space-y-2 text-sm">
|
||||
<a href="/pricing" class="block opacity-75 transition-opacity hover:opacity-100"
|
||||
>Pricing</a
|
||||
>
|
||||
<a href="/blog" class="block opacity-75 transition-opacity hover:opacity-100">Blog</a>
|
||||
<a href="/dashboard" class="block opacity-75 transition-opacity hover:opacity-100"
|
||||
>Dashboard</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Support Links -->
|
||||
<div class="space-y-4">
|
||||
<h3 class="font-semibold">Support</h3>
|
||||
<div class="space-y-2 text-sm">
|
||||
<a
|
||||
href="https://github.com/LukeHagar/sveltey"
|
||||
class="block opacity-75 transition-opacity hover:opacity-100"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
<a href="/contact" class="block opacity-75 transition-opacity hover:opacity-100">
|
||||
Contact
|
||||
</a>
|
||||
<a href="/help" class="block opacity-75 transition-opacity hover:opacity-100">
|
||||
Help Center
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Legal Links -->
|
||||
<div class="space-y-4">
|
||||
<h3 class="font-semibold">Legal</h3>
|
||||
<div class="space-y-2 text-sm">
|
||||
<a href="/privacy" class="block opacity-75 transition-opacity hover:opacity-100">
|
||||
Privacy Policy
|
||||
</a>
|
||||
<a href="/terms" class="block opacity-75 transition-opacity hover:opacity-100">
|
||||
Terms of Service
|
||||
</a>
|
||||
<a href="/cookies" class="block opacity-75 transition-opacity hover:opacity-100">
|
||||
Cookie Policy
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer Bottom -->
|
||||
<div
|
||||
class="border-surface-300-600-token mt-8 flex flex-col items-center justify-between border-t pt-8 md:flex-row"
|
||||
>
|
||||
<p class="text-sm opacity-50">© 2025 Sveltey. All rights reserved.</p>
|
||||
<div class="mt-4 flex flex-wrap items-center justify-center gap-4 md:mt-0">
|
||||
<span class="text-sm opacity-50">Built with</span>
|
||||
<div class="flex items-center gap-2 text-sm opacity-75">
|
||||
<a class="anchor" href="https://kit.svelte.dev/" target="_blank">SvelteKit</a>
|
||||
<span>•</span>
|
||||
<a class="anchor" href="https://supabase.com/" target="_blank">Supabase</a>
|
||||
<span>•</span>
|
||||
<a class="anchor" href="https://skeleton.dev/" target="_blank">Skeleton UI</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<Footer />
|
||||
|
||||
@@ -57,11 +57,13 @@
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<hr class="hr max-w-48" />
|
||||
<div class="flex justify-center">
|
||||
<hr class="hr border-surface-500 max-w-64" />
|
||||
</div>
|
||||
|
||||
<!-- Stats Section -->
|
||||
<section>
|
||||
<div class="flex gap-20 text-center flex-wrap font-bold justify-between justify-center">
|
||||
<div class="flex gap-20 text-center flex-wrap font-bold justify-center">
|
||||
<div class="space-y-1">
|
||||
<span class="text-7xl">99%</span>
|
||||
<p class="text-primary-500">Faster Development</p>
|
||||
@@ -81,7 +83,9 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr class="hr max-w-48" />
|
||||
<div class="flex justify-center">
|
||||
<hr class="hr border-surface-500 max-w-64" />
|
||||
</div>
|
||||
|
||||
<!-- Features Section -->
|
||||
<section class="flex flex-wrap gap-4">
|
||||
@@ -111,7 +115,9 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr class="hr max-w-48" />
|
||||
<div class="flex justify-center">
|
||||
<hr class="hr border-surface-500 max-w-64" />
|
||||
</div>
|
||||
|
||||
<!-- Technologies Section -->
|
||||
<section class="space-y-8 text-center">
|
||||
@@ -144,7 +150,9 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr class="hr max-w-48" />
|
||||
<div class="flex justify-center">
|
||||
<hr class="hr border-surface-500 max-w-64" />
|
||||
</div>
|
||||
|
||||
<!-- Call to Action Section -->
|
||||
<section class="grid grid-cols-1 items-center gap-4 md:grid-cols-[1fr_auto]">
|
||||
|
||||
Reference in New Issue
Block a user