Skip to content

Commit

Permalink
feat: seo
Browse files Browse the repository at this point in the history
  • Loading branch information
pushpak1300 committed Jan 12, 2025
1 parent 9428bdd commit c204f0c
Show file tree
Hide file tree
Showing 18 changed files with 139 additions and 67 deletions.
3 changes: 3 additions & 0 deletions app/Http/Controllers/WelcomeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public function home(): Response
return Inertia::render('Welcome', [
'canLogin' => Route::has('login'),
'canRegister' => Route::has('register'),
'seo' => [
'title' => 'Home',
]
]);
}
}
Binary file modified bun.lockb
Binary file not shown.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
"@tailwindcss/forms": "^0.5.9",
"@tailwindcss/typography": "^0.5.15",
"@tanstack/vue-table": "^8.20.5",
"@unhead/addons": "^1.11.15",
"@unhead/vue": "^1.11.15",
"@unovis/ts": "^1.4.5",
"@unovis/vue": "^1.4.5",
"@vee-validate/zod": "^4.14.7",
Expand Down
48 changes: 48 additions & 0 deletions resources/js/Composables/useSeoMetaTags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { useSeoMeta } from '@unhead/vue'

// Default SEO meta tags
const defaultSeoMeta = {
title: 'Home',
titleTemplate: '%s | Larasonic Modern Laravel SaaS Starter Kit',
description: 'Larasonic is a modern Laravel boilerplate for the VILT stack (Vue, Inertia, Laravel, TailwindCSS). Clone and start building scalable, maintainable, and production-ready applications quickly.',
keywords: 'Larasonic, Laravel boilerplate, Laravel VILT, Vue, Inertia, TailwindCSS, Laravel Octane, Docker, FilamentPHP, OpenAI integration, Laravel Cashier, Laravel Sanctum',
robots: 'index, follow',
themeColor: '#000000',

// Open Graph
ogTitle: '%s | Larasonic Modern Laravel SaaS Starter Kit',
ogDescription: 'Larasonic is a modern Laravel SaaS starter kit for the VILT stack. Clone the repo, start building scalable and maintainable applications quickly.',
ogUrl: 'https://larasonic.com',
ogType: 'website',
ogImage: 'https://larasonic.com/images/og.webp',
ogSiteName: 'Larasonic',
ogLocale: 'en_US',

// Twitter
twitterTitle: '%s | Larasonic Modern Laravel SaaS Starter Kit',
twitterDescription: 'Larasonic is a modern Laravel SaaS starter kit for the VILT stack. Clone the repo, start building scalable and maintainable applications quickly.',
twitterCard: 'summary_large_image',
twitterImage: 'https://larasonic.com/images/og.webp',
twitterSite: '@pushpak1300',
}

