diff --git a/CLAUDE.md b/CLAUDE.md index a6e66ff1..f1e1746d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,6 +17,14 @@ After calling the list-sections tool, you MUST analyze the returned documentatio Analyzes Svelte code and returns issues and suggestions. You MUST use this tool whenever writing Svelte code before sending it to the user. Keep calling it until no issues or suggestions are returned. +## Common Svelte 5 Pitfalls + +### `{@const}` placement +`{@const}` can ONLY be the immediate child of `{#snippet}`, `{#if}`, `{:else if}`, `{:else}`, `{#each}`, `{:then}`, `{:catch}`, ``, `` or ``. It CANNOT be used directly inside regular HTML elements like `
`, `
`, etc. Use `$derived` in the ` + +
+
+ + {monthLabel} + +
+ +
+ {#each weekdays as day} +
{day}
+ {/each} + + {#each calendarDays as day} + {@const key = format(day, 'yyyy-MM-dd')} + {@const dayStickers = stickersByDate.get(key) || []} + {@const inMonth = isSameMonth(day, viewDate)} +
0} + > + {format(day, 'd')} + {#if dayStickers.length > 0} +
+ {#each dayStickers.slice(0, 6) as completion} + {@const sticker = getStickerById(completion.stickerId)} + {#if sticker} + {sticker.name} + {/if} + {/each} + {#if dayStickers.length > 6} + +{dayStickers.length - 6} + {/if} +
+ {/if} +
+ {/each} +
+
+ + diff --git a/src/lib/components/tasks/StickerPopup.svelte b/src/lib/components/tasks/StickerPopup.svelte new file mode 100644 index 00000000..d481f04a --- /dev/null +++ b/src/lib/components/tasks/StickerPopup.svelte @@ -0,0 +1,121 @@ + + + + + + diff --git a/src/lib/components/tasks/TaskForm.svelte b/src/lib/components/tasks/TaskForm.svelte new file mode 100644 index 00000000..87d2a770 --- /dev/null +++ b/src/lib/components/tasks/TaskForm.svelte @@ -0,0 +1,698 @@ + + +
{ e.preventDefault(); handleSubmit(); }}> +
+

{task?._id ? 'Aufgabe bearbeiten' : 'Neue Aufgabe'}

+ +
+ + {#if error} +

{error}

+ {/if} + +
+ + +
+ +
+ + +
+ +
+ +
+ {#each USERS as user} + + {/each} +
+
+ + +
+ + Bestimmen Sticker-Belohnungen + + +
+
+ + {#if tagDropdownOpen && filteredDropdownTags.length > 0} +
+ {#each filteredDropdownTags as { tag, icon }} + + {/each} +
+ {/if} +
+
+ + +
+ {#each AVAILABLE_TAGS as { tag, icon }} + + {/each} +
+ + + {#if selectedTags.length > 0} +
+ {#each selectedTags as tag} + {@const Icon = getTagIcon(tag)} + + {/each} +
+ {/if} +
+ +
+ + Schwerere Aufgaben geben seltenere Sticker +
+ + + + +
+
+ +
+ + +
+ +
+ +
+ + {#if isRecurring} +
+ + +
+ + {#if frequencyType === 'custom'} +
+ + +
+ {/if} + {/if} + +
+ + +
+
+ + diff --git a/src/lib/utils/stickers.ts b/src/lib/utils/stickers.ts new file mode 100644 index 00000000..8c101169 --- /dev/null +++ b/src/lib/utils/stickers.ts @@ -0,0 +1,157 @@ +export interface Sticker { + id: string; + name: string; + image: string; // path under /stickers/ + description: string; + rarity: 'common' | 'uncommon' | 'rare' | 'legendary'; + category: string; +} + +// Blobcat sticker catalog — images from Tirifto's Blobcats (Free Art Licence) & tastytea (CC0) +export const STICKERS: Sticker[] = [ + // Cleaning / household + { id: 'clean-cat', name: 'Putzkatze', image: 'blobcat_clean.svg', description: 'Alles blitzeblank!', rarity: 'common', category: 'cleaning' }, + { id: 'sparkle-proud', name: 'Glitzerkatze', image: 'blobcat_sparkling_proud.svg', description: 'Stolz auf die Sauberkeit', rarity: 'uncommon', category: 'cleaning' }, + { id: 'hammer-cat', name: 'Handwerkerkatze', image: 'blobcat_hammer.svg', description: 'Hier wird angepackt!', rarity: 'uncommon', category: 'cleaning' }, + { id: 'in-box', name: 'Kartonkatze', image: 'blobcat_in_box.svg', description: 'Alles eingeräumt', rarity: 'rare', category: 'cleaning' }, + + // Plants / garden + { id: 'rose-red', name: 'Rosenkatze', image: 'blobcat_rose_red.svg', description: 'Eine rote Rose für dich', rarity: 'common', category: 'plants' }, + { id: 'rose-pink', name: 'Blümchenkatze', image: 'blobcat_rose_pink.svg', description: 'Rosarote Blütenträume', rarity: 'common', category: 'plants' }, + { id: 'strawberry', name: 'Erdbeerkatze', image: 'blobcat_strawberry.svg', description: 'Erntezeit!', rarity: 'uncommon', category: 'plants' }, + { id: 'earth-cat', name: 'Erdkatze', image: 'blobcat_earth.svg', description: 'Die ganze Welt ist ein Garten', rarity: 'rare', category: 'plants' }, + + // Kitchen / cooking + { id: 'cutlery', name: 'Besteckkatze', image: 'blobcat_cutlery.svg', description: 'Messer und Gabel bereit', rarity: 'common', category: 'kitchen' }, + { id: 'cupcake', name: 'Muffinkatze', image: 'blobcat_cupcake.svg', description: 'Süße Belohnung!', rarity: 'common', category: 'kitchen' }, + { id: 'eating-cupcake', name: 'Naschkatze', image: 'blobcat_eating_cupcake.svg', description: 'Nom nom nom', rarity: 'uncommon', category: 'kitchen' }, + { id: 'pot-cat', name: 'Topfkatze', image: 'blobcat_pot.svg', description: 'Was köchelt da?', rarity: 'uncommon', category: 'kitchen' }, + { id: 'hungry', name: 'Hungrige Katze', image: 'blobcat_hungry_cutlery.svg', description: 'Wann gibt\'s Essen?', rarity: 'rare', category: 'kitchen' }, + + // Errands + { id: 'profit', name: 'Geschäftskatze', image: 'blobcat_profit.svg', description: 'Guter Deal!', rarity: 'common', category: 'errands' }, + { id: 'idea-cat', name: 'Ideenkatze', image: 'blobcat_idea.svg', description: 'Heureka!', rarity: 'uncommon', category: 'errands' }, + + // General / universal — positive emotions + { id: 'happy', name: 'Zufriedene Katze', image: 'blobcat_content.svg', description: 'Alles gut!', rarity: 'common', category: 'general' }, + { id: 'heart', name: 'Herzkatze', image: 'blobcat_heart.svg', description: 'Mit Liebe gemacht', rarity: 'common', category: 'general' }, + { id: 'heart-eyes', name: 'Verliebte Katze', image: 'blobcat_heart_eyes.svg', description: 'So schön!', rarity: 'common', category: 'general' }, + { id: 'hooray', name: 'Jubelkatze', image: 'blobcat_hooray.svg', description: 'Hurra!', rarity: 'common', category: 'general' }, + { id: 'waving', name: 'Winkende Katze', image: 'blobcat_waving.svg', description: 'Hallo!', rarity: 'common', category: 'general' }, + { id: 'laughing', name: 'Lachkatze', image: 'blobcat_laughing.svg', description: 'Hahaha!', rarity: 'common', category: 'general' }, + { id: 'thumbs-up', name: 'Daumen-hoch-Katze', image: 'blobcat_thumbs_up.svg', description: 'Super gemacht!', rarity: 'uncommon', category: 'general' }, + { id: 'sparkle-eyes', name: 'Funkelkatze', image: 'blobcat_sparkle_eyes.svg', description: 'Augen wie Sterne', rarity: 'uncommon', category: 'general' }, + { id: 'finger-guns', name: 'Fingerpistolenkatze', image: 'blobcat_finger_guns.svg', description: 'Pew pew!', rarity: 'uncommon', category: 'general' }, + { id: 'proud', name: 'Stolze Katze', image: 'blobcat_proud.svg', description: 'Richtig gut!', rarity: 'uncommon', category: 'general' }, + + // Achievement / reward + { id: 'crown', name: 'Königskatze', image: 'blobcat_crown.svg', description: 'Majestätisch!', rarity: 'rare', category: 'achievement' }, + { id: 'cool', name: 'Coole Katze', image: 'blobcat_cool.svg', description: 'Eiskalt erledigt', rarity: 'rare', category: 'achievement' }, + { id: 'hero', name: 'Heldenkatze', image: 'blobcat_hero.svg', description: 'Held des Tages!', rarity: 'rare', category: 'achievement' }, + { id: '10-of-10', name: 'Perfekte Katze', image: 'blobcat_sign_10_of_10.svg', description: '10 von 10!', rarity: 'rare', category: 'achievement' }, + { id: 'birthday', name: 'Geburtstagskatze', image: 'blobcat_birthday.svg', description: 'Party!', rarity: 'rare', category: 'achievement' }, + + // Cozy / relaxed + { id: 'sleeping', name: 'Schlafkatze', image: 'blobcat_sleeping.svg', description: 'Zzzzz...', rarity: 'uncommon', category: 'cozy' }, + { id: 'tea', name: 'Teekatze', image: 'blobcat_drinking_tea.svg', description: 'Erstmal Tee', rarity: 'uncommon', category: 'cozy' }, + { id: 'cocoa', name: 'Kakaokatze', image: 'blobcat_drinking_cocoa.svg', description: 'Mmh, Kakao!', rarity: 'uncommon', category: 'cozy' }, + { id: 'book', name: 'Lesekatze', image: 'blobcat_book.svg', description: 'Ein gutes Buch', rarity: 'rare', category: 'cozy' }, + { id: 'blanket', name: 'Deckenkatze', image: 'blobcat_blanket.svg', description: 'Eingekuschelt', rarity: 'rare', category: 'cozy' }, + { id: 'teapot', name: 'Teekannenkatze', image: 'blobcat_teapot.svg', description: 'Tee ist fertig!', rarity: 'rare', category: 'cozy' }, + + // Rare / special + { id: 'rainbow', name: 'Regenbogenkatze', image: 'blobcat_rainbow.svg', description: 'Alle Farben!', rarity: 'rare', category: 'special' }, + { id: 'angel', name: 'Engelskatze', image: 'blobcat_angel.svg', description: 'Himmlisch!', rarity: 'rare', category: 'special' }, + { id: 'scientist', name: 'Wissenschaftskatze', image: 'blobcat_scientist.svg', description: 'Für die Wissenschaft!', rarity: 'rare', category: 'special' }, + + // Quirky / cute (general pool — drops for any task) + { id: 'adorable', name: 'Süße Katze', image: 'blobcat_adorable.svg', description: 'Unwiderstehlich süß!', rarity: 'uncommon', category: 'general' }, + { id: 'adoring', name: 'Bewundernde Katze', image: 'blobcat_adoring.svg', description: 'So toll!', rarity: 'common', category: 'general' }, + { id: 'joyful-surprise', name: 'Überraschte Katze', image: 'blobcat_joyful_surprise.svg', description: 'Oh! Was ist das?', rarity: 'uncommon', category: 'general' }, + { id: 'purring', name: 'Schnurrkatze', image: 'blobcat_purring.svg', description: 'Prrrrr...', rarity: 'common', category: 'general' }, + { id: 'x3', name: 'x3-Katze', image: 'blobcat_x3.svg', description: 'x3 UwU', rarity: 'rare', category: 'general' }, + { id: 'heart-tastytea', name: 'Liebevolle Katze', image: 'blobcat_heart_tastytea.svg', description: 'Ganz viel Liebe!', rarity: 'uncommon', category: 'general' }, + { id: 'blobcat-classic', name: 'Klassikatze', image: 'blobcat.svg', description: 'Die Originalkatze', rarity: 'rare', category: 'general' }, + + // Legendary + { id: 'astronaut', name: 'Astronautenkatze', image: 'blobcat_astronaut.svg', description: 'Ab ins All!', rarity: 'legendary', category: 'special' }, + { id: 'space', name: 'Weltraumkatze', image: 'blobcat_space.svg', description: 'Zwischen den Sternen', rarity: 'legendary', category: 'special' }, + { id: 'robot', name: 'Roboterkatze', image: 'blobcat_robot.svg', description: 'Beep boop!', rarity: 'legendary', category: 'special' }, + { id: 'ghost', name: 'Geisterkatze', image: 'blobcat_ghost.svg', description: 'Buuuuh!', rarity: 'legendary', category: 'special' }, +]; + +// Tag to sticker category mapping +const TAG_CATEGORY_MAP: Record = { + 'putzen': ['cleaning', 'general'], + 'saugen': ['cleaning', 'general'], + 'wischen': ['cleaning', 'general'], + 'bad': ['cleaning', 'general'], + 'küche': ['kitchen', 'cleaning', 'general'], + 'kochen': ['kitchen', 'general'], + 'abwasch': ['kitchen', 'cleaning', 'general'], + 'wäsche': ['cleaning', 'general'], + 'bügeln': ['cleaning', 'general'], + 'pflanzen': ['plants', 'general'], + 'gießen': ['plants', 'general'], + 'düngen': ['plants', 'general'], + 'garten': ['plants', 'general'], + 'einkaufen': ['errands', 'general'], + 'müll': ['cleaning', 'general'], +}; + +// Rarity weights per difficulty (higher = more likely) +// low: mostly common, rare/legendary very unlikely +// medium (default): balanced distribution +// high: rare and legendary much more likely +const DIFFICULTY_RARITY_WEIGHTS: Record> = { + low: { common: 65, uncommon: 25, rare: 8, legendary: 2 }, + medium: { common: 50, uncommon: 30, rare: 15, legendary: 5 }, + high: { common: 25, uncommon: 30, rare: 30, legendary: 15 }, +}; + +export function getStickerForTags(tags: string[], difficulty?: string): Sticker { + const weights = DIFFICULTY_RARITY_WEIGHTS[difficulty || 'medium'] || DIFFICULTY_RARITY_WEIGHTS.medium; + + // Determine relevant categories from tags + const categories = new Set(); + for (const tag of tags) { + const mapped = TAG_CATEGORY_MAP[tag.toLowerCase()]; + if (mapped) { + mapped.forEach(c => categories.add(c)); + } + } + // Always include general + achievement/cozy/special so all stickers can drop + categories.add('general'); + categories.add('achievement'); + categories.add('cozy'); + categories.add('special'); + + // Filter stickers by matching categories + const pool = STICKERS.filter(s => categories.has(s.category)); + + // Weighted random selection by rarity + const totalWeight = pool.reduce((sum, s) => sum + weights[s.rarity], 0); + let random = Math.random() * totalWeight; + + for (const sticker of pool) { + random -= weights[sticker.rarity]; + if (random <= 0) return sticker; + } + + // Fallback + return pool[Math.floor(Math.random() * pool.length)]; +} + +export function getStickerById(id: string): Sticker | undefined { + return STICKERS.find(s => s.id === id); +} + +export function getRarityColor(rarity: string): string { + switch (rarity) { + case 'common': return 'var(--nord14)'; + case 'uncommon': return 'var(--nord9)'; + case 'rare': return 'var(--nord15)'; + case 'legendary': return 'var(--nord13)'; + default: return 'var(--nord4)'; + } +} diff --git a/src/models/Task.ts b/src/models/Task.ts new file mode 100644 index 00000000..beef688d --- /dev/null +++ b/src/models/Task.ts @@ -0,0 +1,92 @@ +import mongoose from 'mongoose'; + +export interface ITask { + _id?: string; + title: string; + description?: string; + assignees: string[]; + tags: string[]; + difficulty?: 'low' | 'medium' | 'high'; + isRecurring: boolean; + frequency?: { + type: 'daily' | 'weekly' | 'biweekly' | 'monthly' | 'custom'; + customDays?: number; + }; + nextDueDate: Date; + lastCompletedAt?: Date; + lastCompletedBy?: string; + createdBy: string; + active: boolean; + createdAt?: Date; + updatedAt?: Date; +} + +const TaskSchema = new mongoose.Schema( + { + title: { + type: String, + required: true, + trim: true + }, + description: { + type: String, + trim: true + }, + assignees: [{ + type: String, + trim: true + }], + tags: [{ + type: String, + trim: true, + lowercase: true + }], + difficulty: { + type: String, + enum: ['low', 'medium', 'high'] + }, + isRecurring: { + type: Boolean, + required: true, + default: false + }, + frequency: { + type: { + type: String, + enum: ['daily', 'weekly', 'biweekly', 'monthly', 'custom'] + }, + customDays: { + type: Number, + min: 1 + } + }, + nextDueDate: { + type: Date, + required: true + }, + lastCompletedAt: { + type: Date + }, + lastCompletedBy: { + type: String, + trim: true + }, + createdBy: { + type: String, + required: true, + trim: true + }, + active: { + type: Boolean, + default: true + } + }, + { + timestamps: true + } +); + +TaskSchema.index({ active: 1, nextDueDate: 1 }); +TaskSchema.index({ tags: 1 }); + +export const Task = mongoose.model('Task', TaskSchema); diff --git a/src/models/TaskCompletion.ts b/src/models/TaskCompletion.ts new file mode 100644 index 00000000..d9463f1d --- /dev/null +++ b/src/models/TaskCompletion.ts @@ -0,0 +1,51 @@ +import mongoose from 'mongoose'; + +export interface ITaskCompletion { + _id?: string; + taskId: mongoose.Types.ObjectId; + taskTitle: string; + completedBy: string; + completedAt: Date; + stickerId?: string; + tags: string[]; +} + +const TaskCompletionSchema = new mongoose.Schema( + { + taskId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Task', + required: true + }, + taskTitle: { + type: String, + required: true, + trim: true + }, + completedBy: { + type: String, + required: true, + trim: true + }, + completedAt: { + type: Date, + required: true, + default: Date.now + }, + stickerId: { + type: String, + trim: true + }, + tags: [{ + type: String, + trim: true, + lowercase: true + }] + } +); + +TaskCompletionSchema.index({ completedBy: 1 }); +TaskCompletionSchema.index({ taskId: 1 }); +TaskCompletionSchema.index({ completedAt: -1 }); + +export const TaskCompletion = mongoose.model('TaskCompletion', TaskCompletionSchema); diff --git a/src/routes/(main)/+page.svelte b/src/routes/(main)/+page.svelte index f604d68d..16bb89ae 100644 --- a/src/routes/(main)/+page.svelte +++ b/src/routes/(main)/+page.svelte @@ -56,7 +56,8 @@ transmission: 'Transmission', documents: isEnglish ? 'Documents' : 'Dokumente', audiobooksPodcasts: isEnglish ? 'Audiobooks & Podcasts' : 'Hörbücher & Podcasts', - fitness: 'Fitness' + fitness: 'Fitness', + tasks: isEnglish ? 'Tasks' : 'Aufgaben' }); diff --git a/src/routes/tasks/rewards/+page.server.ts b/src/routes/tasks/rewards/+page.server.ts new file mode 100644 index 00000000..a90d5cb0 --- /dev/null +++ b/src/routes/tasks/rewards/+page.server.ts @@ -0,0 +1,14 @@ +import type { PageServerLoad } from './$types'; +import { redirect } from '@sveltejs/kit'; + +export const load: PageServerLoad = async ({ locals, fetch }) => { + const session = await locals.auth(); + if (!session) throw redirect(302, '/login'); + + const statsRes = await fetch('/api/tasks/stats'); + + return { + session, + stats: await statsRes.json() + }; +}; diff --git a/src/routes/tasks/rewards/+page.svelte b/src/routes/tasks/rewards/+page.svelte new file mode 100644 index 00000000..a8cbf02d --- /dev/null +++ b/src/routes/tasks/rewards/+page.svelte @@ -0,0 +1,378 @@ + + +
+ + + + +

Alle Sticker

+
+ {#each sortedStickers as sticker (sticker.id)} + {@const count = displayedStickers.get(sticker.id) || 0} + {@const owned = count > 0} +
+
+ {#if owned} + {sticker.name} + {:else} + ? + {/if} + {#if count > 1} + x{count} + {/if} +
+
+ {owned ? sticker.name : '???'} + + {rarityLabels[sticker.rarity]} + + {#if owned} + {sticker.description} + {/if} +
+
+ {/each} +
+ + {#if recentWithStickers.length > 0} +
+

Letzte Sticker

+
+ {#each recentWithStickers as completion} + {@const sticker = getStickerById(completion.stickerId)} + {#if sticker} +
+ {sticker.name} +
+ {completion.taskTitle} + + {completion.completedBy} · {formatDistanceToNow(new Date(completion.completedAt), { locale: de, addSuffix: true })} + +
+
+ {/if} + {/each} +
+
+ {/if} +
+ + diff --git a/static/stickers/blobcat.svg b/static/stickers/blobcat.svg new file mode 100644 index 00000000..530631e8 --- /dev/null +++ b/static/stickers/blobcat.svg @@ -0,0 +1,83 @@ + + + +GutkatoGutkatoTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_adorable.svg b/static/stickers/blobcat_adorable.svg new file mode 100644 index 00000000..921976d2 --- /dev/null +++ b/static/stickers/blobcat_adorable.svg @@ -0,0 +1,76 @@ + + + +Gutkato adorindaGutkato adorindaTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_adoring.svg b/static/stickers/blobcat_adoring.svg new file mode 100644 index 00000000..da698f2d --- /dev/null +++ b/static/stickers/blobcat_adoring.svg @@ -0,0 +1,141 @@ + + + +Gutkato adorasGutkato adorasTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_angel.svg b/static/stickers/blobcat_angel.svg new file mode 100644 index 00000000..340c3af3 --- /dev/null +++ b/static/stickers/blobcat_angel.svg @@ -0,0 +1,219 @@ + + + +Gutkato anĝeloGutkato anĝeloTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_astronaut.svg b/static/stickers/blobcat_astronaut.svg new file mode 100644 index 00000000..a2f4be8b --- /dev/null +++ b/static/stickers/blobcat_astronaut.svg @@ -0,0 +1,90 @@ + + + +Gutkato kosmovojaĝistoGutkato kosmovojaĝistoTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_birthday.svg b/static/stickers/blobcat_birthday.svg new file mode 100644 index 00000000..97b1bf98 --- /dev/null +++ b/static/stickers/blobcat_birthday.svg @@ -0,0 +1,192 @@ + + + +Gutkato, datrevenoGutkato, datrevenoTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_blanket.svg b/static/stickers/blobcat_blanket.svg new file mode 100644 index 00000000..8bfe7e02 --- /dev/null +++ b/static/stickers/blobcat_blanket.svg @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/stickers/blobcat_book.svg b/static/stickers/blobcat_book.svg new file mode 100644 index 00000000..80e4430f --- /dev/null +++ b/static/stickers/blobcat_book.svg @@ -0,0 +1,147 @@ + + + +Gutkato, libroTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024Gutkato, libro FUNDA-MENTODE ESPER-ANTO diff --git a/static/stickers/blobcat_clean.svg b/static/stickers/blobcat_clean.svg new file mode 100644 index 00000000..d79a0b02 --- /dev/null +++ b/static/stickers/blobcat_clean.svg @@ -0,0 +1,563 @@ + + + +Gutkato puraGutkato puraTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_content.svg b/static/stickers/blobcat_content.svg new file mode 100644 index 00000000..934d1bbf --- /dev/null +++ b/static/stickers/blobcat_content.svg @@ -0,0 +1,78 @@ + + + +Gutkato kontentaGutkato kontentaTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_cool.svg b/static/stickers/blobcat_cool.svg new file mode 100644 index 00000000..5cd14a8f --- /dev/null +++ b/static/stickers/blobcat_cool.svg @@ -0,0 +1,107 @@ + + + +Gutkato mojosaGutkato mojosaTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_crown.svg b/static/stickers/blobcat_crown.svg new file mode 100644 index 00000000..5c7162fa --- /dev/null +++ b/static/stickers/blobcat_crown.svg @@ -0,0 +1,583 @@ + + + +Kronkato + + + + + + + TiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024Kronkato diff --git a/static/stickers/blobcat_cupcake.svg b/static/stickers/blobcat_cupcake.svg new file mode 100644 index 00000000..14a609c2 --- /dev/null +++ b/static/stickers/blobcat_cupcake.svg @@ -0,0 +1,144 @@ + + + +Gutkato kuketoGutkato kuketoTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_cutlery.svg b/static/stickers/blobcat_cutlery.svg new file mode 100644 index 00000000..9d682d2f --- /dev/null +++ b/static/stickers/blobcat_cutlery.svg @@ -0,0 +1,150 @@ + + + +Gutkato, manĝilaroGutkato, manĝilaroTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_drinking_cocoa.svg b/static/stickers/blobcat_drinking_cocoa.svg new file mode 100644 index 00000000..c398174a --- /dev/null +++ b/static/stickers/blobcat_drinking_cocoa.svg @@ -0,0 +1,234 @@ + + + +Gutkato trinkas kakaon + + + + + + + Gutkato trinkas kakaonTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_drinking_tea.svg b/static/stickers/blobcat_drinking_tea.svg new file mode 100644 index 00000000..26e83412 --- /dev/null +++ b/static/stickers/blobcat_drinking_tea.svg @@ -0,0 +1,193 @@ + + + +Gutkato trinkas teon + + + + + + + Gutkato trinkas teonTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_earth.svg b/static/stickers/blobcat_earth.svg new file mode 100644 index 00000000..4aa61d26 --- /dev/null +++ b/static/stickers/blobcat_earth.svg @@ -0,0 +1,142 @@ + + + +Gutkato TeroGutkato TeroTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_eating_cupcake.svg b/static/stickers/blobcat_eating_cupcake.svg new file mode 100644 index 00000000..65299c72 --- /dev/null +++ b/static/stickers/blobcat_eating_cupcake.svg @@ -0,0 +1,130 @@ + + + +Gutkato manĝas kuketonGutkato manĝas kuketonTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_finger_guns.svg b/static/stickers/blobcat_finger_guns.svg new file mode 100644 index 00000000..6f2975b8 --- /dev/null +++ b/static/stickers/blobcat_finger_guns.svg @@ -0,0 +1,136 @@ + + + +Gutkato fingropafasGutkato fingropafasTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_ghost.svg b/static/stickers/blobcat_ghost.svg new file mode 100644 index 00000000..af2d4e3c --- /dev/null +++ b/static/stickers/blobcat_ghost.svg @@ -0,0 +1,86 @@ + + + +Gutkato fantomoGutkato fantomoTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_hammer.svg b/static/stickers/blobcat_hammer.svg new file mode 100644 index 00000000..4845a087 --- /dev/null +++ b/static/stickers/blobcat_hammer.svg @@ -0,0 +1,329 @@ + + + +Blobcat with hammerBlobcat with hammer2022-07-04tastyteahttps://schlomp.space/tastytea/blobcatsblobcatemojihammer diff --git a/static/stickers/blobcat_heart.svg b/static/stickers/blobcat_heart.svg new file mode 100644 index 00000000..cad89827 --- /dev/null +++ b/static/stickers/blobcat_heart.svg @@ -0,0 +1,121 @@ + + + +Gutkato, koroGutkato, koroTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_heart_eyes.svg b/static/stickers/blobcat_heart_eyes.svg new file mode 100644 index 00000000..adf39b98 --- /dev/null +++ b/static/stickers/blobcat_heart_eyes.svg @@ -0,0 +1,77 @@ + + + +Gutkato, korokulojGutkato, korokulojTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_heart_tastytea.svg b/static/stickers/blobcat_heart_tastytea.svg new file mode 100644 index 00000000..03d6bd47 --- /dev/null +++ b/static/stickers/blobcat_heart_tastytea.svg @@ -0,0 +1,491 @@ + + + + + + + + Blobcat with heart in paws + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Blobcat with heart in paws + 2022-06-13 + + + tastytea + + + https://schlomp.space/tastytea/blobcats/src/branch/main/svg/blobcat_heart.svg + + + blobcat + emoji + heart + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/stickers/blobcat_hero.svg b/static/stickers/blobcat_hero.svg new file mode 100644 index 00000000..7983b007 --- /dev/null +++ b/static/stickers/blobcat_hero.svg @@ -0,0 +1,145 @@ + + + +Gutkato herooGutkato herooTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_hooray.svg b/static/stickers/blobcat_hooray.svg new file mode 100644 index 00000000..f7c09248 --- /dev/null +++ b/static/stickers/blobcat_hooray.svg @@ -0,0 +1,155 @@ + + + +Gutkato, hura!Gutkato, hura!TiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_hungry_cutlery.svg b/static/stickers/blobcat_hungry_cutlery.svg new file mode 100644 index 00000000..ed8f7a26 --- /dev/null +++ b/static/stickers/blobcat_hungry_cutlery.svg @@ -0,0 +1,172 @@ + + + +Gutkato malsata, manĝilaroGutkato malsata, manĝilaroTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_idea.svg b/static/stickers/blobcat_idea.svg new file mode 100644 index 00000000..df2f6d59 --- /dev/null +++ b/static/stickers/blobcat_idea.svg @@ -0,0 +1,138 @@ + + + +Gutkato, ideoGutkato, ideoTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_in_box.svg b/static/stickers/blobcat_in_box.svg new file mode 100644 index 00000000..7a5e0bfa --- /dev/null +++ b/static/stickers/blobcat_in_box.svg @@ -0,0 +1,169 @@ + + + +Gutkato en skatoloGutkato en skatoloTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_joyful_surprise.svg b/static/stickers/blobcat_joyful_surprise.svg new file mode 100644 index 00000000..584a1cfc --- /dev/null +++ b/static/stickers/blobcat_joyful_surprise.svg @@ -0,0 +1,103 @@ + + + +Gutkato ĝojsurprizitaGutkato ĝojsurprizitaTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_laughing.svg b/static/stickers/blobcat_laughing.svg new file mode 100644 index 00000000..b588028f --- /dev/null +++ b/static/stickers/blobcat_laughing.svg @@ -0,0 +1,89 @@ + + + +Gutkato ridasGutkato ridasTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_pot.svg b/static/stickers/blobcat_pot.svg new file mode 100644 index 00000000..c6bbcb31 --- /dev/null +++ b/static/stickers/blobcat_pot.svg @@ -0,0 +1,172 @@ + + + +Gutkato, potoGutkato, potoTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_profit.svg b/static/stickers/blobcat_profit.svg new file mode 100644 index 00000000..863b15ce --- /dev/null +++ b/static/stickers/blobcat_profit.svg @@ -0,0 +1,192 @@ + + + +Gutkato, profitoGutkato, profitoTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_proud.svg b/static/stickers/blobcat_proud.svg new file mode 100644 index 00000000..ba10d7e3 --- /dev/null +++ b/static/stickers/blobcat_proud.svg @@ -0,0 +1,54 @@ + + + +Gutkato fieraGutkato fieraTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_purring.svg b/static/stickers/blobcat_purring.svg new file mode 100644 index 00000000..8f4ab811 --- /dev/null +++ b/static/stickers/blobcat_purring.svg @@ -0,0 +1,132 @@ + + + +Gutkato ronronasGutkato ronronasTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024RRR diff --git a/static/stickers/blobcat_rainbow.svg b/static/stickers/blobcat_rainbow.svg new file mode 100644 index 00000000..c99c4e63 --- /dev/null +++ b/static/stickers/blobcat_rainbow.svg @@ -0,0 +1,110 @@ + + + +Gutkato ĉielarkaGutkato ĉielarkaTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_robot.svg b/static/stickers/blobcat_robot.svg new file mode 100644 index 00000000..a4c49bab --- /dev/null +++ b/static/stickers/blobcat_robot.svg @@ -0,0 +1,170 @@ + + + +Gutkato robotoGutkato robotoTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_rose_pink.svg b/static/stickers/blobcat_rose_pink.svg new file mode 100644 index 00000000..9319f3ed --- /dev/null +++ b/static/stickers/blobcat_rose_pink.svg @@ -0,0 +1,148 @@ + + + +Gutkato, rozo rozkoloraGutkato, rozo rozkoloraTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_rose_red.svg b/static/stickers/blobcat_rose_red.svg new file mode 100644 index 00000000..65138b2e --- /dev/null +++ b/static/stickers/blobcat_rose_red.svg @@ -0,0 +1,148 @@ + + + +Gutkato, rozo ruĝaGutkato, rozo ruĝaTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_scientist.svg b/static/stickers/blobcat_scientist.svg new file mode 100644 index 00000000..f42fabe9 --- /dev/null +++ b/static/stickers/blobcat_scientist.svg @@ -0,0 +1,125 @@ + + + +Gutkato sciencistoGutkato sciencistoTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_sign_10_of_10.svg b/static/stickers/blobcat_sign_10_of_10.svg new file mode 100644 index 00000000..40f190ff --- /dev/null +++ b/static/stickers/blobcat_sign_10_of_10.svg @@ -0,0 +1,155 @@ + + + +Gutkato, afiŝo »10/10«Gutkato, afiŝo »10/10«TiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.202410/10 diff --git a/static/stickers/blobcat_sleeping.svg b/static/stickers/blobcat_sleeping.svg new file mode 100644 index 00000000..741cc80e --- /dev/null +++ b/static/stickers/blobcat_sleeping.svg @@ -0,0 +1,122 @@ + + + +Gutkato dormasZZZGutkato dormasTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_space.svg b/static/stickers/blobcat_space.svg new file mode 100644 index 00000000..712135ff --- /dev/null +++ b/static/stickers/blobcat_space.svg @@ -0,0 +1,106 @@ + + + +Gutkato kosmoGutkato kosmoTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_sparkle_eyes.svg b/static/stickers/blobcat_sparkle_eyes.svg new file mode 100644 index 00000000..5ff48191 --- /dev/null +++ b/static/stickers/blobcat_sparkle_eyes.svg @@ -0,0 +1,158 @@ + + + +Gutkato, brilokulojGutkato, brilokulojTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_sparkling_proud.svg b/static/stickers/blobcat_sparkling_proud.svg new file mode 100644 index 00000000..0be5729b --- /dev/null +++ b/static/stickers/blobcat_sparkling_proud.svg @@ -0,0 +1,77 @@ + + + +Gutkato fiervantaGutkato fiervantaTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_strawberry.svg b/static/stickers/blobcat_strawberry.svg new file mode 100644 index 00000000..a3b1d6ce --- /dev/null +++ b/static/stickers/blobcat_strawberry.svg @@ -0,0 +1,290 @@ + + + +Gutkato fragoGutkato fragoTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_teapot.svg b/static/stickers/blobcat_teapot.svg new file mode 100644 index 00000000..61379e9d --- /dev/null +++ b/static/stickers/blobcat_teapot.svg @@ -0,0 +1,356 @@ + + + + + + + + Blobcat drinks directly from teapot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Blobcat drinks directly from teapot + 2022-06-12 + + + tastytea + + + https://schlomp.space/tastytea/blobcats/src/branch/main/svg/blobcat_teapot.svg + + + blobcat + emoji + teapot + tea + + + + + + Thanks to mg for fixing the arm. + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/stickers/blobcat_thumbs_up.svg b/static/stickers/blobcat_thumbs_up.svg new file mode 100644 index 00000000..1a1096e1 --- /dev/null +++ b/static/stickers/blobcat_thumbs_up.svg @@ -0,0 +1,107 @@ + + + +Gutkato, dikfingro suprenGutkato, dikfingro suprenTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_waving.svg b/static/stickers/blobcat_waving.svg new file mode 100644 index 00000000..1852e953 --- /dev/null +++ b/static/stickers/blobcat_waving.svg @@ -0,0 +1,123 @@ + + + +Gutkato salutasGutkato salutasTiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024 diff --git a/static/stickers/blobcat_x3.svg b/static/stickers/blobcat_x3.svg new file mode 100644 index 00000000..6b9097b3 --- /dev/null +++ b/static/stickers/blobcat_x3.svg @@ -0,0 +1,74 @@ + + + +Gutkato, x3Gutkato, x3TiriftogutkatogutkatojfederujoGutkato, destinita al uzo kiel glumarko aŭ propra bildosigno, ekzemple en Federujo aŭ aliaj retaj komunikiloj.2024