From 61c23d5e790786953a4aaba37237ed18f82e41c3 Mon Sep 17 00:00:00 2001 From: Till JS Date: Tue, 24 Mar 2026 12:21:51 +0100 Subject: [PATCH] fix(manacore): improve dashboard layout polish - Remove unnecessary wrapper div in WidgetContainer - Increase grid gap from gap-4 to gap-5 for breathing room - Add auto-rows-fr for equal row heights - Add min-h on widget content so empty widgets aren't tiny - Change default layout to 3 equal columns (small) Co-Authored-By: Claude Opus 4.6 (1M context) --- .../apps/web/src/routes/offline/+page.ts | 1 + apps/chat/apps/web/Dockerfile | 1 + .../chat/apps/web/src/routes/offline/+page.ts | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + apps/clock/apps/web/Dockerfile | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + .../dashboard/WidgetContainer.svelte | 118 +++++++++--------- .../apps/web/src/routes/offline/+page.ts | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + apps/mukke/apps/web/Dockerfile | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + apps/photos/apps/web/Dockerfile | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + apps/picture/apps/web/Dockerfile | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + apps/presi/apps/web/Dockerfile | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + .../src/achievement/achievement.service.ts | 9 +- .../apps/backend/src/skill/skill.service.ts | 15 ++- apps/skilltree/apps/web/Dockerfile | 1 + .../src/lib/components/AchievementCard.svelte | 6 +- .../components/AchievementCelebration.svelte | 4 +- .../src/lib/components/StatsOverview.svelte | 9 +- .../apps/web/src/lib/services/storage.ts | 4 +- .../web/src/lib/stores/achievements.svelte.ts | 12 +- .../apps/web/src/routes/+page.svelte | 9 +- .../web/src/routes/achievements/+page.svelte | 19 +-- .../apps/web/src/routes/offline/+page.ts | 1 + apps/storage/apps/web/Dockerfile | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + apps/todo/apps/web/scripts/generate-icons.mjs | 34 +++++ apps/todo/apps/web/src/app.html | 17 ++- .../todo/apps/web/src/routes/offline/+page.ts | 1 + .../todo/apps/web/static/apple-touch-icon.png | Bin 0 -> 5269 bytes apps/todo/apps/web/static/favicon.png | Bin 0 -> 1077 bytes apps/todo/apps/web/static/pwa-192x192.png | Bin 0 -> 5789 bytes apps/todo/apps/web/static/pwa-512x512.png | Bin 0 -> 17703 bytes apps/zitare/apps/web/Dockerfile | 1 + .../apps/web/src/routes/offline/+page.ts | 1 + 45 files changed, 185 insertions(+), 100 deletions(-) create mode 100644 apps/calendar/apps/web/src/routes/offline/+page.ts create mode 100644 apps/chat/apps/web/src/routes/offline/+page.ts create mode 100644 apps/citycorners/apps/web/src/routes/offline/+page.ts create mode 100644 apps/clock/apps/web/src/routes/offline/+page.ts create mode 100644 apps/contacts/apps/web/src/routes/offline/+page.ts create mode 100644 apps/context/apps/web/src/routes/offline/+page.ts create mode 100644 apps/manacore/apps/web/src/routes/offline/+page.ts create mode 100644 apps/manadeck/apps/web/src/routes/offline/+page.ts create mode 100644 apps/matrix/apps/web/src/routes/offline/+page.ts create mode 100644 apps/mukke/apps/web/src/routes/offline/+page.ts create mode 100644 apps/nutriphi/apps/web/src/routes/offline/+page.ts create mode 100644 apps/photos/apps/web/src/routes/offline/+page.ts create mode 100644 apps/picture/apps/web/src/routes/offline/+page.ts create mode 100644 apps/planta/apps/web/src/routes/offline/+page.ts create mode 100644 apps/presi/apps/web/src/routes/offline/+page.ts create mode 100644 apps/questions/apps/web/src/routes/offline/+page.ts create mode 100644 apps/skilltree/apps/web/src/routes/offline/+page.ts create mode 100644 apps/storage/apps/web/src/routes/offline/+page.ts create mode 100644 apps/todo/apps/web/scripts/generate-icons.mjs create mode 100644 apps/todo/apps/web/src/routes/offline/+page.ts create mode 100644 apps/todo/apps/web/static/apple-touch-icon.png create mode 100644 apps/todo/apps/web/static/pwa-192x192.png create mode 100644 apps/todo/apps/web/static/pwa-512x512.png create mode 100644 apps/zitare/apps/web/src/routes/offline/+page.ts diff --git a/apps/calendar/apps/web/src/routes/offline/+page.ts b/apps/calendar/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/calendar/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/chat/apps/web/Dockerfile b/apps/chat/apps/web/Dockerfile index e9396a50e..7b6358aa3 100644 --- a/apps/chat/apps/web/Dockerfile +++ b/apps/chat/apps/web/Dockerfile @@ -42,6 +42,7 @@ COPY packages/shared-error-tracking ./packages/shared-error-tracking COPY packages/shared-vite-config ./packages/shared-vite-config COPY packages/shared-api-client ./packages/shared-api-client COPY packages/shared-stores ./packages/shared-stores +COPY packages/shared-app-onboarding ./packages/shared-app-onboarding # Copy chat packages COPY apps/chat/packages ./apps/chat/packages diff --git a/apps/chat/apps/web/src/routes/offline/+page.ts b/apps/chat/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/chat/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/citycorners/apps/web/src/routes/offline/+page.ts b/apps/citycorners/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/citycorners/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/clock/apps/web/Dockerfile b/apps/clock/apps/web/Dockerfile index f50c8c60e..50590255d 100644 --- a/apps/clock/apps/web/Dockerfile +++ b/apps/clock/apps/web/Dockerfile @@ -42,6 +42,7 @@ COPY packages/shared-error-tracking ./packages/shared-error-tracking COPY packages/shared-vite-config ./packages/shared-vite-config COPY packages/shared-api-client ./packages/shared-api-client COPY packages/shared-stores ./packages/shared-stores +COPY packages/shared-app-onboarding ./packages/shared-app-onboarding # Copy clock packages and web COPY apps/clock/packages ./apps/clock/packages diff --git a/apps/clock/apps/web/src/routes/offline/+page.ts b/apps/clock/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/clock/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/contacts/apps/web/src/routes/offline/+page.ts b/apps/contacts/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/contacts/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/context/apps/web/src/routes/offline/+page.ts b/apps/context/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/context/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/manacore/apps/web/src/lib/components/dashboard/WidgetContainer.svelte b/apps/manacore/apps/web/src/lib/components/dashboard/WidgetContainer.svelte index fe04ec211..5c41c172b 100644 --- a/apps/manacore/apps/web/src/lib/components/dashboard/WidgetContainer.svelte +++ b/apps/manacore/apps/web/src/lib/components/dashboard/WidgetContainer.svelte @@ -78,72 +78,72 @@ - - {#if dashboardStore.isEditing} + + {#if dashboardStore.isEditing} +
+
- -
- - - - - - - - - {meta?.icon} {$_(widget.title)} -
+ + + + + + + + + {meta?.icon} {$_(widget.title)} +
- -
- {#each sizes as size} - - {/each} -
- - -
+ +
+ {#each sizes as size} -
+ {/each}
- {/if} - -
- {#if WidgetComponent} - - {:else} -

Unknown widget type: {widget.type}

- {/if} + +
+ +
- + {/if} + + +
+ {#if WidgetComponent} + + {:else} +

Unknown widget type: {widget.type}

+ {/if} +
+ diff --git a/apps/manacore/apps/web/src/routes/offline/+page.ts b/apps/manacore/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/manacore/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/manadeck/apps/web/src/routes/offline/+page.ts b/apps/manadeck/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/manadeck/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/matrix/apps/web/src/routes/offline/+page.ts b/apps/matrix/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/matrix/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/mukke/apps/web/Dockerfile b/apps/mukke/apps/web/Dockerfile index 163576488..75d877599 100644 --- a/apps/mukke/apps/web/Dockerfile +++ b/apps/mukke/apps/web/Dockerfile @@ -43,6 +43,7 @@ COPY packages/shared-ui ./packages/shared-ui COPY packages/shared-utils ./packages/shared-utils COPY packages/shared-error-tracking ./packages/shared-error-tracking COPY packages/shared-vite-config ./packages/shared-vite-config +COPY packages/shared-app-onboarding ./packages/shared-app-onboarding # Copy mukke shared package COPY apps/mukke/packages ./apps/mukke/packages diff --git a/apps/mukke/apps/web/src/routes/offline/+page.ts b/apps/mukke/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/mukke/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/nutriphi/apps/web/src/routes/offline/+page.ts b/apps/nutriphi/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/nutriphi/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/photos/apps/web/Dockerfile b/apps/photos/apps/web/Dockerfile index 53db85675..4a5816064 100644 --- a/apps/photos/apps/web/Dockerfile +++ b/apps/photos/apps/web/Dockerfile @@ -49,6 +49,7 @@ COPY packages/shared-error-tracking ./packages/shared-error-tracking COPY packages/shared-vite-config ./packages/shared-vite-config COPY packages/shared-api-client ./packages/shared-api-client COPY packages/shared-stores ./packages/shared-stores +COPY packages/shared-app-onboarding ./packages/shared-app-onboarding # Copy photos shared package COPY apps/photos/packages/shared ./apps/photos/packages/shared diff --git a/apps/photos/apps/web/src/routes/offline/+page.ts b/apps/photos/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/photos/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/picture/apps/web/Dockerfile b/apps/picture/apps/web/Dockerfile index 12433a3ca..7d1d76b35 100644 --- a/apps/picture/apps/web/Dockerfile +++ b/apps/picture/apps/web/Dockerfile @@ -48,6 +48,7 @@ COPY packages/shared-vite-config ./packages/shared-vite-config COPY packages/shared-api-client ./packages/shared-api-client COPY packages/shared-stores ./packages/shared-stores COPY packages/shared-pwa ./packages/shared-pwa +COPY packages/shared-app-onboarding ./packages/shared-app-onboarding # Copy picture packages COPY apps/picture/packages/shared ./apps/picture/packages/shared diff --git a/apps/picture/apps/web/src/routes/offline/+page.ts b/apps/picture/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/picture/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/planta/apps/web/src/routes/offline/+page.ts b/apps/planta/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/planta/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/presi/apps/web/Dockerfile b/apps/presi/apps/web/Dockerfile index acc85630c..6e7a1c907 100644 --- a/apps/presi/apps/web/Dockerfile +++ b/apps/presi/apps/web/Dockerfile @@ -42,6 +42,7 @@ COPY packages/shared-profile-ui ./packages/shared-profile-ui COPY packages/shared-ui ./packages/shared-ui COPY packages/shared-error-tracking ./packages/shared-error-tracking COPY packages/shared-utils ./packages/shared-utils +COPY packages/shared-app-onboarding ./packages/shared-app-onboarding # Copy presi web COPY apps/presi/apps/web ./apps/presi/apps/web diff --git a/apps/presi/apps/web/src/routes/offline/+page.ts b/apps/presi/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/presi/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/questions/apps/web/src/routes/offline/+page.ts b/apps/questions/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/questions/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/skilltree/apps/backend/src/achievement/achievement.service.ts b/apps/skilltree/apps/backend/src/achievement/achievement.service.ts index 3e9f4836a..09e5b5e7c 100644 --- a/apps/skilltree/apps/backend/src/achievement/achievement.service.ts +++ b/apps/skilltree/apps/backend/src/achievement/achievement.service.ts @@ -94,9 +94,7 @@ export class AchievementService implements OnModuleInit { } async getStats(userId: string): Promise<{ total: number; unlocked: number }> { - const [totalResult] = await this.db - .select({ count: sql`count(*)` }) - .from(achievements); + const [totalResult] = await this.db.select({ count: sql`count(*)` }).from(achievements); const [unlockedResult] = await this.db .select({ count: sql`count(*)` }) @@ -113,7 +111,10 @@ export class AchievementService implements OnModuleInit { * Check all achievements for a user and unlock any newly earned ones. * Called after XP gain, skill creation, activity logging, etc. */ - async checkAndUnlock(userId: string, context?: { activityXp?: number }): Promise { + async checkAndUnlock( + userId: string, + context?: { activityXp?: number } + ): Promise { const allAchievements = await this.db.select().from(achievements); const unlocked = await this.db .select() diff --git a/apps/skilltree/apps/backend/src/skill/skill.service.ts b/apps/skilltree/apps/backend/src/skill/skill.service.ts index fb19e1404..17df2ee85 100644 --- a/apps/skilltree/apps/backend/src/skill/skill.service.ts +++ b/apps/skilltree/apps/backend/src/skill/skill.service.ts @@ -22,11 +22,15 @@ function calculateLevel(xp: number): number { export class SkillService { constructor( @Inject(DATABASE_TOKEN) private db: Database, - private readonly achievementService: AchievementService, + private readonly achievementService: AchievementService ) {} async findAll(userId: string): Promise { - return this.db.select().from(skills).where(eq(skills.userId, userId)).orderBy(desc(skills.totalXp)); + return this.db + .select() + .from(skills) + .where(eq(skills.userId, userId)) + .orderBy(desc(skills.totalXp)); } async findByBranch(userId: string, branch: string): Promise { @@ -109,7 +113,12 @@ export class SkillService { id: string, userId: string, dto: AddXpDto - ): Promise<{ skill: Skill; leveledUp: boolean; newLevel: number; newAchievements: AchievementUnlockResult[] }> { + ): Promise<{ + skill: Skill; + leveledUp: boolean; + newLevel: number; + newAchievements: AchievementUnlockResult[]; + }> { const skill = await this.findByIdOrThrow(id, userId); const newTotalXp = skill.totalXp + dto.xp; diff --git a/apps/skilltree/apps/web/Dockerfile b/apps/skilltree/apps/web/Dockerfile index 6f710fe54..2e642dbe7 100644 --- a/apps/skilltree/apps/web/Dockerfile +++ b/apps/skilltree/apps/web/Dockerfile @@ -33,6 +33,7 @@ COPY packages/shared-utils ./packages/shared-utils COPY packages/shared-error-tracking ./packages/shared-error-tracking COPY packages/shared-vite-config ./packages/shared-vite-config COPY packages/shared-api-client ./packages/shared-api-client +COPY packages/shared-app-onboarding ./packages/shared-app-onboarding # Copy skilltree web COPY apps/skilltree/apps/web ./apps/skilltree/apps/web diff --git a/apps/skilltree/apps/web/src/lib/components/AchievementCard.svelte b/apps/skilltree/apps/web/src/lib/components/AchievementCard.svelte index 7260b1044..5c0130824 100644 --- a/apps/skilltree/apps/web/src/lib/components/AchievementCard.svelte +++ b/apps/skilltree/apps/web/src/lib/components/AchievementCard.svelte @@ -74,7 +74,11 @@
- + +{achievement.xpReward} XP diff --git a/apps/skilltree/apps/web/src/lib/components/AchievementCelebration.svelte b/apps/skilltree/apps/web/src/lib/components/AchievementCelebration.svelte index f1a631729..449be8768 100644 --- a/apps/skilltree/apps/web/src/lib/components/AchievementCelebration.svelte +++ b/apps/skilltree/apps/web/src/lib/components/AchievementCelebration.svelte @@ -59,7 +59,9 @@
-

Achievement freigeschaltet!

+

+ Achievement freigeschaltet! +

{result.achievement.name}

diff --git a/apps/skilltree/apps/web/src/lib/components/StatsOverview.svelte b/apps/skilltree/apps/web/src/lib/components/StatsOverview.svelte index 4cb30b72c..e9ac35d87 100644 --- a/apps/skilltree/apps/web/src/lib/components/StatsOverview.svelte +++ b/apps/skilltree/apps/web/src/lib/components/StatsOverview.svelte @@ -66,7 +66,10 @@
- +
@@ -74,7 +77,9 @@

Achievements

- {achievementStore.stats().unlocked}/{achievementStore.stats().total} + {achievementStore.stats().unlocked}/{achievementStore.stats().total}

diff --git a/apps/skilltree/apps/web/src/lib/services/storage.ts b/apps/skilltree/apps/web/src/lib/services/storage.ts index aed738d03..0864a8308 100644 --- a/apps/skilltree/apps/web/src/lib/services/storage.ts +++ b/apps/skilltree/apps/web/src/lib/services/storage.ts @@ -257,7 +257,9 @@ export async function saveAchievement(achievement: AchievementWithStatus): Promi await db.put('achievements', achievement); } -export async function saveAllAchievements(achievementsList: AchievementWithStatus[]): Promise { +export async function saveAllAchievements( + achievementsList: AchievementWithStatus[] +): Promise { const db = await getDB(); const tx = db.transaction('achievements', 'readwrite'); await tx.objectStore('achievements').clear(); diff --git a/apps/skilltree/apps/web/src/lib/stores/achievements.svelte.ts b/apps/skilltree/apps/web/src/lib/stores/achievements.svelte.ts index 2ba2611e1..b59ec086e 100644 --- a/apps/skilltree/apps/web/src/lib/stores/achievements.svelte.ts +++ b/apps/skilltree/apps/web/src/lib/stores/achievements.svelte.ts @@ -199,22 +199,14 @@ async function checkLocal(context: { unlockedAt: new Date().toISOString(), progress: condition.threshold, }; - achievements = [ - ...achievements.slice(0, i), - unlocked, - ...achievements.slice(i + 1), - ]; + achievements = [...achievements.slice(0, i), unlocked, ...achievements.slice(i + 1)]; await storage.saveAchievement(unlocked); newlyUnlocked.push({ achievement: a, xpReward: a.xpReward }); } else { // Update progress const updated = { ...a, progress: Math.min(current, condition.threshold) }; if (updated.progress !== a.progress) { - achievements = [ - ...achievements.slice(0, i), - updated, - ...achievements.slice(i + 1), - ]; + achievements = [...achievements.slice(0, i), updated, ...achievements.slice(i + 1)]; await storage.saveAchievement(updated); } } diff --git a/apps/skilltree/apps/web/src/routes/+page.svelte b/apps/skilltree/apps/web/src/routes/+page.svelte index 8a372fbe5..3107e489f 100644 --- a/apps/skilltree/apps/web/src/routes/+page.svelte +++ b/apps/skilltree/apps/web/src/routes/+page.svelte @@ -159,7 +159,9 @@ > {#if achievementStore.stats().unlocked > 0} - + {achievementStore.stats().unlocked} {/if} @@ -359,8 +361,5 @@ {/if} {#if showAchievementCelebration && currentAchievementUnlock} - + {/if} diff --git a/apps/skilltree/apps/web/src/routes/achievements/+page.svelte b/apps/skilltree/apps/web/src/routes/achievements/+page.svelte index bf5127b50..ad2fcd2f7 100644 --- a/apps/skilltree/apps/web/src/routes/achievements/+page.svelte +++ b/apps/skilltree/apps/web/src/routes/achievements/+page.svelte @@ -3,11 +3,7 @@ import { ACHIEVEMENT_CATEGORY_INFO, RARITY_INFO } from '$lib/types'; import type { AchievementCategory } from '$lib/types'; import AchievementCard from '$lib/components/AchievementCard.svelte'; - import { - ArrowLeft, - Trophy, - Star, - } from '@manacore/shared-icons'; + import { ArrowLeft, Trophy, Star } from '@manacore/shared-icons'; let selectedCategory = $state('all'); let showOnlyUnlocked = $state(false); @@ -23,7 +19,10 @@ return list.sort((a, b) => a.sortOrder - b.sortOrder); }); - const categoryEntries = Object.entries(ACHIEVEMENT_CATEGORY_INFO) as [AchievementCategory, { name: string; icon: string }][]; + const categoryEntries = Object.entries(ACHIEVEMENT_CATEGORY_INFO) as [ + AchievementCategory, + { name: string; icon: string }, + ][];
@@ -60,7 +59,9 @@

Fortschritt

- {achievementStore.completionPercentage()}% + {achievementStore.completionPercentage()}%
{#each Object.entries(RARITY_INFO) as [rarity, info]} - {@const count = achievementStore.achievements.filter((a) => a.rarity === rarity && a.unlocked).length} + {@const count = achievementStore.achievements.filter( + (a) => a.rarity === rarity && a.unlocked + ).length} {@const total = achievementStore.achievements.filter((a) => a.rarity === rarity).length} diff --git a/apps/skilltree/apps/web/src/routes/offline/+page.ts b/apps/skilltree/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/skilltree/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/storage/apps/web/Dockerfile b/apps/storage/apps/web/Dockerfile index 846807489..6cb1bd099 100644 --- a/apps/storage/apps/web/Dockerfile +++ b/apps/storage/apps/web/Dockerfile @@ -47,6 +47,7 @@ COPY packages/shared-utils ./packages/shared-utils COPY packages/shared-error-tracking ./packages/shared-error-tracking COPY packages/shared-vite-config ./packages/shared-vite-config COPY packages/shared-pwa ./packages/shared-pwa +COPY packages/shared-app-onboarding ./packages/shared-app-onboarding # Copy storage web COPY apps/storage/apps/web ./apps/storage/apps/web diff --git a/apps/storage/apps/web/src/routes/offline/+page.ts b/apps/storage/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/storage/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/todo/apps/web/scripts/generate-icons.mjs b/apps/todo/apps/web/scripts/generate-icons.mjs new file mode 100644 index 000000000..f6e874607 --- /dev/null +++ b/apps/todo/apps/web/scripts/generate-icons.mjs @@ -0,0 +1,34 @@ +#!/usr/bin/env node +import { readFileSync } from 'fs'; +import { join, dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const staticDir = join(__dirname, '..', 'static'); + +const sizes = [ + { name: 'favicon.png', size: 32 }, + { name: 'pwa-192x192.png', size: 192 }, + { name: 'pwa-512x512.png', size: 512 }, + { name: 'apple-touch-icon.png', size: 180 }, +]; + +async function generateIcons() { + try { + const sharp = (await import('sharp')).default; + const svgPath = join(staticDir, 'icons', 'icon.svg'); + const svgBuffer = readFileSync(svgPath); + + for (const { name, size } of sizes) { + const outputPath = join(staticDir, name); + await sharp(svgBuffer).resize(size, size).png().toFile(outputPath); + console.log(`Generated: ${name} (${size}x${size})`); + } + console.log('\nAll icons generated!'); + } catch (error) { + console.error('Error:', error); + process.exit(1); + } +} + +generateIcons(); diff --git a/apps/todo/apps/web/src/app.html b/apps/todo/apps/web/src/app.html index 95ab7a7bb..5e9c14d07 100644 --- a/apps/todo/apps/web/src/app.html +++ b/apps/todo/apps/web/src/app.html @@ -4,16 +4,21 @@ - - - - - + + + + + + - + + + + + Todo %sveltekit.head% diff --git a/apps/todo/apps/web/src/routes/offline/+page.ts b/apps/todo/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/todo/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/apps/todo/apps/web/static/apple-touch-icon.png b/apps/todo/apps/web/static/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4083d23104ab3db66754f2b306b8b93e92df79dc GIT binary patch literal 5269 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 literal 0 HcmV?d00001 diff --git a/apps/todo/apps/web/static/pwa-192x192.png b/apps/todo/apps/web/static/pwa-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..c7c7e5dae992ea2efa11096ddaef20ee87b17c87 GIT binary patch literal 5789 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 DB`|$v literal 0 HcmV?d00001 diff --git a/apps/todo/apps/web/static/pwa-512x512.png b/apps/todo/apps/web/static/pwa-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..dadf1fe185eb542acacc24903cb36312ad175b9b GIT binary patch literal 17703 zcmZ8p2|QHY`@aYwDJ>GBB&ksRq)4MxrK}-YriGNX>=IY0Bt@kX#S}$lnIe>J$R1MJ z*I{hgXRL$k-v7BXs(JsPk5_N^p7WgNJm*=z&$$H~=;;Uxt`&qJNciZHgGLa<4gQxK zTFeLjnDDNh1%C)!K4R_$K|(9=|G1#27i%C$20D6h-%0Nm!)-q9l0DHQj6790z10^s zrEQGdnASR1+NwFY+pBkzYWYD|$u)uL&DyjgQQuP+_U~W3@g|gNVWgX}G3|WXXo+^E zD9`%u$MyEh4C#t)UwTt6qkzvb(ZZ_EM6vwQtXFl*BggXkU%HB;7L$J8XQB&_${bNF zCMCRYpH4n_!~2n1X~kKs3ODRW%fSC86}_qlEJmg#(m$(%|Iec~(Du}4x3)EBx6U|G zUDe~_y}opTmntn2deJ@Wt0E3WDNAW+5nU0I?fNRQ3R0bQmDr7#R;J|Oe9{)%P=QOK zOZ~IzwoN(=eX%>*Uz1+snf0_$T&+!ai0Y|kVUZn`T$=Ut6m|6UxwgjKqJe(r?=k7` zo9qW1zt0y&$x^kp4G~6<9(OBOnb96~oi=tj9c?`KR5M~)(F<;Fpp8Tdjl1$A1=2_X zVJXvWPgVWMh+MsXR@87s_VZ!m?58$_H>l&%7Jku>6N+woGvbS#OwA^8E22w%Enciw z{>Ts0@gK}yXy3<`_uSRYEwY~{4Q8!PUSXyz#U!4c+qXn_Y@-iMbZ|B#CbrbH4D211 zpXv}n@t;v%R8{|dlfUX4!F}O%FDy5YinNHuo>kJk)Dbp&Iy&6fqD^`teU~#aaceOb zdm&hsF{hyGWQ_SVCG2NjUMo zY3+c0s`PK?ZyBj?w;wj#Iw|iwnjo?dY?}2WdmmeJ{$1&!==)9jw})3S9D4i{eGd~u z=DsHV4kR$~AGnns5!gF(GR{w9kaxp_5!)%9s}|AYbEl)N#=o+6BZ6KjA;$07&=_u? zdi9ZRtNzX5H43T@r^m6h%(^cb)MQWA`7ArL95<$!arVXN+hQ}*>_fRO~r&%pJZJN%{h57 z2VZyTgv&ZF%bOqBS1Jm&6nbm*xmxJ)e zVo1v$Id+hDqbhk$Ki2(ru2d9h(N7B-b-I%BcI`hNUeaBnOcy!pE49qeo%OXpc{R@w zvvNtC6J#A0I4{aWruvB_;ftR#Je5A8n;gyV9~r$e@+i+#U5KT6U?~?B)M`#Qz{zW8 zGjU0anN!-8NMwZRa5b9y4-t4JeN^MJ{L2USA50YnzfPGZChfLfI_TuFZer12Uf}!m zQTrD=pZi7(%?EyHtJ@Hs9S_sr_W9WM01-)S8#qok8@YLD%|t$T9k z-0bObwOqweo3>9fdnw)No$Y9)Yn3GqmzJ%4m`CiFS%WFm zJlVe9FL}hsy8qu9`(CGH2^su;FU{P)zi(ol-TZw!9puIzs-=?H<0w8|jX}liv;s8y zX6R9+aO$X&2a$uR7F9&#_*9QgO^V1ScU_kdU)g^fZQ0vFxFY|uAWP$w@ocDD80R!~ zWI7_?u*1>)K@&<|gr5zxDGuQcZ$*pWRgVmx9=c{3WP%a67rYw~LJN$DB=LLiI*Is( zy6JJe(9}lcz4&Y_4isRt)pLblr|bTB6PTXKQw)z8YI{Y`Kg<`>c1d&-4HrsIw_U0>-jbSYEGqPm z$F1&&d_vsbIZ_^tlBG6Rx@vUhug3AijI~(sQTecMXs`?KOLFm-m46gn8c~d)AOhMnELI! zAM_JHLm<>E{}U?3b|qTOZD6Nm)>MaqXw0!eaj-$r?eyv%;(TUS1Bc?0GNd@dY53xyFynZ@ zobFdFHJlH6Pn1#B5=rR zt0*%}EMO>pCJc4DV#%SF8?IwT&QRZ74IipyCML#l+N;D7k;?q#X{!VBO#56pr`(3G z>^MUm;(b}{x9XqjB;V;ITJnFe?Jb5Y+VnX@x@tEfU(aa+Ae&xzZh$)<$(PMDoD*-8Ji7>kERlwBT8 zo!$F=u*dV*2<5LU38bvD0^aNGki5tcbn%KF4~MlhGaJl*eQDJ2vFG~C{ckDRQ20t} z#Bl{^M3z&=l5qNp{8>irfdEfVaa}@6g|w%l89V`@5rv#P+=H&*efhw#d9t7=O1TGJ z{%?WgvMvg|c8H>zbm_|Te`id+%a0ByY3G`dep`&h@cvU<(`|H;_ma!;TOchChKjkd z;AkjO)K78b#Q%F-7?7e5yxUF=ZCxdTl#W8J3D!J_8^@uZyN)rX0*0z<*K3nG&kl?h zwE<%Pl@@;@1*F zBPY#R9<*Q;2isy+bdh*Ynx@RT{}6C5q*DJwKo&*+OMo$I`C{@FCyn3tDAT;qKaD%& zh2$zi|FlGTQ^%+kr*wDl!Y-WK2sz3$`wth#3n^KgT%6m0J`v;GhB1Sj#L2?5d+-b= z3&rk8#a2!h4D%@yfa1p@jAp8{GfDEXw3YhC>b;-z+mYh8Lw*j&`8>sJekhbRzJ1^m zyEm@Davxv2M7Wk_$z4)sn#f3aRl|~UDJLKEaa*?DY`u)=f(4|vA}-l7$^@)^ug_pZ zoQj6%PSVe?*?ZKhJ}1{@JDhT!*JEdZ#2fiAiZhT84~wVlN%cSVE4$?D)b^?J5rs12 zY2gYrte@>hLWs<2D=42Z#-vUp=Qz$Z-C22=n7vYP1DT+{A@f>x>ISw_QOymxAnZsN zT;VlVZ1=M$VCBJfZ~v3d8krOS8Bs=q`-4;VOw;$KFoknvKlD6Y{$*$pyV@h>D1$wi zBcnvsjo-D`JC+`KVn`_T_2pw*OmQ~g7&tp}v4Ztv_{E+GEM5O<1l!K-61Rb=M-lSw znkUo#74zuZ-Zu3Tn>KMJmIhN!nu0w%Vp1>bSr7d$6X~KK=_ql@Vk^bD!$2E|49f7= zoNgz2m~QR6dzr)s?1&uksP8SV<8ya0sjd9BHoF`j9rVPPao1dLNtRHecjUA5KTnx?{<(Dd8==&x|1Ipa_bcHu*iD|xr0?_z)46b- zY@Vxmi&^$die81C!I$(es~&&e)TbY>lba{b(r1d>YGfXlQJDaIv+}X8nF#xkbags_ zy7`r2zgAe5+j@`aUkE+D!u9B&V?$h6a<*%DaNA6Sw;{o~!6Uhi(E_Rs9stB)Be%hd`juGaIr zefGlKQ$x1lDFBxUzhx3z2g)wq$;L9!YX?&_>J$X7(Mf(O%)7?Ow!&|}_daY_#t#a% zt7ItWvL+-peQ@3WDb5CVZ!>73m#)LkySmQt`uGgwo%I>)F$B6&oa}91OSEej7aHE4 zFe&!AU6xY&w1qPGEqr=uMW_N*d57kJ-Ngi<)bkZ@_gtxd(0Vn-?cz@e-mx6}1+*s! zNJ`pD`uh}tuIy4fjRtNF+L#>B@IQj3`fqV0F*Kv+)mFZyXwkU0q{+aD-ZzN?h^BA} z%PE}hAoqTeUWCz4wY}%Ve)VOMzoZVT&r;$#Bl&M@6=2P(QnGnOn!abA#uhWuLmsU7 z0*&AWY{-djwql|Ju05v~GZV4b%d6YAOsy+sTB17a7>0z8p6)*(0AY@2 znAMh0K2Z~?JLMag+iYYp5B%5{#`BaVB2gZ4FWRhpxIWJkBvX*`_2S>f-unYPY|>^B zK0yJLr_99imICxu;?zta*6P+2thd~_Ce}Y<%V~OM?Ncx7u1G@UZhNgGX1B7r^9d5W z&>Eb-5K7d`YN+D@X-0%;*wS|V-mKO8*U;NK^k(I%bWI3JJKO=k1k~%9i2@oOglUAP zbAhmkY(s*vmfp5unF5#P+xmcA*c~W@bHKPM=HMxab`J|nkrJ&jcIGk&LY5gFb2bj* zy-xWZiroX2FJl_$vXs(Q76?vwFqopp zEAyR6)@)neaJNK|=_(YUA^7xxQR;m0ayl`IfY#unLMTf3C}K|Q!?u>#@g+H}+#NQt zhS%<3<+g$ylv6M=4Pse?1S}<}{eoeJg%SztXo+joHbaugfn)b)t+=qHDW(_@#$XuS z$SYINl#UK3QKfSGs4F2+8(>CBo=kpY;9h=nF9RMX_|Dnf472ClKPqJ*qZyFcRNDtr zFtD%tO3;;3qSSbH^@sERx+ius6Pr-c5a{Tork%FSWtev9#jIF=SS;Xkm&?Eo%A0se zr0#?8gU8vz%aF9wU8A_i`7IW(xXWd1;qB#R%M|)#WWW+(6arWxjtFhI2d@mBQIzZH zAij|E>>$71)GL?kcHBs~gL(-<+rd`D{JHMzLJfEIW81M zaK5%z-str0ao#Vp_avFhJNa3u1^@Oh`Iv~5JQC*#2ESW`l{fw9b=|(KiS%>%Lrt@+ z4oc%TB$4fFU#$+f(g!D#S***s zX7DSUHn~{tyCGqaU#Uv>{XUQopscjScw_ME4;pxwM$#7ZS40tMtPEgT2EHLg?BDNJT!aF zw9KshDw&=+FIkXN)2S{344j%Gy&)O0oc74{9_1ghoatdZ9Iwlq+63dx5%J-4C6STDPrCn0h%rxK(d`FeH!>jU8GP68lYm|2T`j-b0*yDYKERs%}A08F)zf*f%by% zeol13!2z4rPHvsnw2pwWXOEYE7%yJkq3C zmK)8*abfT(j1K&hgfUdB;J+{7m*~sAc9R>{MyJk175FgJQ(5^m1!U5tv3LR|VFG>S zPHz?ck<8dZdB{$tmE*gluK{XZf&r?_+S4YCbOXM^<7%_(#wFgdcPYw?1cKb(#fEE* z@J#I0JkghQ%6xYFI)m==9TfS>JQ{VOJ`r7o1OlS^T=Z9qHX{u&y%*t1myKXupnhT;OK^}ly#Ur^|IM(kSPu$JL6jfWRyCi!kbMZodn?@E!iCam%f z6n2zMz^Gp#VTik9dNAO`3H&8+*m!2Rlj)0RhGw|J*r&|A-+CbBut>YGMsLHN1qsR{ zxgb9r)kI&31qA0#dwKo#pv5SZBKGVOiAcK*PXh8h1%z7e%Rl;k?S-tbtnxo@yr*}X zIbe!7{NduxAJ?@{(*43$*mY+-U;3^MjX*?w(Y+5A_F>5&gKfYsnL$QSuMZD#=$Q7t zZZt1P8GnE?Or+g|ZSm!BQ(l%SYEZRk5ZVJgya+FBC8TY6EI(1-#H(`j z8t#nn!j$e%Fu_(!qbia+b+22&(QSy-mW%%()Nx-D$ zp05DtMxCLne}r0}RJ#4|QFR6Ot0! z(D+pW!cHj<2^KZ6p>26?ZvZ~2?B79PyBR>|*(vV3rAW*JAxSt~Fh8qCDh1)Gyqsrn z4KHq}ojcGV5G@--VPm0yqjLG<=lv`4sgHqsow6b`Dha=bW~(k<2?7QL2L&fD#wIiTBz?O3hT{$ZUh}G zAO?wc^zWdo>i`E|X4^O`=2=?}Tm+>}7HPr!UgAp8NdxaT^J5=$1MEtXt2ZeEyfQf`cVcH~e7ufei$RG5Jln_h|Mu@FVF;(EYBodAZeGx1*gX zW0ye6r7OuGr33j{<4I{w5p}fi20m6ENmqpK^WSy~Sl-6B7!@@`?0_30OQTt|MW;Ld4>D5A8IaMjL3awN&{0R>LVUoAb%Qh&qJ4Yie4Vx z<0(EM8k%LJOb0V)t=+Rt7E^h}hWTgTzzL-~T!EA#DGU$Mlf}gQS&xKOw1|uOvGOld z4tfm5i%$;Er!~a9n|1<8mY?GXUhR3MCm?g%<1VhuBRFZR4Jj5Gm9QL@*_d!Dah|fHd*saHV+2m zX3c`45t~-P*(fER@YMgn+tD6VV8Eaf1Zi(FT2ZUa&&!-jE8-sMioG^?KzmCu#Uf`% zYpHRCA%5Sa(nr>py_H(t1N3lE&!zfP_@BD~ZhL(895_~SIZwun6az3=F*0L11&Dn# z%}(b-H8FFKN-RHm_ILnDh{uk6NEjMw-)XuW4NvRb5D|Et`|3%zK0z_u-t(!ro4Z~q zQO)l==wU-DTSdH*PqjnHd*sA+#ghq|Mmx}Ow}xXbtL+~}#_eqpb^?Mir_#xJK%=(1 zx$DLFZD;DHBom~$U}=Wg_+TlIb(_KleHi|{1;E4uSXudZGxHT49<_GgoIsy8J~jL(&t_gCn__?@u`7C>Y0J&;OJkn%HQ8kMhVxz7Vt+*R6f?cisREp*Uipr4L zkIUIGL?oVgf*SNozogmCZ0L3E%7f0x;Y%SHJJA$EL_iiq)l01)FdEo{2z5hG{3`E8Q5APXQPY~PA< z;U&YlT7m0H{4$>K+3zbB_-P5m!K_+$P@@i3yV`Eo5xC=U`^Ak`x(7>8*mWPq^cSE+ z513xcQlu8;vWmr{LU*ldtC5WH3xr`2Hq55=3~cHwD62C4<&}M&YjRyFe`)-nC69fA z1OpXxFTVZ?tlTh+r*`~|=DDQHXV{bqV;bPml%>G?G}l=9^m%ylA5_b>mar|5 zW@VFdOkW(skO!LK=da(cUfIGU`;_R|UTR9fd5k#5nEn9fhcfk}0l>F9?6zDlb&T3r zE&$^qB^azi*MY?wq_Fb-xm4pEiI?rmbSm%8MrzIFe@HSfX=2OBKn-07B8ECI_Rg)a zDJ2JOT^z=H{K&rUbi2deZA_=RmyL?XVdFW?!CiWu19y8Z5s`}FM5vTuM|4@TXJ=>FU_EdfJPHYwH@B-nv<=62t zS`_84uA+MO{L~D>4O_fNE-+8WucU>z_6e|{Ei?8k?JJ<<9z(Wn24`lAOjkc*^v}mC z4k};n2^!?<=|538Rx&PIoV|!=G;|ep_jVl4p4IU?JdkEYikuy)Z4ODG5Vnbsr5?9b zd%fvB}Bge?OZ#R=s8i{*j*8T z_Y7J}LC-+-`R$${2Y%amFROm7o$PZ}-q$s%3#g?rD3g24@b*A^v&Od;l>5%?y}HB* z>9*|~)k%YF*Q2|PDK9ep8K`9>ljw6y&;M%6gV$d7Zw;Rv3UAZeq~EH#(Luk04aI|w zfiEaRse2HYT`dn432pMctqn@IZj?Dx-zz&oebJM`s;UC9)CFu@`&herz{GZnrP@?w6nIrYX0urDvpw zntnko_`PK8@$w`%%d<%q=oRmc zFa7J;%a^Orm2nR&&P*)4Hnx*lDi^4?&snp&P?UANq8>;EdooaM+nYM*$B@}bUn6dI zK@$L%vpBEzRi?>ksZ1xErDo|3_&UX78+ zSYJeMb@%iL;lgzRmJww`C>BT^f;fLitw={8_QGw3k>Tj~zZ}^YI@7^Prer}rT%zD4 zx`5o$ONmudVp*@Gy?sechFv9~OxuvkZz+zbuqS|k9 zbYRZAGdLn+_P^@AyCm^UaT=uRhVm1<(Fvo{Q;V=f z{c4a%7FtE@|61|g?6B>y!cM02*-dBxP(8Bu4gZ<2(@7<&Fw8J>D-QlbbDNPFpG}iB z>7u-$!;CBLK5VFCzTcI`TB;IwfsE8i*Zy z)~D~}fgXXn<*7pg5Dc!*bl}`+)yJF>3TPhSN6{|wVZZu)7dmo3-enNyo=BRZ-4B-Z z2|dvQ8ZIEjYPR{R_-Hl~+{wsY9+V68KfZ;#T}K_qO<$$*!jn&jW`(Pf^2(;k0ai&X zvgSGq(bjs-?hTxwo2A*mTlKrzbY96MwQjUPH!#LY~s4rItLP1*`?`ns6f)w@0$^chAX7*%@UI$TjhpIYBwe*HI z9W=_P6F}PX2}naH7JBTPGrB^;XZb1x#epJiy7Z5A@F@NU_#k*fD1V#Xs0$oi48Q*5 zI9IorDgBDTMz(SK06^buofls5VKVITQ_Cy}4H^uicmcJF!@In*yk}xEN3YOD6x0U1 zcoF_jrL3CcCom)Fd2WNRgI)^I>mi^rv8retI8KoZQ3vq$8+gZ!?%|fP#VgRCQVVqh zfSw^F@cHZmLG56s7`RihhJN&9QKREr4`3>Vz-pq4ti&2u20WulALH8017~nOO3mcD z0a_soC=X#ZuS^N^xdF6m@twy}&nb~SSRv?uAb^Ee9nv%0%iNF?pi{wn{Mb>f<@~RY zi;-}?4x%;K=ns0BJFqZSK}eZrgPcvxS}{aKod;v(>~~=sAT9tYdP{AOoc74yXFU&a z5&&os+>yGcH~?JG>2i$AAZ=>vZgJNp(IfG8yND0c_|Qp=kzzv4lIp5MY)nR)@i2<-p9GGxE=)0b8OnPSlT$`eA5@-Rra`!Qwe zfV&T{jbK0&+hWXDENd7-CO2o!i>QlXk$^*oAOJjpb4`I(it+6{HI^^ub9B@u}E0*nf%g z)WglRg*KOj1xrm>?y&eE>xzg&808_ZKnsB2@nQm=*7S6_ShDnu)%6t%XAr+^?*PxA zbh@16cwWO00o^&c2M2<2{bLc96J+v(>WQL(V?MZcvBT&pga>5zL@l%#ungKb?D!;# z=7GOX^TEmN9pE8`a!?p1g1`C(Q8GAKi@if}0e{UcCRPBFpohZ>iH6102=LeTE;4>C zL_fi}bYVSPL<ztN^hrwBZY(lq|F^zW=VWtD#_7X$VfeGNT6;$JCU@A%@ z9|DA^^al3b7D^E>tPiHng~7kU>VCz0kwo0GmY}ad#yl;B{QxZE3$)V7?}1P* zGq>IeT*~ARg5NI4C6s9fY6rq8P$10Dq_CGRztcrD1taNnbubdPWe&1&T7ozaqKosSgd<&avLx)s-n9Jr z8!%3yu#`9rNYr(bby)JpZ0@lWk#)>Lz#8Q$Qpgr7>7MvMAPSsBApDuViSQjoa6KS# zwUdlravJ?}tq4|$XWeol5)cm@2vQ{J;gCQ5PP2X%V=KE!U7s|N5AqyetMCOO|4R`#kKxN~i=6&@RxT zcqTYTOKNpZkqv`gj$}~&x4{#8wo)+GueRZBp6R3-!GHQet81vLZvoIj?3z1$`Xf+? z2xbtFB4G^zVEYwxuX9`qs9XLnd*G0-g>H$4%~VHNkwcI56@i$< zkG<|>`hw;VVKELac1RC%Z?{dP@`&}xjrg270WKO5V*}tPV4s0si7j9oAd2u0gV1N{ zo-u2ZcF4d<2qcR7YeV5x_?RNLO@cAeISET=)^~lGkp!1zh{sDQU%}*kEbGL848%j* z{eWi!cx~3<=r!QZ4C#N8m>^Jqpz9PuM)KAE>$& zT_hQh*q*lQHMhYA)IQ_m;>&Qxd}`&P02Yx#I20$+31T4x?$!VsetezK0wp#A6t;t6 zppV!At0zmK9~Gb-#XxlomZFl2PIm6oX3Z{!Z{xFR(jnZ-&f`(BI4;2J^2*Cti`+V1 zko{8(To4i9smNPV`&!NNz~j@RbP)it$AdI!)@n;OL|1uvZs(IR6&al6*)9Tb43zJz zTN5c?^JuRnnfw8isIB^yyt8Rl7PsySLS&wG(HM>*!LP)b`arG?Qm|T6TS2>j+cVb! z0t9fsaKWi>SMkIPk8*k$wq^IJPxCvkfv(Cq+|iw+lR&$evKm02Xj8?PkT7tPC6Cw!?IegW?ajz0X5#3N`=`^phQWwsne>l@XWSG`1R(JrH$hT>p^EFsPDy_j#-SaBVCmK;N!N*oY_ z@EQ>=@n(g332?VnlNu-CyHQtAV)k)_VtV&Y1mOhQETpzdz@k5z^LvL@LeBx&u`3D8o1{B2uu`sNreyvd9 zFA~~I*pjm_Vhbx%pI(KP`%D#dP?sI4JXY+2vg*)a6>!7$N1fyS8x$XAV*gyMqGwbw zWYgQN!rQ+){s#L-J25sCyW2eRb_?V~R~Ny`)27tpzxwFP{M^I)Fgtt!tf>5-laPvY zY+}>*8vt+7UmC_;R^T&>3OdgNn*rrL7sfbhCu*geq}Ab~gxZ@brguj-6#5y<{FKl3 zSKVSI4EzE3iEJ8$YA>{#ghB0mup0xM!By*eo@KtHr)K0)9IK%e31GoGkfvx`RXw?Y z>ImT7W^%91AJEitj%4dR!`_<&xbF{Tyw!xlu2W_Jvgy>fTjlGcfJR%Jw=$V8{-8vc z!u<~>b20Zab$CGYX2w!yY^N7DP1FOlpIF89As;Vj#DurwFg3no}|ou$eq%$3{-cZ*A;r5&^SKY59b!_)Qj3-I&jI zcQW}8Z&Tj0r*Z*5{U)T{TUqq}0=Ur@7mU>!%JaQ%DJ~j%OIk0F;Je1|+9zzXB7yI? z=4F{W5&%ZsU9Z$GY~XT7_QIk0%9t7S!-QlN8%8C)yZT6I8g)8X^>B0@9}3KGz!Fo_ zvG%=ivy^)i0IQxSOqHkS`~v+M;Fi4A`uC58XYYMx(C?h#83^y8lQbIq)Z~@tZAdE{ zx4pCy6hsqrx^I)s76U$TR&JP+Fp6;zV`@qL5 z$$Pf-_mReH1JaY?@2aT7sO6eWmOoN$t8;&wcq&bdGYJqb6G< z>@6)t)x`UfG<=BXQry*=I6fSMH?0MksP^of8x4Healby8a~2<(E^coA+&MB6+Bi6i zeMoFt%XWM$UhXlNnRPaN;aD>kG`>0@xD*m$V`{i&z$F(EdBObLV56G0$4+&b zCsV%_C7QZ&t${UPYO%6j_L}178AQYI@=b&>_#VN>sjTB?>8;(puawVB zay(WG0=vfA&xuV}S(byJ4LIhK4yx(%_Grt`!}G!Rzv^t{+0XIcg!7Bg6`7dwv6Iic z4VwrGc`|H-k2SFvLfS^b&Bz23u>eLkRA0xz=TGqAml$RlN#CM%B9d}U&79+_Bht^+ z80`xtG>2{Iv^6?0Wx_d66blZ=lumd@rxbrL&0g!o$*2Zx)RNvmjc)7I0n>^(rwL(< z{-ew%_(!iJ_MfKk;K}}h4@)3*dDys^?cT?9RjU(Ik(|@GG1@ygy}xFKzg?HgOk2vP zK{*cHycr5xIL$^>JS`vHbmPeT9hn@PSA9jJ#O}2E{Pse}_;qj@by1@Pr^1V(#Rp*L zql=Gia=fdjm8`C+3I^#U9$2~2&1ktS^H;In@FRP}{T z;5xQxJ7QM*TKd?{=#k!5(wnu(9ABUjRxCn&9|?KE+g=?2-)q0&pvMryn%&PHIuXD7 zl`&X~<2yPMLja?>VTqzywz!*pYX2#NLu@6!h{G@CnDNNWy$^ouh`wKs>8Ukwd~Z|j z9gJy@sWwsce!ut*zHNN}a|@?I#Py*(r5leQd0%jvr1{lcB6r1 zEY&C7CSjt=dP?|qg@|q8BCppDCvZs9SOBf|8!Yn@(S7y||JK;*{*(mA78U&Le^GKf zYDVYHzjnJfG{MxmiwOnNuuH>L2wGHt|GNNxdVKbW!HaQCR1ZP+oj)0}!8>Doe2 z^)__EVh=tJx0hsIdtdO4-JD^0i3`X#ENxy#j`rYWxYcv}Puu>e8n&y861yqf%J6y0 z(IN%>)ARVXslI=$@O&`rq>&bzfz<@>I_$LkxZ3HKzryLdiK}Q;nd4;Q|H?Pb6}~GO z>iR31EBWxD6TRYHA~TFF<+sMrlW~(;f7jgH1*|@gFjHRQwKCwGCN5THjAj<7!E(#I)-+PnGs}zcE=TF};V0+wmq!cNhx`@WS==9@ zJ%`kINFptTjqBFcn!7}w`gQ)F!s^rYr$IRQZk=)5U)_=aJgNKFb;7YayE&uDr{F#p zOI12Xg+Ls#JLDAKha8F&xi!3Q_h#^2w~o=IslJ`xPWBk^8~n=$PU-!ftI{I}l`KE> zb)D7J={=g7f+=fAB&EO8sQ4RB$cwS4dug$o{CaMY`mym3Ra~kySQG`} zmP7cc_mbt?f%2UXg->isj2X@J1KC62RPdt5_=nG)^|leA9}T>H)qR(&sS%9RR9K5iHN zgq_iZX@X;pY`x3de;nwiOUsRk=iu*(z`DXR6pv7;88U8uEjQe!?>1LPI+1kMKl!C# hqXBz6%~68mvh1j(5?*rPUp|439@0CQvj5DD{{xk9@#Fvi literal 0 HcmV?d00001 diff --git a/apps/zitare/apps/web/Dockerfile b/apps/zitare/apps/web/Dockerfile index 18a0ef407..d101981e4 100644 --- a/apps/zitare/apps/web/Dockerfile +++ b/apps/zitare/apps/web/Dockerfile @@ -43,6 +43,7 @@ COPY packages/shared-ui ./packages/shared-ui COPY packages/shared-utils ./packages/shared-utils COPY packages/shared-error-tracking ./packages/shared-error-tracking COPY packages/shared-vite-config ./packages/shared-vite-config +COPY packages/shared-app-onboarding ./packages/shared-app-onboarding # Copy zitare content package COPY apps/zitare/packages/content ./apps/zitare/packages/content diff --git a/apps/zitare/apps/web/src/routes/offline/+page.ts b/apps/zitare/apps/web/src/routes/offline/+page.ts new file mode 100644 index 000000000..189f71e2e --- /dev/null +++ b/apps/zitare/apps/web/src/routes/offline/+page.ts @@ -0,0 +1 @@ +export const prerender = true;