/**
* Composable for managing SEO meta tags
* @param {object|null} seoMeta - Custom SEO meta tags to apply
* @param {object} options - Configuration options
* @param {boolean} options.merge - When true, merges custom meta tags with defaults.
* When false, only uses custom meta tags.
* Useful for pages that need completely custom SEO
* without inheriting defaults.
* @returns {void}
*/
export function useSeoMetaTags(seoMeta, options = { merge: true }) {
if (!seoMeta)
return useSeoMeta(defaultSeoMeta)

return useSeoMeta(
options.merge
? { ...defaultSeoMeta, ...seoMeta }
: seoMeta,
)
}
9 changes: 6 additions & 3 deletions resources/js/Layouts/AppLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ import SidebarMenuItem from '@/Components/shadcn/ui/sidebar/SidebarMenuItem.vue'
import SidebarProvider from '@/Components/shadcn/ui/sidebar/SidebarProvider.vue'
import SidebarTrigger from '@/Components/shadcn/ui/sidebar/SidebarTrigger.vue'
import Sonner from '@/Components/shadcn/ui/sonner/Sonner.vue'
import { Head } from '@inertiajs/vue3'
import { useSeoMetaTags } from '@/Composables/useSeoMetaTags.js'
defineProps({
const props = defineProps({
title: String,
})
useSeoMetaTags({
title: props.title,
})
</script>

<template>
<div>
<Head :title="title" />
<Sonner position="top-center" />
<SidebarProvider>
<Sidebar collapsible="icon">
Expand Down
9 changes: 6 additions & 3 deletions resources/js/Pages/Auth/ConfirmPassword.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ import Button from '@/Components/shadcn/ui/button/Button.vue'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/Components/shadcn/ui/card'
import Input from '@/Components/shadcn/ui/input/Input.vue'
import Label from '@/Components/shadcn/ui/label/Label.vue'
import { Head, useForm } from '@inertiajs/vue3'
import { useSeoMetaTags } from '@/Composables/useSeoMetaTags.js'
import { useForm } from '@inertiajs/vue3'
import { inject, ref } from 'vue'
const route = inject('route')
const form = useForm({
password: '',
})
useSeoMetaTags({
title: 'Confirm Password',
})
const passwordInput = ref(null)
function submit() {
Expand All @@ -26,8 +31,6 @@ function submit() {
</script>

<template>
<Head title="Secure Area" />

<div class="flex min-h-screen flex-col items-center justify-center">
<Card class="mx-auto max-w-lg">
<CardHeader>
Expand Down
11 changes: 7 additions & 4 deletions resources/js/Pages/Auth/ForgotPassword.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ import AuthenticationCardLogo from '@/Components/LogoRedirect.vue'
import Button from '@/Components/shadcn/ui/button/Button.vue'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/Components/shadcn/ui/card'
import Input from '@/Components/shadcn/ui/input/Input.vue'
import Label from '@/Components/shadcn/ui/label/Label.vue'
import { Head, useForm } from '@inertiajs/vue3'
import { useSeoMetaTags } from '@/Composables/useSeoMetaTags.js'
import { useForm } from '@inertiajs/vue3'
import { inject } from 'vue'
defineProps({
status: String,
})
useSeoMetaTags({
title: 'Forgot Password',
})
const route = inject('route')
const form = useForm({
email: '',
Expand All @@ -23,8 +28,6 @@ function submit() {
</script>

<template>
<Head title="Forgot Password" />

<div class="flex min-h-screen flex-col items-center justify-center">
<Card class="mx-auto max-w-lg">
<CardHeader>
Expand Down
8 changes: 6 additions & 2 deletions resources/js/Pages/Auth/Login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import Input from '@/Components/shadcn/ui/input/Input.vue'
import Label from '@/Components/shadcn/ui/label/Label.vue'
import Sonner from '@/Components/shadcn/ui/sonner/Sonner.vue'
import SocialLoginButton from '@/Components/SocialLoginButton.vue'
import { useSeoMetaTags } from '@/Composables/useSeoMetaTags.js'
import { cn } from '@/lib/utils'
import { Head, Link, useForm, usePage } from '@inertiajs/vue3'
import { Link, useForm, usePage } from '@inertiajs/vue3'
import { inject, onMounted } from 'vue'
import { toast } from 'vue-sonner'
Expand All @@ -22,6 +23,10 @@ defineProps({
const page = usePage()
const route = inject('route')
useSeoMetaTags({
title: 'Log in',
})
const form = useForm({
email: 'test@example.com',
password: 'password',
Expand All @@ -44,7 +49,6 @@ onMounted(() => {
</script>

<template>
<Head title="Log in" />
<Sonner position="top-center" />
<div class="flex min-h-screen flex-col items-center justify-center">
<Card class="mx-auto max-w-lg" :class="cn('w-[380px]')">
Expand Down
9 changes: 6 additions & 3 deletions resources/js/Pages/Auth/Register.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/Com
import Checkbox from '@/Components/shadcn/ui/checkbox/Checkbox.vue'
import Input from '@/Components/shadcn/ui/input/Input.vue'
import Label from '@/Components/shadcn/ui/label/Label.vue'
import { Head, Link, useForm } from '@inertiajs/vue3'
import { useSeoMetaTags } from '@/Composables/useSeoMetaTags.js'
import { Link, useForm } from '@inertiajs/vue3'
import { inject } from 'vue'
useSeoMetaTags({
title: 'Register',
})
const route = inject('route')
const form = useForm({
name: '',
Expand All @@ -27,8 +32,6 @@ function submit() {
</script>

<template>
<Head title="Register" />

<div class="flex min-h-screen flex-col items-center justify-center">
<Card class="mx-auto max-w-lg">
<CardHeader>
Expand Down
10 changes: 7 additions & 3 deletions resources/js/Pages/Auth/ResetPassword.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/Com
import Input from '@/Components/shadcn/ui/input/Input.vue'
import Label from '@/Components/shadcn/ui/label/Label.vue'
import { useSeoMetaTags } from '@/Composables/useSeoMetaTags.js'
import { cn } from '@/lib/utils'
import { Head, useForm } from '@inertiajs/vue3'
import { useForm } from '@inertiajs/vue3'
import { inject } from 'vue'
const props = defineProps({
email: String,
token: String,
})
useSeoMetaTags({
title: 'Register',
})
const route = inject('route')
const form = useForm({
token: props.token,
Expand All @@ -32,8 +38,6 @@ function submit() {
</script>

<template>
<Head title="Reset Password" />

<div class="flex min-h-screen flex-col items-center justify-center">
<Card class="mx-auto max-w-lg" :class="cn('w-[380px]')">
<CardHeader>
Expand Down
9 changes: 6 additions & 3 deletions resources/js/Pages/Auth/TwoFactorChallenge.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@ import Button from '@/Components/shadcn/ui/button/Button.vue'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/Components/shadcn/ui/card'
import Input from '@/Components/shadcn/ui/input/Input.vue'
import Label from '@/Components/shadcn/ui/label/Label.vue'
import { useSeoMetaTags } from '@/Composables/useSeoMetaTags.js'
import { Head, useForm } from '@inertiajs/vue3'
import { useForm } from '@inertiajs/vue3'
import { inject, nextTick, ref } from 'vue'
useSeoMetaTags({
title: 'Two-factor Confirmation',
})
const route = inject('route')
const recovery = ref(false)
Expand Down Expand Up @@ -41,8 +46,6 @@ function submit() {
</script>

<template>
<Head title="Two-factor Confirmation" />

<div class="flex min-h-screen flex-col items-center justify-center">
<Card class="mx-auto max-w-lg">
<CardHeader>
Expand Down
9 changes: 6 additions & 3 deletions resources/js/Pages/Auth/VerifyEmail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@
import AuthenticationCardLogo from '@/Components/LogoRedirect.vue'
import Button from '@/Components/shadcn/ui/button/Button.vue'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/Components/shadcn/ui/card'
import { Head, Link, useForm } from '@inertiajs/vue3'
import { useSeoMetaTags } from '@/Composables/useSeoMetaTags.js'
import { Link, useForm } from '@inertiajs/vue3'
import { computed, inject } from 'vue'
const props = defineProps({
status: String,
})
useSeoMetaTags({
title: 'Email Verification',
})
const route = inject('route')
const form = useForm({})
Expand All @@ -21,8 +26,6 @@ const verificationLinkSent = computed(() => props.status === 'verification-link-
</script>

<template>
<Head title="Email Verification" />

<div class="flex min-h-screen flex-col items-center justify-center">
<Card class="mx-auto max-w-lg">
<CardHeader>
Expand Down
8 changes: 5 additions & 3 deletions resources/js/Pages/PrivacyPolicy.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
<script setup>
import AuthenticationCardLogo from '@/Components/LogoRedirect.vue'
import { Head } from '@inertiajs/vue3'
import { useSeoMetaTags } from '@/Composables/useSeoMetaTags';
defineProps({
policy: String,
})
useSeoMetaTags({
title: 'Privacy Policy',
})
</script>

<template>
<Head title="Privacy Policy" />

<div class="font-sans antialiased">
<div class="pt-4">
<div class="flex min-h-screen flex-col items-center pt-6 sm:pt-0">
Expand Down
8 changes: 5 additions & 3 deletions resources/js/Pages/TermsOfService.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
<script setup>
import AuthenticationCardLogo from '@/Components/LogoRedirect.vue'
import { Head } from '@inertiajs/vue3'
import { useSeoMetaTags } from '@/Composables/useSeoMetaTags';
defineProps({
terms: String,
})
useSeoMetaTags({
title: 'Terms of Service',
})
</script>

<template>
<Head title="Terms of Service" />

<div class="font-sans antialiased">
<div class="pt-4">
<div class="flex min-h-screen flex-col items-center pt-6 sm:pt-0">
Expand Down
13 changes: 9 additions & 4 deletions resources/js/Pages/Welcome.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,26 @@ import AccordionTrigger from '@/Components/shadcn/ui/accordion/AccordionTrigger.
import Badge from '@/Components/shadcn/ui/badge/Badge.vue'
import Button from '@/Components/shadcn/ui/button/Button.vue'
import Terminal from '@/Components/Terminal.vue'
import { useSeoMetaTags } from '@/Composables/useSeoMetaTags.js'
import WebLayout from '@/Layouts/WebLayout.vue'
import { Icon } from '@iconify/vue'
import { Head, Link } from '@inertiajs/vue3'
import { Link } from '@inertiajs/vue3'
defineProps({
const props = defineProps({
canLogin: {
type: Boolean,
},
canRegister: {
type: Boolean,
},
seo: {
type: Object,
default: () => null,
},
})
useSeoMetaTags(props.seo)
const features = [
{
icon: '🚀',
Expand Down Expand Up @@ -105,8 +112,6 @@ const githubUrl = 'https://github.com/pushpak1300/larasonic'

<template>
<WebLayout :can-login="canLogin" :can-register="canRegister">
<Head title="Build Faster with Larasonic" />

<!-- Hero Section -->
<section class="relative overflow-hidden border-b bg-background py-20 sm:py-32">
<div class="container mx-auto px-4 text-center">
Expand Down
Loading

0 comments on commit c204f0c

Please sign in to comment.