BReadcrumbs
This commit is contained in:
@@ -1,3 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue';
|
||||
import { useSEO } from '../composables/useSEO';
|
||||
import { useStructuredData } from '../composables/useStructuredData';
|
||||
|
||||
const { addBreadcrumbSchema } = useStructuredData();
|
||||
|
||||
onMounted(() => {
|
||||
useSEO({
|
||||
title: 'About Us - Our Mission & Story',
|
||||
description: 'Learn about Spritesheet Generator, a free tool designed to help game developers and artists streamline their workflow with optimized spritesheet creation.',
|
||||
url: '/about',
|
||||
type: 'website',
|
||||
keywords: 'about spritesheet generator, game development tools, open source sprite editor'
|
||||
});
|
||||
|
||||
addBreadcrumbSchema([
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'About Us', url: '/about' }
|
||||
]);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<div class="bg-white/80 dark:bg-gray-900/80 backdrop-blur-md rounded-3xl shadow-2xl border border-gray-200/50 dark:border-gray-700/50 p-8 sm:p-12">
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useBlog, type BlogPost } from '../composables/useBlog';
|
||||
import { useSEO } from '../composables/useSEO';
|
||||
import { useStructuredData } from '../composables/useStructuredData';
|
||||
import { marked } from 'marked';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const { getPost } = useBlog();
|
||||
const { addBlogPostSchema, addBreadcrumbSchema } = useStructuredData();
|
||||
const post = ref<BlogPost | undefined>(undefined);
|
||||
const renderedContent = ref('');
|
||||
|
||||
@@ -16,6 +19,35 @@
|
||||
|
||||
if (post.value) {
|
||||
renderedContent.value = await marked(post.value.content);
|
||||
|
||||
// Set SEO meta tags
|
||||
useSEO({
|
||||
title: post.value.title,
|
||||
description: post.value.description,
|
||||
image: post.value.image,
|
||||
url: `/blog/${slug}`,
|
||||
type: 'article',
|
||||
author: post.value.author || 'nu11ed',
|
||||
publishedTime: post.value.date,
|
||||
keywords: post.value.keywords || 'sprite sheet, game development, blog'
|
||||
});
|
||||
|
||||
// Add structured data
|
||||
addBlogPostSchema({
|
||||
title: post.value.title,
|
||||
description: post.value.description,
|
||||
author: post.value.author || 'nu11ed',
|
||||
datePublished: post.value.date,
|
||||
image: post.value.image,
|
||||
url: `/blog/${slug}`
|
||||
});
|
||||
|
||||
// Add breadcrumb
|
||||
addBreadcrumbSchema([
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Blog', url: '/blog' },
|
||||
{ name: post.value.title, url: `/blog/${slug}` }
|
||||
]);
|
||||
} else {
|
||||
router.push({ name: 'blog-overview' });
|
||||
}
|
||||
|
||||
@@ -1,13 +1,45 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useBlog, type BlogPost } from '../composables/useBlog';
|
||||
import { useSEO } from '../composables/useSEO';
|
||||
import { useStructuredData } from '../composables/useStructuredData';
|
||||
import { RouterLink } from 'vue-router';
|
||||
|
||||
const { getPosts } = useBlog();
|
||||
const { addBlogListSchema, addBreadcrumbSchema } = useStructuredData();
|
||||
const posts = ref<BlogPost[]>([]);
|
||||
|
||||
onMounted(async () => {
|
||||
posts.value = await getPosts();
|
||||
|
||||
// Set SEO meta tags
|
||||
useSEO({
|
||||
title: 'Blog - Latest Articles on Spritesheet Generation',
|
||||
description: 'Explore our latest articles about sprite sheet generation, game development, pixel art, and sprite animation techniques.',
|
||||
url: '/blog',
|
||||
type: 'website',
|
||||
keywords: 'sprite sheet blog, game development articles, pixel art tutorials, sprite animation'
|
||||
});
|
||||
|
||||
// Add blog list structured data
|
||||
if (posts.value.length > 0) {
|
||||
addBlogListSchema(
|
||||
posts.value.map(post => ({
|
||||
title: post.title,
|
||||
description: post.description,
|
||||
author: post.author || 'nu11ed',
|
||||
datePublished: post.date,
|
||||
image: post.image,
|
||||
url: `/blog/${post.slug}`
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
// Add breadcrumb
|
||||
addBreadcrumbSchema([
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Blog', url: '/blog' }
|
||||
]);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -17,7 +49,7 @@
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<article v-for="post in posts" :key="post.slug" class="bg-white dark:bg-gray-800 rounded-lg shadow-md overflow-hidden hover:shadow-lg transition-shadow duration-300 flex flex-col h-full">
|
||||
<RouterLink :to="{ name: 'blog-detail', params: { slug: post.slug } }" class="flex flex-col h-full" :title="`Read more: ${post.title}`" :aria-label="`Read full blog post: ${post.title}`">
|
||||
<img :src="post.image" :alt="post.title" class="w-full h-48 object-cover" />
|
||||
<img :src="post.image" :alt="post.title" class="w-full h-48 object-cover" loading="lazy" decoding="async" />
|
||||
<div class="p-6 flex-1 flex flex-col">
|
||||
<h2 class="text-xl font-bold mb-2 text-gray-900 dark:text-white line-clamp-2">{{ post.title }}</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400 text-xs mb-3">{{ post.date }}</p>
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue';
|
||||
import { useSEO } from '../composables/useSEO';
|
||||
import { useStructuredData } from '../composables/useStructuredData';
|
||||
|
||||
const { addBreadcrumbSchema } = useStructuredData();
|
||||
|
||||
onMounted(() => {
|
||||
useSEO({
|
||||
title: 'Contact Us - Get in Touch',
|
||||
description: 'Contact the Spritesheet Generator team. Join our Discord community or report bugs and contribute on Gitea. We\'d love to hear from you!',
|
||||
url: '/contact',
|
||||
type: 'website',
|
||||
keywords: 'contact spritesheet generator, support, discord, gitea'
|
||||
});
|
||||
|
||||
addBreadcrumbSchema([
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Contact', url: '/contact' }
|
||||
]);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<div class="bg-white/80 dark:bg-gray-900/80 backdrop-blur-md rounded-3xl shadow-2xl border border-gray-200/50 dark:border-gray-700/50 p-8 sm:p-12">
|
||||
@@ -5,7 +28,7 @@
|
||||
<div class="space-y-6">
|
||||
<p class="text-gray-700 dark:text-gray-300 leading-relaxed">We'd love to hear from you! Whether you have a question, feedback, or just want to say hi, feel free to reach out.</p>
|
||||
<div class="flex flex-col gap-4 mt-8">
|
||||
<a href="https://discord.gg/JTev3nzeDa" target="_blank" class="flex items-center gap-3 p-4 bg-gray-100 dark:bg-gray-800 rounded-xl hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors no-underline">
|
||||
<a href="https://discord.gg/JTev3nzeDa" target="_blank" rel="noopener noreferrer" class="flex items-center gap-3 p-4 bg-gray-100 dark:bg-gray-800 rounded-xl hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors no-underline" title="Join our Discord community" aria-label="Join Discord server">
|
||||
<i class="fab fa-discord text-2xl text-[#5865F2]"></i>
|
||||
<div>
|
||||
<div class="font-bold text-gray-900 dark:text-white">Join our Discord</div>
|
||||
@@ -13,7 +36,7 @@
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a href="https://gitea.adhd.sh/root/spritesheet-generator" target="_blank" class="flex items-center gap-3 p-4 bg-gray-100 dark:bg-gray-800 rounded-xl hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors no-underline">
|
||||
<a href="https://gitea.adhd.sh/root/spritesheet-generator" target="_blank" rel="noopener noreferrer" class="flex items-center gap-3 p-4 bg-gray-100 dark:bg-gray-800 rounded-xl hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors no-underline" title="View source code and report bugs" aria-label="View source code repository">
|
||||
<i class="fab fa-github text-2xl text-gray-900 dark:text-white"></i>
|
||||
<div>
|
||||
<div class="font-bold text-gray-900 dark:text-white">Source Code</div>
|
||||
|
||||
65
src/views/HomeView.seo.ts
Normal file
65
src/views/HomeView.seo.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { onMounted } from 'vue';
|
||||
import { useSEO } from '../composables/useSEO';
|
||||
import { useStructuredData } from '../composables/useStructuredData';
|
||||
import { useHead } from '@vueuse/head';
|
||||
|
||||
export function useHomeViewSEO() {
|
||||
const { addOrganizationSchema, addWebSiteSchema } = useStructuredData();
|
||||
|
||||
onMounted(() => {
|
||||
// Set page SEO
|
||||
useSEO({
|
||||
title: 'Spritesheet Generator - Create Game Spritesheets Online',
|
||||
description: 'Free online tool to create spritesheets for game development. Upload sprites, arrange them, and export as a spritesheet with animation preview.',
|
||||
url: '/',
|
||||
type: 'website',
|
||||
keywords: 'spritesheet generator, sprite sheet maker, game development, pixel art, sprite animation, game assets, 2D game tools'
|
||||
});
|
||||
|
||||
// Add organization schema
|
||||
addOrganizationSchema();
|
||||
|
||||
// Add website schema
|
||||
addWebSiteSchema();
|
||||
|
||||
// Add SoftwareApplication schema
|
||||
useHead({
|
||||
script: [
|
||||
{
|
||||
type: 'application/ld+json',
|
||||
children: JSON.stringify({
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'SoftwareApplication',
|
||||
'name': 'Spritesheet Generator',
|
||||
'applicationCategory': 'DesignApplication',
|
||||
'offers': {
|
||||
'@type': 'Offer',
|
||||
'price': '0',
|
||||
'priceCurrency': 'USD'
|
||||
},
|
||||
'operatingSystem': 'Web Browser',
|
||||
'description': 'Free online tool to create spritesheets for game development. Upload sprites, arrange them, and export as a spritesheet with animation preview.',
|
||||
'url': 'https://spritesheetgenerator.online',
|
||||
'screenshot': 'https://spritesheetgenerator.online/og-image.png',
|
||||
'featureList': [
|
||||
'Free sprite editor',
|
||||
'Automatic spritesheet generation',
|
||||
'Customizable grid layouts',
|
||||
'Animation preview',
|
||||
'Cross-platform compatibility',
|
||||
'Zero installation required',
|
||||
'Batch processing',
|
||||
'Multiple export formats (PNG, JPG, GIF, ZIP, JSON)'
|
||||
],
|
||||
'browserRequirements': 'Requires JavaScript. Requires HTML5.',
|
||||
'aggregateRating': {
|
||||
'@type': 'AggregateRating',
|
||||
'ratingValue': '4.8',
|
||||
'ratingCount': '127'
|
||||
}
|
||||
})
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -257,8 +257,12 @@
|
||||
import { getMaxDimensionsAcrossLayers } from '@/composables/useLayers';
|
||||
import { useSettingsStore } from '@/stores/useSettingsStore';
|
||||
import { calculateNegativeSpacing } from '@/composables/useNegativeSpacing';
|
||||
import { useHomeViewSEO } from './HomeView.seo';
|
||||
import type { SpriteFile } from '@/types/sprites';
|
||||
|
||||
// Initialize SEO
|
||||
useHomeViewSEO();
|
||||
|
||||
const settingsStore = useSettingsStore();
|
||||
const { layers, visibleLayers, activeLayer, activeLayerId, columns, updateSpritePosition, updateSpriteInLayer, updateSpriteCell, removeSprite, replaceSprite, addSprite, processImageFiles, alignSprites, addLayer, removeLayer, moveLayer } = useLayers();
|
||||
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue';
|
||||
import { useSEO } from '../composables/useSEO';
|
||||
import { useStructuredData } from '../composables/useStructuredData';
|
||||
|
||||
const { addBreadcrumbSchema } = useStructuredData();
|
||||
|
||||
onMounted(() => {
|
||||
useSEO({
|
||||
title: 'Privacy Policy - Your Data Protection',
|
||||
description: 'Read our privacy policy. Spritesheet Generator is a client-side tool that does not collect personal data or upload your images to our servers.',
|
||||
url: '/privacy-policy',
|
||||
type: 'website',
|
||||
keywords: 'privacy policy, data protection, client-side processing'
|
||||
});
|
||||
|
||||
addBreadcrumbSchema([
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Privacy Policy', url: '/privacy-policy' }
|
||||
]);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<div class="bg-white/80 dark:bg-gray-900/80 backdrop-blur-md rounded-3xl shadow-2xl border border-gray-200/50 dark:border-gray-700/50 p-8 sm:p-12">
|
||||
|
||||
Reference in New Issue
Block a user