diff --git a/app/pages/projects/[...slug].vue b/app/pages/projects/[...slug].vue index 04da18a..4c7bbf7 100644 --- a/app/pages/projects/[...slug].vue +++ b/app/pages/projects/[...slug].vue @@ -10,6 +10,7 @@ import { isExternalHref, projectEntryHref, projectOgImage, + sortProjects, } from '~/utils/projects'; const route = useRoute(); @@ -30,7 +31,7 @@ const folderName = computed( const { data } = await useAsyncData( () => `projects:${route.path}`, async () => { - const all = await queryCollection('projects').order('title', 'ASC').all(); + const all = await queryCollection('projects').all(); const visible = all.filter((page) => import.meta.dev || !page.hidden); const project = visible.find( (page) => @@ -44,7 +45,9 @@ const { data } = await useAsyncData( const prefix = contentPath.value.endsWith('/') ? contentPath.value : `${contentPath.value}/`; - const pages = visible.filter((page) => page.path.startsWith(prefix)); + const pages = sortProjects( + visible.filter((page) => page.path.startsWith(prefix)), + ); if (!pages.length) return null; return { kind: 'folder' as const, project: null, pages }; diff --git a/app/pages/projects/index.vue b/app/pages/projects/index.vue index f4a8d1f..347a8d1 100644 --- a/app/pages/projects/index.vue +++ b/app/pages/projects/index.vue @@ -6,11 +6,16 @@ import { personId, websiteId, } from '~/utils/site'; -import { isExternalHref, projectEntryHref } from '~/utils/projects'; +import { + isExternalHref, + projectEntryHref, + sortProjects, +} from '~/utils/projects'; const { data: pages } = await useAsyncData('project-pages', async () => { - const all = await queryCollection('projects').order('title', 'ASC').all(); - return import.meta.dev ? all : all.filter((page) => !page.hidden); + const all = await queryCollection('projects').all(); + const visible = all.filter((page) => !page.hidden); + return sortProjects(visible); }); const projectsUrl = `${SITE_URL}/projects`; diff --git a/app/pages/styleguide.vue b/app/pages/styleguide.vue index c110dd7..a35e5c9 100644 --- a/app/pages/styleguide.vue +++ b/app/pages/styleguide.vue @@ -6,6 +6,7 @@ import { } from '~/utils/fonts'; import { BG_THEMES } from '~/utils/themes'; import { SITE_URL } from '~/utils/site'; +import { sortProjects } from '~/utils/projects'; const TOKEN_NAMES = [ '--bg', @@ -51,8 +52,8 @@ const { data: writingPages } = await useAsyncData( const { data: projectPages } = await useAsyncData( 'styleguide-projects', async () => { - const all = await queryCollection('projects').order('title', 'ASC').all(); - return all.filter((page) => !page.hidden).slice(0, 4); + const all = await queryCollection('projects').all(); + return sortProjects(all.filter((page) => !page.hidden)).slice(0, 4); }, ); diff --git a/app/pages/writing/index.vue b/app/pages/writing/index.vue index ae2ed2c..2b6ec6c 100644 --- a/app/pages/writing/index.vue +++ b/app/pages/writing/index.vue @@ -9,7 +9,7 @@ import { const { data: pages } = await useAsyncData('writing-pages', async () => { const all = await queryCollection('writing').order('date', 'DESC').all(); - return import.meta.dev ? all : all.filter((page) => !page.hidden); + return all.filter((page) => !page.hidden); }); const writingUrl = `${SITE_URL}/writing`; diff --git a/app/utils/projects.ts b/app/utils/projects.ts index 473c52c..b898fdb 100644 --- a/app/utils/projects.ts +++ b/app/utils/projects.ts @@ -5,6 +5,20 @@ export function projectEntryHref(page: { return page.href || `/projects${page.path}`; } +export function sortProjects< + T extends { title: string; date?: Date | string | null }, +>(pages: T[]) { + return [...pages].sort((a, b) => { + const aTime = a.date ? new Date(a.date).getTime() : Number.NaN; + const bTime = b.date ? new Date(b.date).getTime() : Number.NaN; + const aHasDate = !Number.isNaN(aTime); + const bHasDate = !Number.isNaN(bTime); + if (aHasDate && bHasDate && aTime !== bTime) return bTime - aTime; + if (aHasDate !== bHasDate) return aHasDate ? -1 : 1; + return a.title.localeCompare(b.title); + }); +} + export function isExternalHref(href: string) { return /^https?:\/\//i.test(href); } diff --git a/content.config.ts b/content.config.ts index 728f40e..4aff4ba 100644 --- a/content.config.ts +++ b/content.config.ts @@ -26,6 +26,7 @@ export default defineContentConfig({ description: z.string(), href: z.string().optional(), hidden: z.boolean().optional(), + date: z.coerce.date().optional(), image: z.string().optional(), }), }), diff --git a/content/projects/mystwright.md b/content/projects/mystwright.md index 28493e6..b66d70e 100644 --- a/content/projects/mystwright.md +++ b/content/projects/mystwright.md @@ -2,4 +2,5 @@ title: Mystwright description: An AI-driven mystery detective game. Generate, investigate, solve. href: https://mystwright.com/ +hidden: true ---