Adds meta tags
This commit is contained in:
@@ -26,6 +26,21 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>Portainer Templates</title>
|
||||||
|
<meta name="description" content="A community-driven library of 1-click self-hosted apps" />
|
||||||
|
<meta property="og:title" content="Portainer Templates" />
|
||||||
|
<meta property="og:description" content="A community-driven library of 1-click self-hosted apps" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:url" content="{import.meta.env.VITE_PUBLIC_BASE_URL}/" />
|
||||||
|
<meta property="og:image" content="{import.meta.env.VITE_PUBLIC_BASE_URL}/banner.png" />
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:title" content="Portainer Templates" />
|
||||||
|
<meta name="twitter:description" content="A community-driven library of 1-click self-hosted apps" />
|
||||||
|
<meta name="twitter:image" content="{import.meta.env.VITE_PUBLIC_BASE_URL}/banner.png" />
|
||||||
|
<link rel="canonical" href="{import.meta.env.VITE_PUBLIC_BASE_URL}" />
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
{#if showNav}
|
{#if showNav}
|
||||||
<Header />
|
<Header />
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { page } from '$app/stores'
|
||||||
|
|
||||||
import Hero from '$lib/Hero.svelte';
|
import Hero from '$lib/Hero.svelte';
|
||||||
import ListFilter from '$lib/ListFilter.svelte';
|
import ListFilter from '$lib/ListFilter.svelte';
|
||||||
@@ -11,20 +12,24 @@
|
|||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const preSelectedCategories = $page.url.searchParams.get('categories');
|
||||||
|
|
||||||
let searchTerm = '';
|
let searchTerm = '';
|
||||||
|
|
||||||
let showCategories = false;
|
let selectedCategories: string[] = preSelectedCategories?.split(',') || [];
|
||||||
|
|
||||||
let selectedCategories: string[] = [];
|
let showCategories = !!preSelectedCategories || false;
|
||||||
|
|
||||||
$: filteredTemplates = data.templates.filter((template: Template) => {
|
$: filteredTemplates = data.templates.filter((template: Template) => {
|
||||||
const compareStr = (str1: string, str2: string) =>
|
const compareStr = (str1: string, str2: string) =>
|
||||||
(str1 || '').toLowerCase().includes(str2.toLowerCase());
|
(str1 || '').toLowerCase().includes(str2.toLowerCase());
|
||||||
|
|
||||||
if (selectedCategories.length) {
|
if (selectedCategories.length) {
|
||||||
const templateCategories = template.categories || [];
|
const templateCategories = (template.categories || []).map((c) => c.toLowerCase());
|
||||||
const hasSelectedCategory = selectedCategories.some((cat) =>
|
const hasSelectedCategory = selectedCategories.some((cat) =>
|
||||||
templateCategories.includes(cat)
|
templateCategories.includes(cat.toLocaleLowerCase())
|
||||||
);
|
);
|
||||||
if (!hasSelectedCategory) return false;
|
if (!hasSelectedCategory) return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,10 +53,13 @@ const getServices = async (template): Promise<Service[]> => {
|
|||||||
container: vol.split(':')[1],
|
container: vol.split(':')[1],
|
||||||
})),
|
})),
|
||||||
restart_policy: serviceData.restart,
|
restart_policy: serviceData.restart,
|
||||||
env: Object.keys(serviceData.environment || {}).map((envName) => ({
|
env: Object.keys(serviceData.environment || {}).map((envName) => {
|
||||||
name: envName,
|
if (typeof envName === 'string') {
|
||||||
value: serviceData.environment[envName],
|
const nowItsArray = serviceData.environment[envName].split('=') || [];
|
||||||
})),
|
return { name: nowItsArray[0] || '', value: nowItsArray[1] || '' }
|
||||||
|
}
|
||||||
|
return { name: envName, value: serviceData.environment[envName] }
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return someServices;
|
return someServices;
|
||||||
@@ -80,7 +83,6 @@ const returnResults = async (templates, templateSlug) => {
|
|||||||
// If only 1 service, merge it with the template
|
// If only 1 service, merge it with the template
|
||||||
if (services.length === 1) {
|
if (services.length === 1) {
|
||||||
template = {...template, ...services[0]};
|
template = {...template, ...services[0]};
|
||||||
services = [];
|
|
||||||
} else if (services.length > 1) {
|
} else if (services.length > 1) {
|
||||||
// If made up from multiple services, fetch Docker info for each image
|
// If made up from multiple services, fetch Docker info for each image
|
||||||
services = await Promise.all(
|
services = await Promise.all(
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
const template = $page.data.template as Template;
|
const template = $page.data.template as Template;
|
||||||
const dockerStats = $page.data.dockerStats as DockerHubResponse;
|
const dockerStats = $page.data.dockerStats as DockerHubResponse;
|
||||||
const services = $page.data.services as Service[];
|
const services = $page.data.services as Service[];
|
||||||
const serviceDockerStats = $page.data.serviceDockerStats as DockerHubResponse[] || null;
|
|
||||||
|
|
||||||
const makeMultiDoc = (services: Service[]) => {
|
const makeMultiDoc = (services: Service[]) => {
|
||||||
return services.map((s) => {
|
return services.map((s) => {
|
||||||
@@ -27,8 +26,25 @@
|
|||||||
}).filter((thingy) => thingy !== null);
|
}).filter((thingy) => thingy !== null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const makeMetaDescription = () => {
|
||||||
|
return `Installation guide for ${template.title}, using Portainer, Docker Run or Docker-Compose. `
|
||||||
|
+`Portainer-Templates is a community driven repository of Portainer Templates for Self-Hosted apps. \n`
|
||||||
|
+`${template.description}`;
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>{template.title} | Portainer Templates</title>
|
||||||
|
<meta name="description" content={makeMetaDescription()} />
|
||||||
|
<meta property="og:title" content="{template.title} | Portainer Templates" />
|
||||||
|
<meta property="og:description" content={makeMetaDescription()} />
|
||||||
|
<meta property="og:url" content="{import.meta.env.VITE_PUBLIC_BASE_URL}/{urlSlug}" />
|
||||||
|
<meta name="twitter:title" content="{template.title} | Portainer Templates" />
|
||||||
|
<meta name="twitter:description" content={makeMetaDescription()} />
|
||||||
|
<link rel="canonical" href="{import.meta.env.VITE_PUBLIC_BASE_URL}/{urlSlug}" />
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
{#if template}
|
{#if template}
|
||||||
<section class="summary-section">
|
<section class="summary-section">
|
||||||
<h1>
|
<h1>
|
||||||
@@ -38,7 +54,7 @@
|
|||||||
{#if template.categories || template.category }
|
{#if template.categories || template.category }
|
||||||
<p class="tags">
|
<p class="tags">
|
||||||
{#each (template.categories || template.category || []) as tag}
|
{#each (template.categories || template.category || []) as tag}
|
||||||
<span>{tag}</span>
|
<a href="/?categories={tag}"><span>{tag}</span></a>
|
||||||
{/each}
|
{/each}
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -56,7 +72,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#await services then returnedServices}
|
{#await services then returnedServices}
|
||||||
{#if returnedServices && returnedServices.length > 0}
|
{#if returnedServices && returnedServices.length > 1}
|
||||||
<section class="service-section">
|
<section class="service-section">
|
||||||
<h2>Services</h2>
|
<h2>Services</h2>
|
||||||
<div class="service-list">
|
<div class="service-list">
|
||||||
@@ -115,6 +131,11 @@
|
|||||||
.tags {
|
.tags {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
gap: 0.5rem;
|
||||||
|
a {
|
||||||
|
color: var(--foreground);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
span {
|
span {
|
||||||
&:before {
|
&:before {
|
||||||
content: '#';
|
content: '#';
|
||||||
@@ -125,6 +146,11 @@
|
|||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&:hover {
|
||||||
|
color: var(--accent);
|
||||||
|
transform: scale(1.08);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user