Skip to content

Commit 243a1cf

Browse files
committed
Make website mobile-only
1 parent 19f65e7 commit 243a1cf

16 files changed

Lines changed: 254 additions & 1221 deletions

File tree

website/src/lib/components/JournalMockup.svelte

Lines changed: 0 additions & 471 deletions
This file was deleted.

website/src/lib/components/WindowsIcon.svelte

Lines changed: 0 additions & 23 deletions
This file was deleted.

website/src/lib/data/blog.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,14 @@ export type BlogPost = {
105105
/** Frontmatter as authored - most fields are optional and filled in below. */
106106
type RawFrontmatter = Partial<Omit<BlogPost, 'slug'>>;
107107

108-
const metaModules = import.meta.glob<RawFrontmatter>('/src/content/blog/*.md', {
109-
eager: true,
110-
import: 'metadata'
108+
/**
109+
* Import each mdsvex module as a namespace, then read its generated metadata
110+
* export below. A named `import: 'metadata'` works in production builds but
111+
* Bun-triggered Vite dependency scans can inspect the raw Markdown before
112+
* mdsvex transforms it and incorrectly report that the export is missing.
113+
*/
114+
const metaModules = import.meta.glob<{ metadata: RawFrontmatter }>('/src/content/blog/*.md', {
115+
eager: true
111116
});
112117

113118
/** Lazily loaded post bodies, so the index does not bundle every post. */
@@ -157,8 +162,8 @@ function toPost(path: string, meta: RawFrontmatter): BlogPost {
157162
};
158163
}
159164

160-
export const authoredPosts: BlogPost[] = Object.entries(metaModules).map(([path, meta]) =>
161-
toPost(path, meta)
165+
export const authoredPosts: BlogPost[] = Object.entries(metaModules).map(([path, module]) =>
166+
toPost(path, module.metadata)
162167
);
163168

164169
/** Only approved content is visible to routes, feeds, related posts, and the sitemap. */

website/src/lib/data/faq.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export const faqs: FaqItem[] = [
3838
{
3939
question: 'Which platforms is Patterns available on?',
4040
answer:
41-
'Patterns is available for iOS, Android, macOS, Windows, and Linux. It is built with Flutter for a clean, focused experience on every screen.'
41+
'Patterns is a mobile app available for iPhone and Android. You can download it from the App Store or Google Play.'
4242
},
4343
{
4444
question: 'How much does Patterns cost?',

website/src/lib/data/features.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
LineChart,
66
Shield,
77
Moon,
8-
MonitorSmartphone
8+
Smartphone
99
} from 'lucide-svelte';
1010

1111
export type Feature = {
@@ -46,9 +46,9 @@ export const features: Feature[] = [
4646
'Switch between carefully crafted dark and light themes to match your environment and reduce eye strain during late-night reflections.'
4747
},
4848
{
49-
icon: MonitorSmartphone,
50-
title: 'Mobile & Desktop',
49+
icon: Smartphone,
50+
title: 'iPhone & Android',
5151
description:
52-
'Built with Flutter for iOS, Android, macOS, Linux, and Windows with a clean interface that feels focused on every screen.'
52+
'Built for iOS and Android, so your journal and ERP tools are available when a trigger or urge happens.'
5353
}
5454
];

website/src/lib/data/links.test.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ describe('store links', () => {
3434
expect(new URL(links.playStore).searchParams.get('utm_source')).toBeNull();
3535
});
3636

37-
it('keeps the macOS link on the same app id', () => {
38-
expect(links.macos).toContain(`/id${IOS_APP_ID}`);
39-
expect(new URL(links.macos).searchParams.get('mt')).toBe('12');
40-
});
4137
});
4238

4339
describe('canonical site host', () => {

website/src/lib/data/links.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
export const links = {
22
ios: 'https://apps.apple.com/us/app/patterns-ocd-journaling/id6762611172',
3-
macos:
4-
'https://apps.apple.com/us/app/patterns-ocd-journaling/id6762611172?mt=12',
53
playStore:
64
'https://play.google.com/store/apps/details?id=com.maskedsyntax.patterns',
75
github: 'https://github.com/maskedsyntax/patterns',
86
githubApi: 'https://api.github.com/repos/maskedsyntax/patterns',
97
kofi: 'https://ko-fi.com/aftaabsiddiqui',
108
sponsors: 'https://github.com/sponsors/maskedsyntax',
11-
releases: 'https://github.com/maskedsyntax/patterns/releases',
12-
releasesLatest: 'https://github.com/maskedsyntax/patterns/releases/latest',
139
issues: 'https://github.com/maskedsyntax/patterns/issues',
1410
license: 'https://github.com/maskedsyntax/patterns/blob/master/LICENSE',
1511
maskedsyntax: 'https://maskedsyntax.com/',
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { readFileSync } from 'node:fs';
2+
import { resolve } from 'node:path';
3+
import { describe, expect, it } from 'vitest';
4+
import { faqs } from './faq';
5+
import { features } from './features';
6+
import { links } from './links';
7+
8+
const PUBLIC_COPY_FILES = [
9+
'src/routes/+page.svelte',
10+
'src/routes/roadmap/+page.svelte',
11+
'src/lib/sections/Download.svelte',
12+
'src/lib/sections/Preview.svelte'
13+
];
14+
15+
const publicCopy = PUBLIC_COPY_FILES.map((path) => ({
16+
path,
17+
body: readFileSync(resolve(process.cwd(), path), 'utf8')
18+
}));
19+
20+
const retiredPlatformLanguage = /\b(?:macOS|Windows|Linux)\b|desktop app|download for desktop|on desktop/i;
21+
22+
describe('mobile-only website positioning', () => {
23+
it('does not advertise retired app platforms in public page copy', () => {
24+
for (const file of publicCopy) {
25+
expect(file.body, file.path).not.toMatch(retiredPlatformLanguage);
26+
}
27+
28+
for (const feature of features) {
29+
expect(`${feature.title} ${feature.description}`, feature.title).not.toMatch(
30+
retiredPlatformLanguage
31+
);
32+
}
33+
34+
for (const faq of faqs) {
35+
expect(`${faq.question} ${faq.answer}`, faq.question).not.toMatch(retiredPlatformLanguage);
36+
}
37+
});
38+
39+
it('exposes only the two mobile store destinations', () => {
40+
expect(links.ios).toContain('apps.apple.com');
41+
expect(links.playStore).toContain('play.google.com');
42+
expect(Object.keys(links)).not.toContain('macos');
43+
});
44+
45+
it('states the supported mobile platforms in the download experience', () => {
46+
const download = publicCopy.find((file) => file.path.endsWith('Download.svelte'))?.body ?? '';
47+
expect(download).toContain('Available on iOS and Android');
48+
expect(download).toContain('App Store');
49+
expect(download).toContain('Google Play');
50+
});
51+
});

0 commit comments

Comments
 (0)