Skip to content

Instantly share code, notes, and snippets.

View johannschopplich's full-sized avatar

Johann Schopplich johannschopplich

View GitHub Profile
@johannschopplich
johannschopplich / storage.ts
Last active June 27, 2024 15:27
IndexedDB storage wrapper for VueUse
import { useStorageAsync } from "@vueuse/core";
import { get, set, del } from "idb-keyval";
export const STORAGE_KEY_PREFIX = "app.session.";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function useIdbStorage<T = any>(key: string, initialValue: T) {
return useStorageAsync(`${STORAGE_KEY_PREFIX}${key}`, initialValue, {
async getItem(key: string) {
return (await get<string>(key)) ?? null;
@johannschopplich
johannschopplich / fetch.ts
Last active October 20, 2022 06:50
Fetch data with typed response from Zog schema
// Create a schema for a post
const Post = z.object({
slug: z.string(),
content: z.string(),
});
// Create a schema for a post collection
const Posts = z.array(Post);
// Fetch a post by slug with the correct typed response
@johannschopplich
johannschopplich / AppIcon.vue
Created February 24, 2023 13:41
Auto-import icons from `assets` in Nuxt
<template>
<span
v-if="icon"
:class="[
'children-[svg]:h-full children-[svg]:w-full',
defaultStyles && 'inline-block h-[1em] w-[1em] align-middle',
]"
v-html="icon"
/>
</template>
@johannschopplich
johannschopplich / better-scroller.client.ts
Created June 7, 2023 17:19
Nuxt plugin for `vue-router-better-scroller` with with Suspense route resolution
import { createRouterScroller } from 'vue-router-better-scroller'
interface ScrollPositionCoordinates {
behavior?: ScrollOptions['behavior']
left?: number
top?: number
}
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(
@johannschopplich
johannschopplich / storage.ts
Created October 30, 2023 11:05
Capacitor Preferences binding for VueUse `useStorageAsync`
import { Preferences } from "@capacitor/preferences";
import type {
MaybeRefOrGetter,
RemovableRef,
StorageLikeAsync,
UseStorageAsyncOptions,
} from "@vueuse/core";
const capacitorPreferenceStorage: StorageLikeAsync = {
async getItem(key: string): Promise<string | null> {
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Patrick Marsceill, software designer</title>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/favicon-32x32.png"
@johannschopplich
johannschopplich / blueprint.yaml
Created April 19, 2024 05:43 — forked from lukaskleinschmidt/blueprint.yaml
Kirby 4 query pages from a searchengine for the pages field
fields:
articles:
type: pages
query: kirby.collection('articles')
@johannschopplich
johannschopplich / proxy.ts
Created August 30, 2024 08:19
unenv `createMock`, but optimized
const fn = function () {}
function createMock(name: string, overrides: Record<any, any> = {}): any {
fn.prototype.name = name
const props: Record<any, any> = {}
return new Proxy(fn, {
get(_target, prop) {
if (prop === 'caller') {
return null
}
@johannschopplich
johannschopplich / cache_expiration.conf
Created November 23, 2024 21:20
Ploi.io nginx Configuration Extensions for Kirby CMS
# ----------------------------------------------------------------------
# | Cache expiration |
# ----------------------------------------------------------------------
# Serve resources with a far-future expiration date.
#
# (!) If you don't control versioning with filename-based cache busting, you
# should consider lowering the cache times to something like one week.
#
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
@johannschopplich
johannschopplich / README.md
Last active February 7, 2025 10:28
Bücherspur Flowchart

Bücherspur Flow

Kirby CMS & Stationen

Im Kirby CMS können Benutzer Touren und Stationen anlegen und bearbeiten. Jede Station enthält neben Textinhalten auch einen POI-Datensatz. Dieser POI-Datensatz ist für die Nutzer schreibgeschützt, da er von der externen Destination One-Datenbank importiert wird. Anhand eines POI-ID-Feldes wird eine Verbindung zwischen der Station und dem entsprechenden POI hergestellt. Über einen Button im Kirby Panel können Sie gezielt POI-Daten importieren. Wird der Button betätigt, erfolgt ein Aufruf des Workers, der die Datenaktualisierung durchführt.

Der Abruf von POI-Daten von Destination One erfolgt auf Abruf. Alle Daten vom Frontend werden immer von Kirby geladen.

Worker

Der serverlose Worker kümmert sich um sämtliche Logik rund um die POI-Daten. Er kommuniziert direkt mit der externen Destination One-Datenbank und stellt über zwei unterschiedliche Routen sicher, dass die Daten synchronisiert werden:

  • Die Route /destination-one/:id/poi holt gezielt die POI-Daten