vybekiit 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +6457 -6312
- package/dist/global-skills/aws-serverless/SKILL.md +44 -44
- package/dist/global-skills/aws-serverless/assets/powertools-handler.py +2 -1
- package/dist/global-skills/aws-serverless/references/api-gateway.md +50 -470
- package/dist/global-skills/aws-serverless/references/architecture.md +47 -186
- package/dist/global-skills/aws-serverless/references/concurrency.md +44 -158
- package/dist/global-skills/aws-serverless/references/deployment.md +1 -1
- package/dist/global-skills/aws-serverless/references/event-sources.md +72 -391
- package/dist/global-skills/aws-serverless/references/lambda.md +69 -428
- package/dist/global-skills/aws-serverless/references/orchestration.md +65 -384
- package/dist/global-skills/aws-serverless/references/production.md +78 -415
- package/dist/global-skills/aws-serverless/references/troubleshooting.md +79 -626
- package/dist/global-skills/email-best-practices/.github/workflows/sync-skills.yml +30 -0
- package/dist/global-skills/email-best-practices/README.md +63 -0
- package/dist/global-skills/email-best-practices/references/accessibility.md +189 -0
- package/dist/global-skills/email-best-practices/references/compliance.md +125 -0
- package/dist/global-skills/email-best-practices/references/deliverability.md +121 -0
- package/dist/global-skills/email-best-practices/references/email-capture.md +129 -0
- package/dist/global-skills/email-best-practices/references/email-types.md +173 -0
- package/dist/global-skills/email-best-practices/references/list-management.md +157 -0
- package/dist/global-skills/email-best-practices/references/marketing-emails.md +115 -0
- package/dist/global-skills/email-best-practices/references/sending-reliability.md +155 -0
- package/dist/global-skills/email-best-practices/references/transactional-email-catalog.md +418 -0
- package/dist/global-skills/email-best-practices/references/transactional-emails.md +92 -0
- package/dist/global-skills/email-best-practices/references/webhooks-events.md +167 -0
- package/dist/global-skills/email-best-practices/tests/README.md +35 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/01-spam-deliverability.md +46 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/02-multi-region-compliance.md +48 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/03-retry-idempotency.md +36 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/04-webhook-bounce-handling.md +52 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/05-new-saas-email-plan.md +51 -0
- package/dist/global-skills/instrument-feature-flags/references/usage.md +35 -0
- package/dist/global-skills/instrument-product-analytics/SKILL.md +1 -1
- package/dist/global-skills/instrument-product-analytics/references/android.md +36 -0
- package/dist/global-skills/instrument-product-analytics/references/configuration.md +1 -0
- package/dist/global-skills/instrument-product-analytics/references/flutter.md +37 -0
- package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +3 -2
- package/dist/global-skills/instrument-product-analytics/references/usage.md +35 -0
- package/dist/global-skills/neon/SKILL.md +27 -20
- package/dist/global-skills/neon-ai-gateway/SKILL.md +68 -2
- package/dist/global-skills/neon-functions/SKILL.md +7 -7
- package/dist/global-skills/neon-object-storage/SKILL.md +2 -2
- package/dist/global-skills/neon-postgres/SKILL.md +5 -5
- package/dist/global-skills/neon-postgres/references/neon-sdk.md +262 -0
- package/dist/global-skills/neon-postgres-branches/SKILL.md +1 -1
- package/dist/global-skills/stripe-best-practices/SKILL.md +11 -6
- package/dist/global-skills/stripe-best-practices/references/billing.md +5 -0
- package/dist/global-skills/stripe-best-practices/references/payments.md +4 -2
- package/dist/global-skills/stripe-best-practices/references/tax.md +78 -8
- package/package.json +7 -7
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Scenario 1: Emails Going to Spam
|
|
2
|
+
|
|
3
|
+
## Prompt
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
You are an AI coding assistant. A developer asks you:
|
|
7
|
+
|
|
8
|
+
"My transactional emails (password resets, order confirmations) are going to spam in Gmail. What do I do to fix this?"
|
|
9
|
+
|
|
10
|
+
Answer with specific, actionable steps. Include exact DNS records, commands to verify, and threshold numbers where relevant.
|
|
11
|
+
|
|
12
|
+
Format your response as a numbered action plan.
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Expected Correctness Criteria
|
|
16
|
+
|
|
17
|
+
The agent MUST include these skill-specific details:
|
|
18
|
+
|
|
19
|
+
### Authentication (deliverability.md)
|
|
20
|
+
- [ ] SPF record example: `v=spf1 include:amazonses.com ~all`
|
|
21
|
+
- [ ] DKIM: provider supplies the record
|
|
22
|
+
- [ ] DMARC: `v=DMARC1; p=none; rua=mailto:dmarc@example.com`
|
|
23
|
+
- [ ] DMARC rollout: `p=none` → `p=quarantine; pct=25` → `p=reject`
|
|
24
|
+
- [ ] Verification commands: `dig TXT example.com +short`, `dig TXT resend._domainkey.example.com +short`, `dig TXT _dmarc.example.com +short`
|
|
25
|
+
|
|
26
|
+
### Thresholds (deliverability.md)
|
|
27
|
+
- [ ] Bounce targets: <1% good, 1-3% acceptable, 3-4% concerning, >4% critical
|
|
28
|
+
- [ ] Complaint targets: <0.01% excellent, 0.01-0.05% good, >0.05% critical
|
|
29
|
+
|
|
30
|
+
### IP Warming (deliverability.md)
|
|
31
|
+
- [ ] Week 1: 50-100/day
|
|
32
|
+
- [ ] Week 2: 200-500/day
|
|
33
|
+
- [ ] Week 3: 1,000-2,000/day
|
|
34
|
+
- [ ] Week 4: 5,000-10,000/day
|
|
35
|
+
|
|
36
|
+
### Infrastructure (deliverability.md)
|
|
37
|
+
- [ ] Dedicated subdomains: `t.example.com` (transactional), `m.example.com` (marketing)
|
|
38
|
+
- [ ] DNS TTL: 300s during setup, 3600s+ after stable
|
|
39
|
+
|
|
40
|
+
### Troubleshooting order (deliverability.md)
|
|
41
|
+
- [ ] Check in order: 1. Authentication, 2. List-Unsubscribe header, 3. Reputation, 4. Content, 5. Sending patterns
|
|
42
|
+
|
|
43
|
+
### Diagnostic tools (deliverability.md)
|
|
44
|
+
- [ ] Google Postmaster Tools
|
|
45
|
+
- [ ] mail-tester.com
|
|
46
|
+
- [ ] MXToolbox blacklist check
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Scenario 2: Multi-Region Email Compliance
|
|
2
|
+
|
|
3
|
+
## Prompt
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
You are an AI coding assistant. A developer asks you:
|
|
7
|
+
|
|
8
|
+
"I'm building an email newsletter for my SaaS product. I have users in the US, EU, and Canada. What legal requirements do I need to follow? Give me a comparison table of requirements by region and the specific implementation steps."
|
|
9
|
+
|
|
10
|
+
Be specific about penalty amounts, timing requirements for unsubscribe processing, and consent record requirements.
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Expected Correctness Criteria
|
|
14
|
+
|
|
15
|
+
### Penalties (compliance.md)
|
|
16
|
+
- [ ] CAN-SPAM: $53k/email
|
|
17
|
+
- [ ] GDPR: EUR 20M or 4% revenue
|
|
18
|
+
- [ ] CASL: $1M (individual) to $10M (organization) CAD
|
|
19
|
+
|
|
20
|
+
### Consent types (compliance.md)
|
|
21
|
+
- [ ] CAN-SPAM: opt-out model (can send without opt-in)
|
|
22
|
+
- [ ] GDPR: explicit opt-in (no pre-checked boxes)
|
|
23
|
+
- [ ] CASL express: explicit opt-in
|
|
24
|
+
- [ ] CASL implied: existing relationship (2 years) or inquiry (6 months)
|
|
25
|
+
|
|
26
|
+
### Unsubscribe timing (compliance.md)
|
|
27
|
+
- [ ] CAN-SPAM: 10 business days, must work 30 days after send
|
|
28
|
+
- [ ] GDPR: immediately, as easy as opting in
|
|
29
|
+
- [ ] CASL: 10 business days, must work 60 days after send
|
|
30
|
+
|
|
31
|
+
### CASL specifics (compliance.md)
|
|
32
|
+
- [ ] Sender identification valid 60 days after send
|
|
33
|
+
- [ ] Keep consent records 3 years after expiration
|
|
34
|
+
|
|
35
|
+
### Consent records (compliance.md)
|
|
36
|
+
- [ ] Record: email, date/time, method, what consented to, source
|
|
37
|
+
|
|
38
|
+
### International sending (compliance.md)
|
|
39
|
+
- [ ] Best practice: follow GDPR (most restrictive) for all regions
|
|
40
|
+
|
|
41
|
+
### Managing preferences vs unsubscribe (compliance.md)
|
|
42
|
+
- [ ] One-click unsubscribe required; preference management is nice-to-have, doesn't replace unsubscribe
|
|
43
|
+
|
|
44
|
+
### List-Unsubscribe header (compliance.md)
|
|
45
|
+
- [ ] Required by Gmail/Yahoo since Feb 2024
|
|
46
|
+
- [ ] Headers: `List-Unsubscribe` URL + `List-Unsubscribe-Post: List-Unsubscribe=One-Click`
|
|
47
|
+
- [ ] Endpoint: POST returns 200/202, GET shows unsubscribe page
|
|
48
|
+
- [ ] Stop sending within 48 hours
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Scenario 3: Retry Logic + Idempotency
|
|
2
|
+
|
|
3
|
+
## Prompt
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
You are an AI coding assistant. A developer asks you:
|
|
7
|
+
|
|
8
|
+
"I'm using the Resend API to send transactional emails. I need to implement retry logic with idempotency to prevent duplicate sends. Show me a TypeScript implementation with idempotency keys, exponential backoff, and proper error code handling."
|
|
9
|
+
|
|
10
|
+
Include specific HTTP error codes and which ones to retry vs not retry, idempotency key generation strategies, and backoff timing.
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Expected Correctness Criteria
|
|
14
|
+
|
|
15
|
+
### Idempotency keys (sending-reliability.md)
|
|
16
|
+
- [ ] Event-based key example: `order-confirm-${orderId}` (recommended)
|
|
17
|
+
- [ ] Request-scoped example: `reset-${userId}-${resetRequestId}`
|
|
18
|
+
- [ ] UUID fallback: `crypto.randomUUID()` — generate once, reuse on retry
|
|
19
|
+
- [ ] Warns against `Date.now()` or random values generated fresh on each attempt
|
|
20
|
+
- [ ] Key expiration: 24 hours — complete retry logic within this window
|
|
21
|
+
|
|
22
|
+
### Error codes (sending-reliability.md)
|
|
23
|
+
- [ ] Retry: 5xx (server error), 429 (rate limit), network timeout, DNS failure
|
|
24
|
+
- [ ] Do NOT retry: 400 (bad request), 401 (unauthorized), 403 (forbidden), 404 (not found), 422 (validation)
|
|
25
|
+
|
|
26
|
+
### Backoff (sending-reliability.md)
|
|
27
|
+
- [ ] Exponential: 1s -> 2s -> 4s -> 8s
|
|
28
|
+
- [ ] Cap at 30 seconds
|
|
29
|
+
- [ ] Jitter to prevent thundering herd
|
|
30
|
+
- [ ] Max retries: 3
|
|
31
|
+
|
|
32
|
+
### Timeout (sending-reliability.md)
|
|
33
|
+
- [ ] AbortController pattern with 10-30 second timeout
|
|
34
|
+
|
|
35
|
+
### Queuing (sending-reliability.md)
|
|
36
|
+
- [ ] Queue pattern for critical emails: write pending -> attempt send -> mark sent/schedule retry -> mark failed + alert
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Scenario 4: Webhook Bounce/Complaint Handling
|
|
2
|
+
|
|
3
|
+
## Prompt
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
You are an AI coding assistant. A developer asks you:
|
|
7
|
+
|
|
8
|
+
"I need to set up Resend webhooks to handle bounces and complaints. Show me how to implement this with signature verification using svix, idempotent event processing, and proper bounce/complaint handling (when to suppress, when to retry). Include TypeScript code."
|
|
9
|
+
|
|
10
|
+
Be specific about: svix verification headers, hard vs soft bounce handling thresholds, and complaint handling requirements.
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Expected Correctness Criteria
|
|
14
|
+
|
|
15
|
+
### Webhook setup (webhooks-events.md)
|
|
16
|
+
- [ ] Endpoint must return 2xx within 5 seconds
|
|
17
|
+
- [ ] Return 200 immediately, process asynchronously
|
|
18
|
+
|
|
19
|
+
### Svix verification (webhooks-events.md)
|
|
20
|
+
- [ ] Import from 'svix'
|
|
21
|
+
- [ ] Headers: `svix-id`, `svix-timestamp`, `svix-signature`
|
|
22
|
+
- [ ] Verify before processing, return 400 on invalid signature
|
|
23
|
+
|
|
24
|
+
### Idempotent processing (webhooks-events.md)
|
|
25
|
+
- [ ] Use event ID to deduplicate
|
|
26
|
+
- [ ] Check if already processed before handling
|
|
27
|
+
- [ ] Mark as processed after handling
|
|
28
|
+
|
|
29
|
+
### Event types (webhooks-events.md)
|
|
30
|
+
- [ ] `email.sent`, `email.delivered`, `email.bounced`, `email.complained`, `email.opened`, `email.clicked`
|
|
31
|
+
|
|
32
|
+
### Bounce handling (webhooks-events.md + list-management.md)
|
|
33
|
+
- [ ] Hard bounce: suppress immediately, remove from all lists
|
|
34
|
+
- [ ] Soft bounce: track count, suppress after 3 failures
|
|
35
|
+
- [ ] Suppression entry schema includes: email, reason, created_at, source_email_id
|
|
36
|
+
|
|
37
|
+
### Complaint handling (webhooks-events.md + list-management.md)
|
|
38
|
+
- [ ] Immediate suppression — no exceptions
|
|
39
|
+
- [ ] Remove from all lists
|
|
40
|
+
- [ ] Log for analysis
|
|
41
|
+
|
|
42
|
+
### Suppression unsuppress rules (list-management.md)
|
|
43
|
+
- [ ] Hard bounce: cannot unsuppress (address invalid)
|
|
44
|
+
- [ ] Complaint: cannot unsuppress (legal requirement)
|
|
45
|
+
- [ ] Soft bounce (3x): can unsuppress after 30-90 days
|
|
46
|
+
- [ ] Manual removal: only if user requests
|
|
47
|
+
|
|
48
|
+
### Pre-send check (list-management.md)
|
|
49
|
+
- [ ] Always check suppression before sending
|
|
50
|
+
|
|
51
|
+
### Retry behavior (webhooks-events.md)
|
|
52
|
+
- [ ] Non-2xx triggers retries: ~30s -> ~1min -> ~5min (continues ~24 hours)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Scenario 5: New SaaS Email Infrastructure Plan
|
|
2
|
+
|
|
3
|
+
## Prompt
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
You are an AI coding assistant. A developer asks you:
|
|
7
|
+
|
|
8
|
+
"I'm building a new SaaS app and need to plan my entire email infrastructure. I need to know: (1) what types of transactional emails I should plan for, (2) how to set up DNS authentication, (3) how to warm up my sending domain, (4) how to handle bounces/complaints in production, and (5) what compliance requirements I need for international users. Give me a comprehensive implementation roadmap."
|
|
9
|
+
|
|
10
|
+
Be specific about: IP warming schedules (daily volumes by week), bounce rate thresholds, complaint rate thresholds, DNS record formats, and legal requirements by region.
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Expected Correctness Criteria
|
|
14
|
+
|
|
15
|
+
### Email planning (transactional-email-catalog.md)
|
|
16
|
+
- [ ] References the transactional email catalog for SaaS planning
|
|
17
|
+
- [ ] Covers at minimum: verification, password reset, OTP/2FA, security alerts, billing
|
|
18
|
+
|
|
19
|
+
### DNS authentication (deliverability.md)
|
|
20
|
+
- [ ] SPF, DKIM, DMARC records with examples
|
|
21
|
+
- [ ] DMARC rollout strategy (none -> quarantine; pct=25 -> reject)
|
|
22
|
+
- [ ] Dedicated subdomains for transactional vs marketing
|
|
23
|
+
|
|
24
|
+
### Warming (deliverability.md)
|
|
25
|
+
- [ ] Correct weekly schedule: 50-100 / 200-500 / 1k-2k / 5k-10k
|
|
26
|
+
- [ ] Start with engaged users, send consistently
|
|
27
|
+
|
|
28
|
+
### Bounce/complaint handling (deliverability.md + list-management.md + webhooks-events.md)
|
|
29
|
+
- [ ] Bounce thresholds: <1% good, >4% critical
|
|
30
|
+
- [ ] Complaint thresholds: <0.01% excellent, >0.05% critical
|
|
31
|
+
- [ ] Hard bounce: immediate suppression
|
|
32
|
+
- [ ] Soft bounce: suppress after 3 failures
|
|
33
|
+
- [ ] Complaint: immediate suppression
|
|
34
|
+
- [ ] Pre-send suppression check
|
|
35
|
+
|
|
36
|
+
### Compliance (compliance.md)
|
|
37
|
+
- [ ] Covers CAN-SPAM, GDPR, CASL
|
|
38
|
+
- [ ] Correct penalty amounts
|
|
39
|
+
- [ ] Correct unsubscribe timing by region
|
|
40
|
+
- [ ] Recommends GDPR as global standard
|
|
41
|
+
|
|
42
|
+
### Data retention (list-management.md)
|
|
43
|
+
- [ ] Send attempts: 90 days
|
|
44
|
+
- [ ] Bounce/complaint events: 3 years
|
|
45
|
+
- [ ] Suppression list: indefinite
|
|
46
|
+
- [ ] Email content: 30 days
|
|
47
|
+
- [ ] Consent records: 3 years after expiry
|
|
48
|
+
|
|
49
|
+
### Cross-resource synthesis
|
|
50
|
+
- [ ] Agent references multiple resource files (not just one)
|
|
51
|
+
- [ ] "Start Here" routing from SKILL.md is followed
|
|
@@ -534,6 +534,41 @@ PostHogSDK.shared.captureFeatureView(flag: "flag-key", flagVariant: "variant-key
|
|
|
534
534
|
PostHogSDK.shared.captureFeatureInteraction(flag: "flag-key", flagVariant: "variant-key")
|
|
535
535
|
```
|
|
536
536
|
|
|
537
|
+
### Bootstrapping flags
|
|
538
|
+
|
|
539
|
+
Since there is a delay between initializing PostHog and fetching feature flags, feature flags are not always available immediately. This makes them unusable if you want to do something like redirecting a user to a different page based on a feature flag.
|
|
540
|
+
|
|
541
|
+
To have your feature flags available immediately, you can initialize PostHog with precomputed values until it has had a chance to fetch them. This is called bootstrapping. After the SDK fetches feature flags from PostHog, it will use those flag values instead of bootstrapped ones.
|
|
542
|
+
|
|
543
|
+
Set `config.bootstrap` before calling `setup()` to seed identity and flag values before the first `/flags` response (requires iOS SDK `3.66.0`+):
|
|
544
|
+
|
|
545
|
+
Swift
|
|
546
|
+
|
|
547
|
+
PostHog AI
|
|
548
|
+
|
|
549
|
+
```swift
|
|
550
|
+
let config = PostHogConfig(projectToken: "<ph_project_token>", host: "https://us.i.posthog.com")
|
|
551
|
+
config.bootstrap = PostHogBootstrapConfig(
|
|
552
|
+
distinctId: "distinct_id_of_your_user",
|
|
553
|
+
isIdentifiedId: true,
|
|
554
|
+
featureFlags: [
|
|
555
|
+
"flag-1": true,
|
|
556
|
+
"variant-flag": "control"
|
|
557
|
+
],
|
|
558
|
+
featureFlagPayloads: nil
|
|
559
|
+
)
|
|
560
|
+
PostHogSDK.shared.setup(config)
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
- **Bootstrapped identity applies to the first session.** Setting it before `setup()` means events captured synchronously during initialization (like `Application Installed`) carry your distinct ID instead of the SDK-generated UUID.
|
|
564
|
+
- An **anonymous** bootstrap (`isIdentifiedId: false`, the default) seeds the anonymous ID only when none is persisted yet. Once an anonymous ID exists on disk, or the user has been identified, it is ignored.
|
|
565
|
+
- An **identified** bootstrap (`isIdentifiedId: true`) is for a user you've already identified outside the SDK (for example, from a backend session token). On a fresh install it seeds the distinct ID and marks the user identified. On a returning install where an anonymous user already exists, it merges that user into the identified ID via `identify()`, which emits a `$identify` event during `setup()`. A *different*, already-identified user is left untouched. The identified ID never becomes the device ID.
|
|
566
|
+
- **Bootstrapped flags are served until the first `/flags` response, then replaced.** A complete `/flags` response takes over entirely, so bootstrapped-only keys don't persist past it. Only *enabled* flags are seeded: a `true` boolean or a non-empty variant string. A `false` or empty value is dropped, matching posthog-js. Seed payloads with the separate `featureFlagPayloads` option. Flag values and payloads must be JSON-serializable, or they're dropped. Bootstrapped flags are cleared on `reset()`.
|
|
567
|
+
|
|
568
|
+
The feature-flags-loaded signal fires as soon as bootstrapped flags are applied, so startup logic can read them immediately. These SDKs don't support the `sessionID` bootstrap option.
|
|
569
|
+
|
|
570
|
+
See the [bootstrapping guide](/docs/feature-flags/bootstrapping.md) for the cross-SDK overview.
|
|
571
|
+
|
|
537
572
|
## Experiments (A/B tests)
|
|
538
573
|
|
|
539
574
|
Since [experiments](/docs/experiments/start-here.md) use feature flags, the code for running an experiment is very similar to the feature flags code. See [adding experiment code](/docs/experiments/adding-experiment-code.md) for iOS examples.
|
|
@@ -65,7 +65,7 @@ STEP 9: Set up environment variables.
|
|
|
65
65
|
STEP 10: Verify and clean up.
|
|
66
66
|
- Check the project for errors. Look for type checking or build scripts in package.json.
|
|
67
67
|
- Ensure any components created were actually used.
|
|
68
|
-
- Run any linter or prettier-like scripts found in the package.json.
|
|
68
|
+
- Run any linter or prettier-like scripts found in the package.json, but ONLY on the files you have edited or created during this session. Never run formatting or linting across the entire project's codebase.
|
|
69
69
|
|
|
70
70
|
## Reference files
|
|
71
71
|
|
|
@@ -566,6 +566,41 @@ PostHog.captureFeatureView("flag-key", flagVariant = "variant-key")
|
|
|
566
566
|
PostHog.captureFeatureInteraction("flag-key", flagVariant = "variant-key")
|
|
567
567
|
```
|
|
568
568
|
|
|
569
|
+
### Bootstrapping flags
|
|
570
|
+
|
|
571
|
+
Since there is a delay between initializing PostHog and fetching feature flags, feature flags are not always available immediately. This makes them unusable if you want to do something like redirecting a user to a different page based on a feature flag.
|
|
572
|
+
|
|
573
|
+
To have your feature flags available immediately, you can initialize PostHog with precomputed values until it has had a chance to fetch them. This is called bootstrapping. After the SDK fetches feature flags from PostHog, it will use those flag values instead of bootstrapped ones.
|
|
574
|
+
|
|
575
|
+
Set `config.bootstrap` before calling `setup()` to seed identity and flag values before the first `/flags` response (requires Android SDK `3.55.0`+):
|
|
576
|
+
|
|
577
|
+
Kotlin
|
|
578
|
+
|
|
579
|
+
PostHog AI
|
|
580
|
+
|
|
581
|
+
```kotlin
|
|
582
|
+
import com.posthog.PostHogBootstrapConfig
|
|
583
|
+
val config = PostHogAndroidConfig(apiKey = POSTHOG_API_KEY, host = POSTHOG_HOST)
|
|
584
|
+
config.bootstrap = PostHogBootstrapConfig(
|
|
585
|
+
distinctId = "distinct_id_of_your_user",
|
|
586
|
+
isIdentifiedId = true,
|
|
587
|
+
featureFlags = mapOf(
|
|
588
|
+
"flag-1" to true,
|
|
589
|
+
"variant-flag" to "control"
|
|
590
|
+
)
|
|
591
|
+
)
|
|
592
|
+
PostHogAndroid.setup(this, config)
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
- **Bootstrapped identity applies to the first session.** Setting it before `setup()` means events captured synchronously during initialization (like `Application Installed`) carry your distinct ID instead of the SDK-generated UUID.
|
|
596
|
+
- An **anonymous** bootstrap (`isIdentifiedId: false`, the default) seeds the anonymous ID only when none is persisted yet. Once an anonymous ID exists on disk, or the user has been identified, it is ignored.
|
|
597
|
+
- An **identified** bootstrap (`isIdentifiedId: true`) is for a user you've already identified outside the SDK (for example, from a backend session token). On a fresh install it seeds the distinct ID and marks the user identified. On a returning install where an anonymous user already exists, it merges that user into the identified ID via `identify()`, which emits a `$identify` event during `setup()`. A *different*, already-identified user is left untouched. The identified ID never becomes the device ID.
|
|
598
|
+
- **Bootstrapped flags are served until the first `/flags` response, then replaced.** A complete `/flags` response takes over entirely, so bootstrapped-only keys don't persist past it. Only *enabled* flags are seeded: a `true` boolean or a non-empty variant string. A `false` or empty value is dropped, matching posthog-js. Seed payloads with the separate `featureFlagPayloads` option. Flag values and payloads must be JSON-serializable, or they're dropped. Bootstrapped flags are cleared on `reset()`.
|
|
599
|
+
|
|
600
|
+
The feature-flags-loaded signal fires as soon as bootstrapped flags are applied, so startup logic can read them immediately. These SDKs don't support the `sessionID` bootstrap option.
|
|
601
|
+
|
|
602
|
+
See the [bootstrapping guide](/docs/feature-flags/bootstrapping.md) for the cross-SDK overview.
|
|
603
|
+
|
|
569
604
|
## Experiments (A/B tests)
|
|
570
605
|
|
|
571
606
|
Since [experiments](/docs/experiments/start-here.md) use feature flags, the code for running an experiment is very similar to the feature flags code:
|
|
@@ -750,6 +785,7 @@ val config = PostHogAndroidConfig(
|
|
|
750
785
|
| errorTrackingConfig | PostHogErrorTrackingConfig() | Configures error tracking. autoCapture defaults to false; set it to true to autocapture uncaught exceptions when project settings also enable error tracking. |
|
|
751
786
|
| surveys | false | Internal/experimental native Android survey support. Native Android survey UI is not fully supported or documented yet. |
|
|
752
787
|
| surveysConfig | PostHogSurveysConfig() | Internal/experimental survey display delegate configuration, primarily for hybrid SDKs. |
|
|
788
|
+
| bootstrap | null | Seeds identity (distinctId, isIdentifiedId) and feature-flag state (featureFlags, featureFlagPayloads) before the first /flags response. Bootstrapped identity applies to the first session; only enabled flags are served, until the first /flags response replaces them. See [bootstrapping](/docs/feature-flags/bootstrapping.md#behavior-on-mobile-sdks). |
|
|
753
789
|
|
|
754
790
|
### Event filtering with `beforeSend`
|
|
755
791
|
|
|
@@ -289,6 +289,7 @@ The [`PostHogConfig` object](https://github.com/PostHog/posthog-ios/blob/main/Po
|
|
|
289
289
|
| reuseAnonymousIdType: BooleanDefault: false | Whether the SDK should reuse the anonymous Id between user changes. When enabled, a single Id will be used for all anonymous users on this device. |
|
|
290
290
|
| surveysType: BooleanDefault: true | Enable Surveys. |
|
|
291
291
|
| setBeforeSendType: FunctionDefault: undefined | Hook that allows for amending, sampling, or dropping events before they are sent to PostHog. |
|
|
292
|
+
| bootstrapType: PostHogBootstrapConfigDefault: nil | Seeds identity (distinctId, isIdentifiedId) and feature-flag state (featureFlags, featureFlagPayloads) before the first /flags response. Bootstrapped identity applies to the first session; only enabled flags are served, until the first /flags response replaces them. See [bootstrapping](/docs/feature-flags/bootstrapping.md#behavior-on-mobile-sdks). |
|
|
292
293
|
|
|
293
294
|
### Community questions
|
|
294
295
|
|
|
@@ -605,6 +605,43 @@ PostHog AI
|
|
|
605
605
|
await Posthog().reloadFeatureFlags();
|
|
606
606
|
```
|
|
607
607
|
|
|
608
|
+
### Bootstrapping flags
|
|
609
|
+
|
|
610
|
+
Since there is a delay between initializing PostHog and fetching feature flags, feature flags are not always available immediately. This makes them unusable if you want to do something like redirecting a user to a different page based on a feature flag.
|
|
611
|
+
|
|
612
|
+
To have your feature flags available immediately, you can initialize PostHog with precomputed values until it has had a chance to fetch them. This is called bootstrapping. After the SDK fetches feature flags from PostHog, it will use those flag values instead of bootstrapped ones.
|
|
613
|
+
|
|
614
|
+
Set `config.bootstrap` before calling `setup()` to seed identity and flag values before the first `/flags` response (requires the Flutter SDK `5.31.0`+):
|
|
615
|
+
|
|
616
|
+
Dart
|
|
617
|
+
|
|
618
|
+
PostHog AI
|
|
619
|
+
|
|
620
|
+
```dart
|
|
621
|
+
final config = PostHogConfig('<ph_project_token>');
|
|
622
|
+
config.host = 'https://us.i.posthog.com';
|
|
623
|
+
config.bootstrap = PostHogBootstrapConfig(
|
|
624
|
+
distinctId: 'distinct_id_of_your_user',
|
|
625
|
+
isIdentifiedId: true,
|
|
626
|
+
featureFlags: {
|
|
627
|
+
'flag-1': true,
|
|
628
|
+
'variant-flag': 'control',
|
|
629
|
+
},
|
|
630
|
+
);
|
|
631
|
+
await Posthog().setup(config);
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
The values are forwarded to the native iOS and Android SDKs:
|
|
635
|
+
|
|
636
|
+
- **Bootstrapped identity applies to the first session.** Setting it before `setup()` means events captured synchronously during initialization (like `Application Installed`) carry your distinct ID instead of the SDK-generated UUID.
|
|
637
|
+
- An **anonymous** bootstrap (`isIdentifiedId: false`, the default) seeds the anonymous ID only when none is persisted yet. Once an anonymous ID exists on disk, or the user has been identified, it is ignored.
|
|
638
|
+
- An **identified** bootstrap (`isIdentifiedId: true`) is for a user you've already identified outside the SDK (for example, from a backend session token). On a fresh install it seeds the distinct ID and marks the user identified. On a returning install where an anonymous user already exists, it merges that user into the identified ID via `identify()`, which emits a `$identify` event during `setup()`. A *different*, already-identified user is left untouched. The identified ID never becomes the device ID.
|
|
639
|
+
- **Bootstrapped flags are served until the first `/flags` response, then replaced.** A complete `/flags` response takes over entirely, so bootstrapped-only keys don't persist past it. Only *enabled* flags are seeded: a `true` boolean or a non-empty variant string. A `false` or empty value is dropped, matching posthog-js. Seed payloads with the separate `featureFlagPayloads` option. Flag values and payloads must be JSON-serializable, or they're dropped. Bootstrapped flags are cleared on `reset()`.
|
|
640
|
+
|
|
641
|
+
The feature-flags-loaded signal fires as soon as bootstrapped flags are applied, so startup logic can read them immediately. These SDKs don't support the `sessionID` bootstrap option.
|
|
642
|
+
|
|
643
|
+
On Flutter web, `bootstrap` is not applied, so configure it in your `posthog.init({...})` snippet instead. See the [bootstrapping guide](/docs/feature-flags/bootstrapping.md) for the cross-SDK overview.
|
|
644
|
+
|
|
608
645
|
### Setting properties for flag evaluation
|
|
609
646
|
|
|
610
647
|
If a flag targets person or group properties, you can send those properties inline with the next flag evaluation request instead of waiting for a `$set` event to be ingested. This avoids the race where a flag returns a stale value right after you set a property.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# PostHog Python SDK
|
|
2
2
|
|
|
3
|
-
**SDK Version:** 7.
|
|
3
|
+
**SDK Version:** 7.25.0
|
|
4
4
|
|
|
5
5
|
Integrate PostHog into any python application.
|
|
6
6
|
|
|
@@ -73,6 +73,7 @@ Initialize a new PostHog client instance.
|
|
|
73
73
|
- **`capture_compression`** (`CaptureCompression`) - Request-body compression for capture-v1 uploads (ignored in V0, which uses ``gzip``). ``CaptureCompression.GZIP`` or ``DEFLATE`` (or the strings ``"gzip"``/``"deflate"``). When omitted, the ``POSTHOG_CAPTURE_COMPRESSION`` env var is consulted, then the legacy ``gzip`` flag, then no compression.
|
|
74
74
|
- **`secret_key`** (`any`) - A Personal API Key or Project Secret API Key, used to authenticate local feature flag evaluation, remote config payloads, and decrypted flag payloads. Example:: posthog.Client(project_api_key, secret_key="phx_...")
|
|
75
75
|
- **`_dedicated_ai_endpoint`** (`bool`)
|
|
76
|
+
- **`metrics?`** (`dict`)
|
|
76
77
|
|
|
77
78
|
### Returns
|
|
78
79
|
|
|
@@ -259,7 +260,7 @@ posthog.capture('$pageview', distinct_id="distinct_id_of_the_user", properties={
|
|
|
259
260
|
|
|
260
261
|
**Release Tag:** public
|
|
261
262
|
|
|
262
|
-
Capture an exception for error tracking.
|
|
263
|
+
Capture an exception for error tracking. When OpenTelemetry is installed and a valid span is active, its trace and span IDs are added as ``$trace_id`` and ``$span_id`` event properties.
|
|
263
264
|
|
|
264
265
|
### Parameters
|
|
265
266
|
|
|
@@ -534,6 +534,41 @@ PostHogSDK.shared.captureFeatureView(flag: "flag-key", flagVariant: "variant-key
|
|
|
534
534
|
PostHogSDK.shared.captureFeatureInteraction(flag: "flag-key", flagVariant: "variant-key")
|
|
535
535
|
```
|
|
536
536
|
|
|
537
|
+
### Bootstrapping flags
|
|
538
|
+
|
|
539
|
+
Since there is a delay between initializing PostHog and fetching feature flags, feature flags are not always available immediately. This makes them unusable if you want to do something like redirecting a user to a different page based on a feature flag.
|
|
540
|
+
|
|
541
|
+
To have your feature flags available immediately, you can initialize PostHog with precomputed values until it has had a chance to fetch them. This is called bootstrapping. After the SDK fetches feature flags from PostHog, it will use those flag values instead of bootstrapped ones.
|
|
542
|
+
|
|
543
|
+
Set `config.bootstrap` before calling `setup()` to seed identity and flag values before the first `/flags` response (requires iOS SDK `3.66.0`+):
|
|
544
|
+
|
|
545
|
+
Swift
|
|
546
|
+
|
|
547
|
+
PostHog AI
|
|
548
|
+
|
|
549
|
+
```swift
|
|
550
|
+
let config = PostHogConfig(projectToken: "<ph_project_token>", host: "https://us.i.posthog.com")
|
|
551
|
+
config.bootstrap = PostHogBootstrapConfig(
|
|
552
|
+
distinctId: "distinct_id_of_your_user",
|
|
553
|
+
isIdentifiedId: true,
|
|
554
|
+
featureFlags: [
|
|
555
|
+
"flag-1": true,
|
|
556
|
+
"variant-flag": "control"
|
|
557
|
+
],
|
|
558
|
+
featureFlagPayloads: nil
|
|
559
|
+
)
|
|
560
|
+
PostHogSDK.shared.setup(config)
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
- **Bootstrapped identity applies to the first session.** Setting it before `setup()` means events captured synchronously during initialization (like `Application Installed`) carry your distinct ID instead of the SDK-generated UUID.
|
|
564
|
+
- An **anonymous** bootstrap (`isIdentifiedId: false`, the default) seeds the anonymous ID only when none is persisted yet. Once an anonymous ID exists on disk, or the user has been identified, it is ignored.
|
|
565
|
+
- An **identified** bootstrap (`isIdentifiedId: true`) is for a user you've already identified outside the SDK (for example, from a backend session token). On a fresh install it seeds the distinct ID and marks the user identified. On a returning install where an anonymous user already exists, it merges that user into the identified ID via `identify()`, which emits a `$identify` event during `setup()`. A *different*, already-identified user is left untouched. The identified ID never becomes the device ID.
|
|
566
|
+
- **Bootstrapped flags are served until the first `/flags` response, then replaced.** A complete `/flags` response takes over entirely, so bootstrapped-only keys don't persist past it. Only *enabled* flags are seeded: a `true` boolean or a non-empty variant string. A `false` or empty value is dropped, matching posthog-js. Seed payloads with the separate `featureFlagPayloads` option. Flag values and payloads must be JSON-serializable, or they're dropped. Bootstrapped flags are cleared on `reset()`.
|
|
567
|
+
|
|
568
|
+
The feature-flags-loaded signal fires as soon as bootstrapped flags are applied, so startup logic can read them immediately. These SDKs don't support the `sessionID` bootstrap option.
|
|
569
|
+
|
|
570
|
+
See the [bootstrapping guide](/docs/feature-flags/bootstrapping.md) for the cross-SDK overview.
|
|
571
|
+
|
|
537
572
|
## Experiments (A/B tests)
|
|
538
573
|
|
|
539
574
|
Since [experiments](/docs/experiments/start-here.md) use feature flags, the code for running an experiment is very similar to the feature flags code. See [adding experiment code](/docs/experiments/adding-experiment-code.md) for iOS examples.
|
|
@@ -2,17 +2,15 @@
|
|
|
2
2
|
name: neon
|
|
3
3
|
description: >-
|
|
4
4
|
Overview of the Neon platform for apps and agents, spanning Postgres, Auth,
|
|
5
|
-
Data API, and the new services: Object Storage, Compute Functions, and AI
|
|
6
|
-
Gateway. Use
|
|
7
|
-
|
|
8
|
-
"
|
|
9
|
-
"model routing", or "call an LLM" → AI Gateway; "database", "Postgres", or
|
|
10
|
-
"authentication" → Postgres and Auth.
|
|
5
|
+
the Data API, and the new services: Object Storage, Compute Functions, and AI
|
|
6
|
+
Gateway. Use when "Neon" is mentioned, or when any of its individual
|
|
7
|
+
capabilities are the trigger: "object storage" or "S3", "buckets", "serverless
|
|
8
|
+
functions", "AI gateway", "call an LLM", "postgres", "database", or "backend".
|
|
11
9
|
---
|
|
12
10
|
|
|
13
11
|
# Neon
|
|
14
12
|
|
|
15
|
-
Important: Neon is no longer just a Serverless Postgres provider. Neon is the backend for apps and agents with Serverless Postgres, Auth, Functions, Storage, and an AI Gateway: instant, branchable, serverless.
|
|
13
|
+
Important: Neon is no longer just a Serverless Postgres provider. Neon is the backend for apps and agents with Serverless Postgres, Auth, Functions, Object Storage, and an AI Gateway: instant, branchable, serverless.
|
|
16
14
|
|
|
17
15
|
Use this skill as the starting point for anything Neon: get an overview of its capabilities, find your way around the Neon agent skills and documentation, and follow best practices for getting started and for branch-first development workflows.
|
|
18
16
|
|
|
@@ -22,15 +20,15 @@ Neon bundles several backend primitives for building apps and agents that all br
|
|
|
22
20
|
|
|
23
21
|
- **Postgres** — Serverless Postgres that scales and branches with your app. _Generally available._
|
|
24
22
|
- **Auth** — Managed authentication with users and sessions stored in Postgres. _Generally available._
|
|
25
|
-
- **Object Storage** — S3-compatible object storage that branches with your projects.
|
|
26
|
-
- **
|
|
27
|
-
- **AI Gateway** — One API for all frontier and open-source models, with routing, logging, and cost controls, powered by Databricks.
|
|
23
|
+
- **Object Storage** — S3-compatible object storage that branches with your projects. _Public beta._
|
|
24
|
+
- **Functions** — Long-running serverless functions - Neon's compute offering - running close to your database — for WebSocket servers, long agent HTTP streams, APIs, and server-sent event servers. _Public beta._
|
|
25
|
+
- **AI Gateway** — One API for all frontier and open-source models, with routing, logging, and cost controls, powered by Databricks. _Public beta._
|
|
28
26
|
|
|
29
|
-
###
|
|
27
|
+
### Public Beta Service Availability
|
|
30
28
|
|
|
31
|
-
Object Storage,
|
|
29
|
+
Object Storage, Functions, and AI Gateway are in public beta.
|
|
32
30
|
|
|
33
|
-
|
|
31
|
+
Beta access features are only available on net-new projects created in the `us-east-2` region; they cannot be enabled on existing projects for now. Before guiding a user through any of these services, confirm they are working with a new project in `us-east-2`. If not, they will need to create a new project in that region.
|
|
34
32
|
|
|
35
33
|
## Architecture: how Neon fits
|
|
36
34
|
|
|
@@ -74,7 +72,7 @@ Common doc URLs are organized in the topic links below. If you need a page not l
|
|
|
74
72
|
- Choosing or creating the right branch type for dev, preview, test, or CI workflows → `neon-postgres-branches`.
|
|
75
73
|
- Storing and serving files (uploads, images, blobs) that branch with the database → `neon-object-storage`.
|
|
76
74
|
- Deploying long-running or streaming serverless functions — APIs, agents, SSE/WebSocket servers — next to the database → `neon-functions`.
|
|
77
|
-
- Calling an LLM or routing across model providers with one credential → `neon-ai-gateway`.
|
|
75
|
+
- Calling an LLM or routing across model providers with one credential — including discovering the branch's servable models at runtime via the OpenAI-compatible `/v1/models` endpoint → `neon-ai-gateway`.
|
|
78
76
|
- Provisioning instant, claimable temporary Postgres databases (for example, one per end user or demo) → `claimable-postgres`.
|
|
79
77
|
- Diagnosing or fixing excessive Postgres egress (network data-transfer) costs in a codebase → `neon-postgres-egress-optimizer`.
|
|
80
78
|
|
|
@@ -98,6 +96,8 @@ For example, to install the object storage skill globally for a specific agent w
|
|
|
98
96
|
npx skills add neondatabase/agent-skills -s neon-object-storage -g -y -a <agent-name>
|
|
99
97
|
```
|
|
100
98
|
|
|
99
|
+
You should also make sure the skills are up to date. You can run the same command or replace `add` with `update` to update all Neon skills.
|
|
100
|
+
|
|
101
101
|
## Getting Started with Neon
|
|
102
102
|
|
|
103
103
|
Use this section when guiding a user through first-time Neon setup, or when adding a new Neon service (Auth, object storage, functions, and so on) to a project that is already onboarded (for example, one already using Neon Postgres).
|
|
@@ -129,7 +129,7 @@ If `init` is not suitable, the individual steps can be run non-interactively, us
|
|
|
129
129
|
- **MCP server:** `npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a <agent-name>`
|
|
130
130
|
- **Agent skill:** `npx skills add neondatabase/agent-skills --skill neon-postgres --skill neon --agent <agent-name> -y`
|
|
131
131
|
|
|
132
|
-
Prefer the CLI over the MCP server unless the user instructs otherwise, since it provides more capabilities, including deploying Neon Functions. For full CLI installation options, see https://neon.com/docs/
|
|
132
|
+
Prefer the CLI over the MCP server unless the user instructs otherwise, since it provides more capabilities, including deploying Neon Functions. For full CLI installation options, see https://neon.com/docs/cli/install.md
|
|
133
133
|
|
|
134
134
|
### Setup Flow
|
|
135
135
|
|
|
@@ -178,7 +178,7 @@ If env vars are injected at runtime instead of written to disk — or you simply
|
|
|
178
178
|
- `neon-env run -- <your dev command>` (from `@neon/env`) fetches the branch's vars from your `neon.ts` and injects them into the child process at runtime — no `.env` file needed. This is the runtime counterpart to the on-disk `env pull`.
|
|
179
179
|
- `neon-env export` (from `@neon/env`) prints the branch's env to stdout as dotenv lines or, with `--format json`, JSON — for piping into another env manager rather than running a command. For example, [varlock](https://varlock.dev) can bulk-load it from a `.env.schema` with `@setValuesBulk(exec("neon-env export --format json"), format=json)`.
|
|
180
180
|
- `fetchEnv` from `@neon/env` is the programmatic version of the same thing: resolve the branch's env in code at runtime instead of shelling out to `neon-env run`.
|
|
181
|
-
- `neon dev` injects the same vars into your local dev server — it's part of Neon Functions local development (a
|
|
181
|
+
- `neon dev` injects the same vars into your local dev server — it's part of Neon Functions local development (a public beta feature).
|
|
182
182
|
|
|
183
183
|
When an agent should not write a local `.env`, instruct it (for example in your `AGENTS.md`) to run `neon checkout <branch> --no-env-pull` and rely on runtime injection.
|
|
184
184
|
|
|
@@ -212,9 +212,13 @@ export default defineConfig({
|
|
|
212
212
|
auth: true,
|
|
213
213
|
dataApi: true,
|
|
214
214
|
preview: {
|
|
215
|
-
functions: {
|
|
216
|
-
|
|
217
|
-
|
|
215
|
+
functions: {
|
|
216
|
+
/* ... */
|
|
217
|
+
}, // see the neon-functions skill
|
|
218
|
+
buckets: {
|
|
219
|
+
/* ... */
|
|
220
|
+
}, // see the neon-object-storage skill
|
|
221
|
+
aiGateway: true, // see the neon-ai-gateway skill
|
|
218
222
|
},
|
|
219
223
|
});
|
|
220
224
|
```
|
|
@@ -320,7 +324,10 @@ export default defineConfig({ auth: true, dataApi: true });
|
|
|
320
324
|
|
|
321
325
|
// 2. Or verify a third-party IdP instead of Neon Auth:
|
|
322
326
|
export default defineConfig({
|
|
323
|
-
dataApi: {
|
|
327
|
+
dataApi: {
|
|
328
|
+
authProvider: "external",
|
|
329
|
+
jwksUrl: "https://your-idp/.well-known/jwks.json",
|
|
330
|
+
},
|
|
324
331
|
});
|
|
325
332
|
```
|
|
326
333
|
|