Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/markdoc/layouts/Post.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
export let callToAction: BlogCallToActionInput;
export let lastUpdated: string;
export let faqs: { question: string; answer: string }[] | undefined = undefined;
/** Frontmatter `draft: true`: the post stays reachable by its direct URL but is hidden from all listings/feeds and marked noindex. */
export let draft = false;

const posts = getContext<PostsData[]>('posts')?.filter(
(post) => !(post.unlisted ?? false) && !(post.draft ?? false)
Expand Down Expand Up @@ -133,6 +135,10 @@
</script>

<svelte:head>
{#if draft}
<!-- Draft: reachable by direct URL but kept out of search indexes -->
<meta name="robots" content="noindex" />
{/if}
<!-- Titles -->
<title>{resolvedMetaTitle + TITLE_SUFFIX}</title>
<meta property="og:title" content={resolvedMetaTitle} />
Expand Down
4 changes: 2 additions & 2 deletions src/routes/blog/+layout.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { posts, authors, categories } from './content';
import { publishedPosts, authors, categories } from './content';

export async function load({ data }) {
return {
posts,
posts: publishedPosts,
authors,
categories,
rawContent: data.rawContent
Expand Down
11 changes: 9 additions & 2 deletions src/routes/blog/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ export const posts = Object.entries(postsGlob)
return b.date.getTime() - a.date.getTime();
});

// Posts visible to the public. Drafts are excluded everywhere except their own
// direct URL: the /blog/post/<slug> route still renders a draft (and emits a
// noindex meta via Post.svelte), but it never appears in any listing or feed.
export const publishedPosts = posts.filter((post) => !post.draft);

export const authors = Object.values(authorsGlob).map((authorList) => {
const { frontmatter } = authorList as {
frontmatter: AuthorData;
Expand Down Expand Up @@ -115,12 +120,14 @@ export const normalizeCategory = (str: string) => str?.replace(/\s+/g, '-').toLo

export const getBlogEntries = () => {
const filteredCategories = categories.filter((category) =>
posts.some((post) => normalizeCategory(post.category) === normalizeCategory(category.name))
publishedPosts.some(
(post) => normalizeCategory(post.category) === normalizeCategory(category.name)
)
);

return {
authors,
filteredCategories,
posts: posts.filter((post) => !post.unlisted)
posts: publishedPosts.filter((post) => !post.unlisted)
};
};
6 changes: 3 additions & 3 deletions src/routes/blog/feed.json/+server.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { RequestHandler } from './$types';
import { posts } from '../content';
import { publishedPosts } from '../content';
import { json } from '@sveltejs/kit';

export const prerender = true;

export const GET: RequestHandler = () => {
return json({
posts,
total: Object.keys(posts).length
posts: publishedPosts,
total: publishedPosts.length
});
};
4 changes: 2 additions & 2 deletions src/routes/blog/rss.xml/+server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { RequestHandler } from './$types';
import { posts } from '../content';
import { publishedPosts } from '../content';

export const prerender = true;

Expand All @@ -26,7 +26,7 @@ export const GET: RequestHandler = () => {
<link>https://appwrite.io</link>
<atom:link href="https://appwrite.io/blog/rss.xml" rel="self" type="application/rss+xml" />
<description>Appwrite is an open-source platform for building applications at any scale, using your preferred programming languages and tools.</description>
${posts
${publishedPosts
.map(
(post) => `<item>
<title>${encodeText(post.title)}</title>
Expand Down
12 changes: 12 additions & 0 deletions src/routes/llms-full.txt/+server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { RequestHandler } from '@sveltejs/kit';
import { SPECIAL_PAGES } from '../llms-config';
import { publishedPosts } from '../blog/content';

export const prerender = true;

Expand All @@ -9,6 +10,11 @@ const markdocAndMarkdownFiles = import.meta.glob('$routes/**/*.{markdoc,md}', {
eager: true
});

// Published (non-draft) blog post slugs — the single source of truth for what is public.
const PUBLISHED_BLOG_SLUGS = new Set(
publishedPosts.map((p) => p.href.split('/blog/post/')[1]).filter(Boolean)
);

function stripRouteGroups(routePath: string): string {
return routePath.replace(/\([^/]+\)\//g, '');
}
Expand Down Expand Up @@ -128,6 +134,12 @@ ${page.fullContent}
continue;
}

// Skip draft blog posts: only include published ones (single source of truth)
if (href.startsWith('/blog/post')) {
const slug = href.split('/blog/post/')[1]?.replace(/\/+$/, '');
if (!slug || !PUBLISHED_BLOG_SLUGS.has(slug)) continue;
}

const url = new URL(href, base).toString();

const fmOrH1 = extractTitle(raw);
Expand Down
12 changes: 12 additions & 0 deletions src/routes/llms.txt/+server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { RequestHandler } from '@sveltejs/kit';
import { SPECIAL_PAGES } from '../llms-config';
import { publishedPosts } from '../blog/content';

export const prerender = true;

Expand All @@ -10,6 +11,11 @@ const markdocAndMarkdownFiles = import.meta.glob('$routes/**/*.{markdoc,md}', {
eager: true
});

// Published (non-draft) blog post slugs — the single source of truth for what is public.
const PUBLISHED_BLOG_SLUGS = new Set(
publishedPosts.map((p) => p.href.split('/blog/post/')[1]).filter(Boolean)
);

// Strip group directories like (marketing) from a route path
function stripRouteGroups(routePath: string): string {
return routePath.replace(/\([^/]+\)\//g, '');
Expand Down Expand Up @@ -148,6 +154,12 @@ export const GET: RequestHandler = ({ request }) => {
continue;
}

// Skip draft blog posts: only include published ones (single source of truth)
if (href.startsWith('/blog/post')) {
const slug = href.split('/blog/post/')[1]?.replace(/\/+$/, '');
if (!slug || !PUBLISHED_BLOG_SLUGS.has(slug)) continue;
}

const url = new URL(href, base).toString();

const title = extractTitle(raw) ?? href.split('/').pop()!.replace(/[-_]/g, ' ');
Expand Down
Loading