Skip to content
Skip to content
Goodspeed

Build apps with PostHog

PostHog is the analytics layer in every Goodspeed app: consent-aware lazy init, a typed EVENTS catalog, feature flags, and A/B testing. Goodspeed generates PostHog as a standard part of every app, so the output is a working codebase from day one, not a scaffold you have to finish yourself.

WHAT GETS GENERATED

Built into every PostHog build

Every app Goodspeed generates with PostHog includes these production-ready patterns, wired together from the first build.

ItemDescriptionStrength
lib/posthog.ts consent-aware lazy initThe PostHog client is not created at module load time. getPostHog() initializes it on first call, but only if GDPR analytics consent has been granted.Privacy
hooks/useAnalytics.ts custom event hookA React hook that wraps captureEvent and captureScreen from lib/posthog.ts, making event tracking a one-liner in any component.Hook
lib/events.ts typed EVENTS catalogA string-literal-union EVENTS type exports every declared event name. TypeScript rejects any captureEvent call that uses an undeclared string.Type Safety
gasConfig.backend.posthog keysPostHog API key and host live in gas.config.ts under backend.posthog, read by lib/posthog.ts on first initialization.Configuration
Feature flags and A/B testingposthog.isFeatureEnabled and posthog.getFeatureFlag are called in hooks/useFeatureFlag.ts to gate features and split-test UI variants.Experimentation

Source: gas-template repository · Product Analytics

REAL GENERATED CODE

A snippet from a PostHog app the studio shipped

This pattern comes directly from the gas-template codebase, the foundation every Goodspeed app is generated on. The studio generates PostHog code like this for every app in the pipeline, not just a hello-world scaffold.

  1. Consent-aware init

    // lib/posthog.ts: lazy, consent-aware PostHog singleton
    let _posthog: PostHog | null = null;
    
    export async function getPostHog(): Promise<PostHog | null> {
      if (_posthog) return _posthog;
      const granted = await checkAnalyticsConsent();
      if (!granted) return null;
      if (!apiKey) return null;
      _posthog = new PostHog(apiKey, {
        host,
        persistence: 'memory',
        bootstrap: { distinctId: await getAnonymousId() },
      });
      return _posthog;
    }
GDaily Allergens

Today's log

Gluten
Tree nuts
Shellfish
Dairy
HomeScanLogProfile

START WITH POSTHOG

Your PostHog app, generated