This commit is contained in:
2026-03-05 15:28:55 +02:00
parent aad888ff2c
commit 1df8a3f452
13 changed files with 3059 additions and 10822 deletions

2830
bun.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,9 @@ const { openInPopup } = useUserSession();
<UCard class="max-w-sm grid gap-6 justify-center items-center">
<div class="flex flex-col gap-10 items-center justify-center">
<div class="flex gap-2 items-center">
<div class="font-bold text-xl tracking-tight font-fira-code">
<div
class="font-bold text-xl tracking-tight font-fira-code"
>
Ghostwriter
</div>
<NuxtImg src="/ghostwriter-logo.png" class="size-9" />
@@ -23,8 +25,8 @@ const { openInPopup } = useUserSession();
Sign in to your account.
</div>
<div class="text-center">
Connect with Strava to automatically add personalized titles and
descriptions to your activities.
Connect with Strava to automatically add personalized
titles and descriptions to your activities.
</div>
</div>
<div

View File

@@ -14,11 +14,6 @@ export default defineNuxtConfig({
hookdeckKey: "",
openaiApiKey: "",
databaseUrl: "",
public: {
posthogPublicKey: "",
posthogHost: "",
posthogDefaults: "2025-05-24",
},
},
future: { compatibilityVersion: 4 },
compatibilityDate: "2025-03-01",

View File

@@ -22,8 +22,6 @@
"nuxt": "^4.0.3",
"nuxt-auth-utils": "0.5.23",
"openai": "^5.12.2",
"posthog-js": "^1.259.0",
"posthog-node": "^5.6.0",
"radash": "^12.1.1",
"ts-pattern": "^5.8.0",
"url": "^0.11.4",

View File

@@ -54,14 +54,14 @@ const saveOp = watchPausable(
<div class="font-bold text-lg">Welcome to Ghostwriter!</div>
<div>
Let's generate fun and engaging titles and descriptions for your Strava
activities automatically, right when they are created. Customize your
preferences below.
Let's generate fun and engaging titles and descriptions for your
Strava activities automatically, right when they are created.
Customize your preferences below.
</div>
<div>
Add a touch of creativity to your Strava workouts. Simply enable it and
choose your language, and we'll do the rest!
Add a touch of creativity to your Strava workouts. Simply enable it
and choose your language, and we'll do the rest!
</div>
</UContainer>
@@ -69,12 +69,15 @@ const saveOp = watchPausable(
<div class="font-bold text-lg"> Support</div>
<UCard class="">
<div class="flex flex-col gap-8">
Ghostwriter 👻 is free to use, but it takes time and resources to keep
it running smoothly. If you enjoy it, consider supporting the app and
its creator - every bit helps!
Ghostwriter 👻 is free to use, but it takes time and resources
to keep it running smoothly. If you enjoy it, consider
supporting the app and its creator - every bit helps!
</div>
<template #footer>
<ULink href="https://buymeacoffee.com/mariosant" target="_blank">
<ULink
href="https://buymeacoffee.com/mariosant"
target="_blank"
>
<NuxtImg
src="images/bmac-orange-button.png"
height="32px"
@@ -190,11 +193,15 @@ const saveOp = watchPausable(
<CardField>
<template #title> Athlete ID </template>
<template #description>
Your Athlete ID. Click it to view your profile on Strava.</template
Your Athlete ID. Click it to view your profile on
Strava.</template
>
<template #value>
<ULink :href="stravaLink" class="underline flex items-center gap-2">
<ULink
:href="stravaLink"
class="underline flex items-center gap-2"
>
{{ user.id }}
<UIcon
name="heroicons:arrow-top-right-on-square"

View File

@@ -1,20 +0,0 @@
import posthog from "posthog-js";
export default defineNuxtPlugin(() => {
const runtimeConfig = useRuntimeConfig();
const posthogClient = posthog.init(runtimeConfig.public.posthogPublicKey, {
api_host: runtimeConfig.public.posthogHost,
//@ts-expect-error typing is more explicit than what it should
defaults: runtimeConfig.public.posthogDefaults,
loaded: (posthog) => {
if (import.meta.env.MODE === "development") posthog.debug();
},
});
return {
provide: {
posthog: () => posthogClient,
},
};
});

10491
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +0,0 @@
onlyBuiltDependencies:
- '@parcel/watcher'
- '@tailwindcss/oxide'
- core-js
- esbuild
- sharp
- vue-demi

View File

@@ -20,22 +20,9 @@ export default defineEventHandler(async (event) => {
},
});
posthog.identifyImmediate({
distinctId: String(user!.id),
properties: {
name: user!.name,
country: user!.country,
},
});
await db
.delete(tables.users)
.where(eq(tables.users.id, get(body, "object_id")));
posthog.captureImmediate({
distinctId: get(body, "object_id"),
event: "user deleted",
});
sendNoContent(event);
});

View File

@@ -1,29 +0,0 @@
import { PostHog } from "posthog-node";
import { waitUntil } from "@vercel/functions";
export default defineNitroPlugin((nitroApp) => {
const runtimeConfig = useRuntimeConfig();
const posthog = new PostHog(runtimeConfig.public.posthogPublicKey, {
host: runtimeConfig.public.posthogHost,
flushAt: 1,
flushInterval: 0,
});
nitroApp.hooks.hook("request", (event) => {
event.context.posthog = posthog;
});
nitroApp.hooks.hook("beforeResponse", () => {
waitUntil(posthog.shutdown());
});
nitroApp.hooks.hook("close", () => {
waitUntil(posthog.shutdown());
});
});
declare module "h3" {
interface H3EventContext {
posthog: PostHog;
}
}

View File

@@ -24,8 +24,6 @@ export default defineOAuthStravaEventHandler({
});
}
const posthog = event.context.posthog;
const userPayload = {
id: auth.user.id,
name: `${auth.user.firstname} ${auth.user.lastname}`,
@@ -82,19 +80,6 @@ export default defineOAuthStravaEventHandler({
user: userPayload,
});
posthog.identifyImmediate({
distinctId: String(user!.id),
properties: {
name: user!.name,
country: user!.country,
},
});
posthog.captureImmediate({
distinctId: String(user!.id),
event: "user logged in",
});
sendRedirect(event, "/");
},
});

View File

@@ -1,20 +0,0 @@
import { PostHog } from "posthog-node";
let client: PostHog;
export const usePosthog = () => {
const runtimeConfig = useRuntimeConfig();
client =
client ??
new PostHog(runtimeConfig.public.posthogPublicKey, {
host: runtimeConfig.public.posthogHost,
defaults: runtimeConfig.public.posthogDefaults,
});
if (process.dev) {
client.debug();
}
return client;
};