[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-encore-encore-go-webhook":3,"mdc-9nvh3v-key":40,"related-org-encore-encore-go-webhook":1018,"related-repo-encore-encore-go-webhook":1190},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":27,"repoUrl":28,"updatedAt":29,"license":30,"forks":31,"topics":32,"repo":35,"sourceUrl":38,"mdContent":39},"encore-go-webhook","receive webhooks in Encore Go","Receive inbound webhooks from external services (Stripe, GitHub, Slack, Twilio, etc.) in Encore Go using `\u002F\u002Fencore:api raw`. The right skill any time the user names a third-party provider that POSTs events to a URL you own.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"encore","Encore","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fencore.png","encoredev",[13,17,20,21,24],{"name":14,"slug":15,"type":16},"Backend","backend","tag",{"name":18,"slug":19,"type":16},"Integrations","integrations",{"name":9,"slug":8,"type":16},{"name":22,"slug":23,"type":16},"Webhooks","webhooks",{"name":25,"slug":26,"type":16},"Go","go",26,"https:\u002F\u002Fgithub.com\u002Fencoredev\u002Fskills","2026-05-16T05:59:55.464934",null,5,[33,34],"claude-code","skills",{"repoUrl":28,"stars":27,"forks":31,"topics":36,"description":37},[33,34],"Agent Skills for development with Encore.","https:\u002F\u002Fgithub.com\u002Fencoredev\u002Fskills\u002Ftree\u002FHEAD\u002Fencore\u002Fgo-webhook","---\nname: encore-go-webhook\ndescription: Receive inbound webhooks from external services (Stripe, GitHub, Slack, Twilio, etc.) in Encore Go using `\u002F\u002Fencore:api raw`. The right skill any time the user names a third-party provider that POSTs events to a URL you own.\nwhen_to_use: >-\n  User mentions a webhook, a \u002Fwebhooks\u002F* path, raw HTTP, `\u002F\u002Fencore:api raw`, accepting external callbacks, verifying webhook signatures (Stripe-Signature, X-Hub-Signature-256), reading the raw request body, parsing form-encoded payloads, or any time the user names a third-party provider that posts events — Stripe, GitHub, GitLab, Bitbucket, Shopify, Twilio, SendGrid, Mailgun, Auth0, Clerk, Slack, Discord, PayPal, Square. Use `encore-go-api` instead for typed JSON endpoints in your own service. Trigger phrases: \"Stripe webhook\", \"GitHub webhook\", \"\u002Fwebhooks\u002Fstripe\", \"raw HTTP endpoint\", \"raw endpoint\", \"verify the signature\", \"inbound webhook\", \"external callback\".\n---\n\n# Encore Go Webhook Endpoints\n\n## Instructions\n\nUse `\u002F\u002Fencore:api raw` to receive inbound webhooks from third-party services. Raw endpoints give you direct access to `http.ResponseWriter` and `*http.Request`, which you need for signature verification (the verification typically requires the unparsed raw body).\n\n### 1. Define the endpoint with `\u002F\u002Fencore:api raw`\n\n```go\npackage webhooks\n\nimport (\n    \"io\"\n    \"net\u002Fhttp\"\n)\n\n\u002F\u002Fencore:api public raw path=\u002Fwebhooks\u002Fstripe method=POST\nfunc StripeWebhook(w http.ResponseWriter, req *http.Request) {\n    sig := req.Header.Get(\"Stripe-Signature\")\n\n    \u002F\u002F Read the raw body — needed for signature verification.\n    body, err := io.ReadAll(req.Body)\n    if err != nil {\n        http.Error(w, \"could not read body\", http.StatusBadRequest)\n        return\n    }\n\n    \u002F\u002F Verify signature, parse event, handle, then respond...\n\n    w.Header().Set(\"Content-Type\", \"application\u002Fjson\")\n    w.WriteHeader(http.StatusOK)\n    w.Write([]byte(`{\"received\":true}`))\n}\n```\n\n### 2. Verify the signature\n\nMost providers sign webhooks. Read the secret with `secrets` (see the `encore-go-secret` skill) and verify before trusting the payload.\n\n```go\npackage webhooks\n\nimport (\n    \"github.com\u002Fstripe\u002Fstripe-go\u002Fv76\u002Fwebhook\"\n)\n\nvar secrets struct {\n    StripeWebhookSecret string\n}\n\n\u002F\u002Fencore:api public raw path=\u002Fwebhooks\u002Fstripe method=POST\nfunc StripeWebhook(w http.ResponseWriter, req *http.Request) {\n    body, _ := io.ReadAll(req.Body)\n    sig := req.Header.Get(\"Stripe-Signature\")\n\n    event, err := webhook.ConstructEvent(body, sig, secrets.StripeWebhookSecret)\n    if err != nil {\n        http.Error(w, \"signature verification failed\", http.StatusBadRequest)\n        return\n    }\n\n    \u002F\u002F event is now trusted — handle it.\n    _ = event\n    w.WriteHeader(http.StatusOK)\n}\n```\n\nFor GitHub, verify the HMAC-SHA256 in the `X-Hub-Signature-256` header against the raw body using your webhook secret.\n\n## Common providers\n\n| Provider | Signature header | Verification |\n|---|---|---|\n| Stripe | `Stripe-Signature` | `stripe.webhook.ConstructEvent(rawBody, sig, secret)` |\n| GitHub | `X-Hub-Signature-256` | HMAC-SHA256 over the raw body |\n| Slack | `X-Slack-Signature` | HMAC-SHA256 over `v0:{timestamp}:{rawBody}` |\n| Shopify | `X-Shopify-Hmac-Sha256` | HMAC-SHA256 (base64) over the raw body |\n| Twilio | `X-Twilio-Signature` | HMAC-SHA1 over URL + sorted form fields |\n\n## Always respond quickly\n\nWebhook senders retry on non-2xx or slow responses. Acknowledge with a 2xx as soon as the payload is verified, then enqueue the actual work via Pub\u002FSub (see `encore-go-pubsub`) instead of doing it in the request handler.\n\n```go\npackage webhooks\n\nimport (\n    \"encore.dev\u002Fpubsub\"\n    \"net\u002Fhttp\"\n)\n\ntype StripeEvent struct {\n    ID   string `json:\"id\"`\n    Type string `json:\"type\"`\n    Data any    `json:\"data\"`\n}\n\nvar StripeEvents = pubsub.NewTopic[*StripeEvent](\"stripe-events\", pubsub.TopicConfig{\n    DeliveryGuarantee: pubsub.AtLeastOnce,\n})\n\n\u002F\u002Fencore:api public raw path=\u002Fwebhooks\u002Fstripe method=POST\nfunc StripeWebhook(w http.ResponseWriter, req *http.Request) {\n    \u002F\u002F ... verify signature, parse event ...\n\n    _, _ = StripeEvents.Publish(req.Context(), &StripeEvent{\n        ID: event.ID, Type: string(event.Type), Data: event.Data,\n    })\n    w.WriteHeader(http.StatusOK)\n}\n```\n\n## Guidelines\n\n- Use `\u002F\u002Fencore:api raw` *only* for webhooks and other low-level HTTP integrations.\n- Always verify the provider's signature before trusting the payload.\n- Always respond 2xx fast — push slow work onto Pub\u002FSub.\n- Store the signing secret in `secrets struct{...}`; never inline it.\n- For typed JSON endpoints in your own service, use plain `\u002F\u002Fencore:api` from the `encore-go-api` skill.\n",{"data":41,"body":43},{"name":4,"description":6,"when_to_use":42},"User mentions a webhook, a \u002Fwebhooks\u002F* path, raw HTTP, `\u002F\u002Fencore:api raw`, accepting external callbacks, verifying webhook signatures (Stripe-Signature, X-Hub-Signature-256), reading the raw request body, parsing form-encoded payloads, or any time the user names a third-party provider that posts events — Stripe, GitHub, GitLab, Bitbucket, Shopify, Twilio, SendGrid, Mailgun, Auth0, Clerk, Slack, Discord, PayPal, Square. Use `encore-go-api` instead for typed JSON endpoints in your own service. Trigger phrases: \"Stripe webhook\", \"GitHub webhook\", \"\u002Fwebhooks\u002Fstripe\", \"raw HTTP endpoint\", \"raw endpoint\", \"verify the signature\", \"inbound webhook\", \"external callback\".",{"type":44,"children":45},"root",[46,55,62,93,105,329,335,356,547,560,566,718,724,737,938,944,1012],{"type":47,"tag":48,"props":49,"children":51},"element","h1",{"id":50},"encore-go-webhook-endpoints",[52],{"type":53,"value":54},"text","Encore Go Webhook Endpoints",{"type":47,"tag":56,"props":57,"children":59},"h2",{"id":58},"instructions",[60],{"type":53,"value":61},"Instructions",{"type":47,"tag":63,"props":64,"children":65},"p",{},[66,68,75,77,83,85,91],{"type":53,"value":67},"Use ",{"type":47,"tag":69,"props":70,"children":72},"code",{"className":71},[],[73],{"type":53,"value":74},"\u002F\u002Fencore:api raw",{"type":53,"value":76}," to receive inbound webhooks from third-party services. Raw endpoints give you direct access to ",{"type":47,"tag":69,"props":78,"children":80},{"className":79},[],[81],{"type":53,"value":82},"http.ResponseWriter",{"type":53,"value":84}," and ",{"type":47,"tag":69,"props":86,"children":88},{"className":87},[],[89],{"type":53,"value":90},"*http.Request",{"type":53,"value":92},", which you need for signature verification (the verification typically requires the unparsed raw body).",{"type":47,"tag":94,"props":95,"children":97},"h3",{"id":96},"_1-define-the-endpoint-with-encoreapi-raw",[98,100],{"type":53,"value":99},"1. Define the endpoint with ",{"type":47,"tag":69,"props":101,"children":103},{"className":102},[],[104],{"type":53,"value":74},{"type":47,"tag":106,"props":107,"children":111},"pre",{"className":108,"code":109,"language":26,"meta":110,"style":110},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","package webhooks\n\nimport (\n    \"io\"\n    \"net\u002Fhttp\"\n)\n\n\u002F\u002Fencore:api public raw path=\u002Fwebhooks\u002Fstripe method=POST\nfunc StripeWebhook(w http.ResponseWriter, req *http.Request) {\n    sig := req.Header.Get(\"Stripe-Signature\")\n\n    \u002F\u002F Read the raw body — needed for signature verification.\n    body, err := io.ReadAll(req.Body)\n    if err != nil {\n        http.Error(w, \"could not read body\", http.StatusBadRequest)\n        return\n    }\n\n    \u002F\u002F Verify signature, parse event, handle, then respond...\n\n    w.Header().Set(\"Content-Type\", \"application\u002Fjson\")\n    w.WriteHeader(http.StatusOK)\n    w.Write([]byte(`{\"received\":true}`))\n}\n","",[112],{"type":47,"tag":69,"props":113,"children":114},{"__ignoreMap":110},[115,126,136,145,154,162,171,179,188,197,206,214,223,232,241,250,259,268,276,285,293,302,311,320],{"type":47,"tag":116,"props":117,"children":120},"span",{"class":118,"line":119},"line",1,[121],{"type":47,"tag":116,"props":122,"children":123},{},[124],{"type":53,"value":125},"package webhooks\n",{"type":47,"tag":116,"props":127,"children":129},{"class":118,"line":128},2,[130],{"type":47,"tag":116,"props":131,"children":133},{"emptyLinePlaceholder":132},true,[134],{"type":53,"value":135},"\n",{"type":47,"tag":116,"props":137,"children":139},{"class":118,"line":138},3,[140],{"type":47,"tag":116,"props":141,"children":142},{},[143],{"type":53,"value":144},"import (\n",{"type":47,"tag":116,"props":146,"children":148},{"class":118,"line":147},4,[149],{"type":47,"tag":116,"props":150,"children":151},{},[152],{"type":53,"value":153},"    \"io\"\n",{"type":47,"tag":116,"props":155,"children":156},{"class":118,"line":31},[157],{"type":47,"tag":116,"props":158,"children":159},{},[160],{"type":53,"value":161},"    \"net\u002Fhttp\"\n",{"type":47,"tag":116,"props":163,"children":165},{"class":118,"line":164},6,[166],{"type":47,"tag":116,"props":167,"children":168},{},[169],{"type":53,"value":170},")\n",{"type":47,"tag":116,"props":172,"children":174},{"class":118,"line":173},7,[175],{"type":47,"tag":116,"props":176,"children":177},{"emptyLinePlaceholder":132},[178],{"type":53,"value":135},{"type":47,"tag":116,"props":180,"children":182},{"class":118,"line":181},8,[183],{"type":47,"tag":116,"props":184,"children":185},{},[186],{"type":53,"value":187},"\u002F\u002Fencore:api public raw path=\u002Fwebhooks\u002Fstripe method=POST\n",{"type":47,"tag":116,"props":189,"children":191},{"class":118,"line":190},9,[192],{"type":47,"tag":116,"props":193,"children":194},{},[195],{"type":53,"value":196},"func StripeWebhook(w http.ResponseWriter, req *http.Request) {\n",{"type":47,"tag":116,"props":198,"children":200},{"class":118,"line":199},10,[201],{"type":47,"tag":116,"props":202,"children":203},{},[204],{"type":53,"value":205},"    sig := req.Header.Get(\"Stripe-Signature\")\n",{"type":47,"tag":116,"props":207,"children":209},{"class":118,"line":208},11,[210],{"type":47,"tag":116,"props":211,"children":212},{"emptyLinePlaceholder":132},[213],{"type":53,"value":135},{"type":47,"tag":116,"props":215,"children":217},{"class":118,"line":216},12,[218],{"type":47,"tag":116,"props":219,"children":220},{},[221],{"type":53,"value":222},"    \u002F\u002F Read the raw body — needed for signature verification.\n",{"type":47,"tag":116,"props":224,"children":226},{"class":118,"line":225},13,[227],{"type":47,"tag":116,"props":228,"children":229},{},[230],{"type":53,"value":231},"    body, err := io.ReadAll(req.Body)\n",{"type":47,"tag":116,"props":233,"children":235},{"class":118,"line":234},14,[236],{"type":47,"tag":116,"props":237,"children":238},{},[239],{"type":53,"value":240},"    if err != nil {\n",{"type":47,"tag":116,"props":242,"children":244},{"class":118,"line":243},15,[245],{"type":47,"tag":116,"props":246,"children":247},{},[248],{"type":53,"value":249},"        http.Error(w, \"could not read body\", http.StatusBadRequest)\n",{"type":47,"tag":116,"props":251,"children":253},{"class":118,"line":252},16,[254],{"type":47,"tag":116,"props":255,"children":256},{},[257],{"type":53,"value":258},"        return\n",{"type":47,"tag":116,"props":260,"children":262},{"class":118,"line":261},17,[263],{"type":47,"tag":116,"props":264,"children":265},{},[266],{"type":53,"value":267},"    }\n",{"type":47,"tag":116,"props":269,"children":271},{"class":118,"line":270},18,[272],{"type":47,"tag":116,"props":273,"children":274},{"emptyLinePlaceholder":132},[275],{"type":53,"value":135},{"type":47,"tag":116,"props":277,"children":279},{"class":118,"line":278},19,[280],{"type":47,"tag":116,"props":281,"children":282},{},[283],{"type":53,"value":284},"    \u002F\u002F Verify signature, parse event, handle, then respond...\n",{"type":47,"tag":116,"props":286,"children":288},{"class":118,"line":287},20,[289],{"type":47,"tag":116,"props":290,"children":291},{"emptyLinePlaceholder":132},[292],{"type":53,"value":135},{"type":47,"tag":116,"props":294,"children":296},{"class":118,"line":295},21,[297],{"type":47,"tag":116,"props":298,"children":299},{},[300],{"type":53,"value":301},"    w.Header().Set(\"Content-Type\", \"application\u002Fjson\")\n",{"type":47,"tag":116,"props":303,"children":305},{"class":118,"line":304},22,[306],{"type":47,"tag":116,"props":307,"children":308},{},[309],{"type":53,"value":310},"    w.WriteHeader(http.StatusOK)\n",{"type":47,"tag":116,"props":312,"children":314},{"class":118,"line":313},23,[315],{"type":47,"tag":116,"props":316,"children":317},{},[318],{"type":53,"value":319},"    w.Write([]byte(`{\"received\":true}`))\n",{"type":47,"tag":116,"props":321,"children":323},{"class":118,"line":322},24,[324],{"type":47,"tag":116,"props":325,"children":326},{},[327],{"type":53,"value":328},"}\n",{"type":47,"tag":94,"props":330,"children":332},{"id":331},"_2-verify-the-signature",[333],{"type":53,"value":334},"2. Verify the signature",{"type":47,"tag":63,"props":336,"children":337},{},[338,340,346,348,354],{"type":53,"value":339},"Most providers sign webhooks. Read the secret with ",{"type":47,"tag":69,"props":341,"children":343},{"className":342},[],[344],{"type":53,"value":345},"secrets",{"type":53,"value":347}," (see the ",{"type":47,"tag":69,"props":349,"children":351},{"className":350},[],[352],{"type":53,"value":353},"encore-go-secret",{"type":53,"value":355}," skill) and verify before trusting the payload.",{"type":47,"tag":106,"props":357,"children":359},{"className":108,"code":358,"language":26,"meta":110,"style":110},"package webhooks\n\nimport (\n    \"github.com\u002Fstripe\u002Fstripe-go\u002Fv76\u002Fwebhook\"\n)\n\nvar secrets struct {\n    StripeWebhookSecret string\n}\n\n\u002F\u002Fencore:api public raw path=\u002Fwebhooks\u002Fstripe method=POST\nfunc StripeWebhook(w http.ResponseWriter, req *http.Request) {\n    body, _ := io.ReadAll(req.Body)\n    sig := req.Header.Get(\"Stripe-Signature\")\n\n    event, err := webhook.ConstructEvent(body, sig, secrets.StripeWebhookSecret)\n    if err != nil {\n        http.Error(w, \"signature verification failed\", http.StatusBadRequest)\n        return\n    }\n\n    \u002F\u002F event is now trusted — handle it.\n    _ = event\n    w.WriteHeader(http.StatusOK)\n}\n",[360],{"type":47,"tag":69,"props":361,"children":362},{"__ignoreMap":110},[363,370,377,384,392,399,406,414,422,429,436,443,450,458,465,472,480,487,495,502,509,516,524,532,539],{"type":47,"tag":116,"props":364,"children":365},{"class":118,"line":119},[366],{"type":47,"tag":116,"props":367,"children":368},{},[369],{"type":53,"value":125},{"type":47,"tag":116,"props":371,"children":372},{"class":118,"line":128},[373],{"type":47,"tag":116,"props":374,"children":375},{"emptyLinePlaceholder":132},[376],{"type":53,"value":135},{"type":47,"tag":116,"props":378,"children":379},{"class":118,"line":138},[380],{"type":47,"tag":116,"props":381,"children":382},{},[383],{"type":53,"value":144},{"type":47,"tag":116,"props":385,"children":386},{"class":118,"line":147},[387],{"type":47,"tag":116,"props":388,"children":389},{},[390],{"type":53,"value":391},"    \"github.com\u002Fstripe\u002Fstripe-go\u002Fv76\u002Fwebhook\"\n",{"type":47,"tag":116,"props":393,"children":394},{"class":118,"line":31},[395],{"type":47,"tag":116,"props":396,"children":397},{},[398],{"type":53,"value":170},{"type":47,"tag":116,"props":400,"children":401},{"class":118,"line":164},[402],{"type":47,"tag":116,"props":403,"children":404},{"emptyLinePlaceholder":132},[405],{"type":53,"value":135},{"type":47,"tag":116,"props":407,"children":408},{"class":118,"line":173},[409],{"type":47,"tag":116,"props":410,"children":411},{},[412],{"type":53,"value":413},"var secrets struct {\n",{"type":47,"tag":116,"props":415,"children":416},{"class":118,"line":181},[417],{"type":47,"tag":116,"props":418,"children":419},{},[420],{"type":53,"value":421},"    StripeWebhookSecret string\n",{"type":47,"tag":116,"props":423,"children":424},{"class":118,"line":190},[425],{"type":47,"tag":116,"props":426,"children":427},{},[428],{"type":53,"value":328},{"type":47,"tag":116,"props":430,"children":431},{"class":118,"line":199},[432],{"type":47,"tag":116,"props":433,"children":434},{"emptyLinePlaceholder":132},[435],{"type":53,"value":135},{"type":47,"tag":116,"props":437,"children":438},{"class":118,"line":208},[439],{"type":47,"tag":116,"props":440,"children":441},{},[442],{"type":53,"value":187},{"type":47,"tag":116,"props":444,"children":445},{"class":118,"line":216},[446],{"type":47,"tag":116,"props":447,"children":448},{},[449],{"type":53,"value":196},{"type":47,"tag":116,"props":451,"children":452},{"class":118,"line":225},[453],{"type":47,"tag":116,"props":454,"children":455},{},[456],{"type":53,"value":457},"    body, _ := io.ReadAll(req.Body)\n",{"type":47,"tag":116,"props":459,"children":460},{"class":118,"line":234},[461],{"type":47,"tag":116,"props":462,"children":463},{},[464],{"type":53,"value":205},{"type":47,"tag":116,"props":466,"children":467},{"class":118,"line":243},[468],{"type":47,"tag":116,"props":469,"children":470},{"emptyLinePlaceholder":132},[471],{"type":53,"value":135},{"type":47,"tag":116,"props":473,"children":474},{"class":118,"line":252},[475],{"type":47,"tag":116,"props":476,"children":477},{},[478],{"type":53,"value":479},"    event, err := webhook.ConstructEvent(body, sig, secrets.StripeWebhookSecret)\n",{"type":47,"tag":116,"props":481,"children":482},{"class":118,"line":261},[483],{"type":47,"tag":116,"props":484,"children":485},{},[486],{"type":53,"value":240},{"type":47,"tag":116,"props":488,"children":489},{"class":118,"line":270},[490],{"type":47,"tag":116,"props":491,"children":492},{},[493],{"type":53,"value":494},"        http.Error(w, \"signature verification failed\", http.StatusBadRequest)\n",{"type":47,"tag":116,"props":496,"children":497},{"class":118,"line":278},[498],{"type":47,"tag":116,"props":499,"children":500},{},[501],{"type":53,"value":258},{"type":47,"tag":116,"props":503,"children":504},{"class":118,"line":287},[505],{"type":47,"tag":116,"props":506,"children":507},{},[508],{"type":53,"value":267},{"type":47,"tag":116,"props":510,"children":511},{"class":118,"line":295},[512],{"type":47,"tag":116,"props":513,"children":514},{"emptyLinePlaceholder":132},[515],{"type":53,"value":135},{"type":47,"tag":116,"props":517,"children":518},{"class":118,"line":304},[519],{"type":47,"tag":116,"props":520,"children":521},{},[522],{"type":53,"value":523},"    \u002F\u002F event is now trusted — handle it.\n",{"type":47,"tag":116,"props":525,"children":526},{"class":118,"line":313},[527],{"type":47,"tag":116,"props":528,"children":529},{},[530],{"type":53,"value":531},"    _ = event\n",{"type":47,"tag":116,"props":533,"children":534},{"class":118,"line":322},[535],{"type":47,"tag":116,"props":536,"children":537},{},[538],{"type":53,"value":310},{"type":47,"tag":116,"props":540,"children":542},{"class":118,"line":541},25,[543],{"type":47,"tag":116,"props":544,"children":545},{},[546],{"type":53,"value":328},{"type":47,"tag":63,"props":548,"children":549},{},[550,552,558],{"type":53,"value":551},"For GitHub, verify the HMAC-SHA256 in the ",{"type":47,"tag":69,"props":553,"children":555},{"className":554},[],[556],{"type":53,"value":557},"X-Hub-Signature-256",{"type":53,"value":559}," header against the raw body using your webhook secret.",{"type":47,"tag":56,"props":561,"children":563},{"id":562},"common-providers",[564],{"type":53,"value":565},"Common providers",{"type":47,"tag":567,"props":568,"children":569},"table",{},[570,594],{"type":47,"tag":571,"props":572,"children":573},"thead",{},[574],{"type":47,"tag":575,"props":576,"children":577},"tr",{},[578,584,589],{"type":47,"tag":579,"props":580,"children":581},"th",{},[582],{"type":53,"value":583},"Provider",{"type":47,"tag":579,"props":585,"children":586},{},[587],{"type":53,"value":588},"Signature header",{"type":47,"tag":579,"props":590,"children":591},{},[592],{"type":53,"value":593},"Verification",{"type":47,"tag":595,"props":596,"children":597},"tbody",{},[598,625,646,674,696],{"type":47,"tag":575,"props":599,"children":600},{},[601,607,616],{"type":47,"tag":602,"props":603,"children":604},"td",{},[605],{"type":53,"value":606},"Stripe",{"type":47,"tag":602,"props":608,"children":609},{},[610],{"type":47,"tag":69,"props":611,"children":613},{"className":612},[],[614],{"type":53,"value":615},"Stripe-Signature",{"type":47,"tag":602,"props":617,"children":618},{},[619],{"type":47,"tag":69,"props":620,"children":622},{"className":621},[],[623],{"type":53,"value":624},"stripe.webhook.ConstructEvent(rawBody, sig, secret)",{"type":47,"tag":575,"props":626,"children":627},{},[628,633,641],{"type":47,"tag":602,"props":629,"children":630},{},[631],{"type":53,"value":632},"GitHub",{"type":47,"tag":602,"props":634,"children":635},{},[636],{"type":47,"tag":69,"props":637,"children":639},{"className":638},[],[640],{"type":53,"value":557},{"type":47,"tag":602,"props":642,"children":643},{},[644],{"type":53,"value":645},"HMAC-SHA256 over the raw body",{"type":47,"tag":575,"props":647,"children":648},{},[649,654,663],{"type":47,"tag":602,"props":650,"children":651},{},[652],{"type":53,"value":653},"Slack",{"type":47,"tag":602,"props":655,"children":656},{},[657],{"type":47,"tag":69,"props":658,"children":660},{"className":659},[],[661],{"type":53,"value":662},"X-Slack-Signature",{"type":47,"tag":602,"props":664,"children":665},{},[666,668],{"type":53,"value":667},"HMAC-SHA256 over ",{"type":47,"tag":69,"props":669,"children":671},{"className":670},[],[672],{"type":53,"value":673},"v0:{timestamp}:{rawBody}",{"type":47,"tag":575,"props":675,"children":676},{},[677,682,691],{"type":47,"tag":602,"props":678,"children":679},{},[680],{"type":53,"value":681},"Shopify",{"type":47,"tag":602,"props":683,"children":684},{},[685],{"type":47,"tag":69,"props":686,"children":688},{"className":687},[],[689],{"type":53,"value":690},"X-Shopify-Hmac-Sha256",{"type":47,"tag":602,"props":692,"children":693},{},[694],{"type":53,"value":695},"HMAC-SHA256 (base64) over the raw body",{"type":47,"tag":575,"props":697,"children":698},{},[699,704,713],{"type":47,"tag":602,"props":700,"children":701},{},[702],{"type":53,"value":703},"Twilio",{"type":47,"tag":602,"props":705,"children":706},{},[707],{"type":47,"tag":69,"props":708,"children":710},{"className":709},[],[711],{"type":53,"value":712},"X-Twilio-Signature",{"type":47,"tag":602,"props":714,"children":715},{},[716],{"type":53,"value":717},"HMAC-SHA1 over URL + sorted form fields",{"type":47,"tag":56,"props":719,"children":721},{"id":720},"always-respond-quickly",[722],{"type":53,"value":723},"Always respond quickly",{"type":47,"tag":63,"props":725,"children":726},{},[727,729,735],{"type":53,"value":728},"Webhook senders retry on non-2xx or slow responses. Acknowledge with a 2xx as soon as the payload is verified, then enqueue the actual work via Pub\u002FSub (see ",{"type":47,"tag":69,"props":730,"children":732},{"className":731},[],[733],{"type":53,"value":734},"encore-go-pubsub",{"type":53,"value":736},") instead of doing it in the request handler.",{"type":47,"tag":106,"props":738,"children":740},{"className":108,"code":739,"language":26,"meta":110,"style":110},"package webhooks\n\nimport (\n    \"encore.dev\u002Fpubsub\"\n    \"net\u002Fhttp\"\n)\n\ntype StripeEvent struct {\n    ID   string `json:\"id\"`\n    Type string `json:\"type\"`\n    Data any    `json:\"data\"`\n}\n\nvar StripeEvents = pubsub.NewTopic[*StripeEvent](\"stripe-events\", pubsub.TopicConfig{\n    DeliveryGuarantee: pubsub.AtLeastOnce,\n})\n\n\u002F\u002Fencore:api public raw path=\u002Fwebhooks\u002Fstripe method=POST\nfunc StripeWebhook(w http.ResponseWriter, req *http.Request) {\n    \u002F\u002F ... verify signature, parse event ...\n\n    _, _ = StripeEvents.Publish(req.Context(), &StripeEvent{\n        ID: event.ID, Type: string(event.Type), Data: event.Data,\n    })\n    w.WriteHeader(http.StatusOK)\n}\n",[741],{"type":47,"tag":69,"props":742,"children":743},{"__ignoreMap":110},[744,751,758,765,773,780,787,794,802,810,818,826,833,840,848,856,864,871,878,885,893,900,908,916,924,931],{"type":47,"tag":116,"props":745,"children":746},{"class":118,"line":119},[747],{"type":47,"tag":116,"props":748,"children":749},{},[750],{"type":53,"value":125},{"type":47,"tag":116,"props":752,"children":753},{"class":118,"line":128},[754],{"type":47,"tag":116,"props":755,"children":756},{"emptyLinePlaceholder":132},[757],{"type":53,"value":135},{"type":47,"tag":116,"props":759,"children":760},{"class":118,"line":138},[761],{"type":47,"tag":116,"props":762,"children":763},{},[764],{"type":53,"value":144},{"type":47,"tag":116,"props":766,"children":767},{"class":118,"line":147},[768],{"type":47,"tag":116,"props":769,"children":770},{},[771],{"type":53,"value":772},"    \"encore.dev\u002Fpubsub\"\n",{"type":47,"tag":116,"props":774,"children":775},{"class":118,"line":31},[776],{"type":47,"tag":116,"props":777,"children":778},{},[779],{"type":53,"value":161},{"type":47,"tag":116,"props":781,"children":782},{"class":118,"line":164},[783],{"type":47,"tag":116,"props":784,"children":785},{},[786],{"type":53,"value":170},{"type":47,"tag":116,"props":788,"children":789},{"class":118,"line":173},[790],{"type":47,"tag":116,"props":791,"children":792},{"emptyLinePlaceholder":132},[793],{"type":53,"value":135},{"type":47,"tag":116,"props":795,"children":796},{"class":118,"line":181},[797],{"type":47,"tag":116,"props":798,"children":799},{},[800],{"type":53,"value":801},"type StripeEvent struct {\n",{"type":47,"tag":116,"props":803,"children":804},{"class":118,"line":190},[805],{"type":47,"tag":116,"props":806,"children":807},{},[808],{"type":53,"value":809},"    ID   string `json:\"id\"`\n",{"type":47,"tag":116,"props":811,"children":812},{"class":118,"line":199},[813],{"type":47,"tag":116,"props":814,"children":815},{},[816],{"type":53,"value":817},"    Type string `json:\"type\"`\n",{"type":47,"tag":116,"props":819,"children":820},{"class":118,"line":208},[821],{"type":47,"tag":116,"props":822,"children":823},{},[824],{"type":53,"value":825},"    Data any    `json:\"data\"`\n",{"type":47,"tag":116,"props":827,"children":828},{"class":118,"line":216},[829],{"type":47,"tag":116,"props":830,"children":831},{},[832],{"type":53,"value":328},{"type":47,"tag":116,"props":834,"children":835},{"class":118,"line":225},[836],{"type":47,"tag":116,"props":837,"children":838},{"emptyLinePlaceholder":132},[839],{"type":53,"value":135},{"type":47,"tag":116,"props":841,"children":842},{"class":118,"line":234},[843],{"type":47,"tag":116,"props":844,"children":845},{},[846],{"type":53,"value":847},"var StripeEvents = pubsub.NewTopic[*StripeEvent](\"stripe-events\", pubsub.TopicConfig{\n",{"type":47,"tag":116,"props":849,"children":850},{"class":118,"line":243},[851],{"type":47,"tag":116,"props":852,"children":853},{},[854],{"type":53,"value":855},"    DeliveryGuarantee: pubsub.AtLeastOnce,\n",{"type":47,"tag":116,"props":857,"children":858},{"class":118,"line":252},[859],{"type":47,"tag":116,"props":860,"children":861},{},[862],{"type":53,"value":863},"})\n",{"type":47,"tag":116,"props":865,"children":866},{"class":118,"line":261},[867],{"type":47,"tag":116,"props":868,"children":869},{"emptyLinePlaceholder":132},[870],{"type":53,"value":135},{"type":47,"tag":116,"props":872,"children":873},{"class":118,"line":270},[874],{"type":47,"tag":116,"props":875,"children":876},{},[877],{"type":53,"value":187},{"type":47,"tag":116,"props":879,"children":880},{"class":118,"line":278},[881],{"type":47,"tag":116,"props":882,"children":883},{},[884],{"type":53,"value":196},{"type":47,"tag":116,"props":886,"children":887},{"class":118,"line":287},[888],{"type":47,"tag":116,"props":889,"children":890},{},[891],{"type":53,"value":892},"    \u002F\u002F ... verify signature, parse event ...\n",{"type":47,"tag":116,"props":894,"children":895},{"class":118,"line":295},[896],{"type":47,"tag":116,"props":897,"children":898},{"emptyLinePlaceholder":132},[899],{"type":53,"value":135},{"type":47,"tag":116,"props":901,"children":902},{"class":118,"line":304},[903],{"type":47,"tag":116,"props":904,"children":905},{},[906],{"type":53,"value":907},"    _, _ = StripeEvents.Publish(req.Context(), &StripeEvent{\n",{"type":47,"tag":116,"props":909,"children":910},{"class":118,"line":313},[911],{"type":47,"tag":116,"props":912,"children":913},{},[914],{"type":53,"value":915},"        ID: event.ID, Type: string(event.Type), Data: event.Data,\n",{"type":47,"tag":116,"props":917,"children":918},{"class":118,"line":322},[919],{"type":47,"tag":116,"props":920,"children":921},{},[922],{"type":53,"value":923},"    })\n",{"type":47,"tag":116,"props":925,"children":926},{"class":118,"line":541},[927],{"type":47,"tag":116,"props":928,"children":929},{},[930],{"type":53,"value":310},{"type":47,"tag":116,"props":932,"children":933},{"class":118,"line":27},[934],{"type":47,"tag":116,"props":935,"children":936},{},[937],{"type":53,"value":328},{"type":47,"tag":56,"props":939,"children":941},{"id":940},"guidelines",[942],{"type":53,"value":943},"Guidelines",{"type":47,"tag":945,"props":946,"children":947},"ul",{},[948,968,973,978,991],{"type":47,"tag":949,"props":950,"children":951},"li",{},[952,953,958,960,966],{"type":53,"value":67},{"type":47,"tag":69,"props":954,"children":956},{"className":955},[],[957],{"type":53,"value":74},{"type":53,"value":959}," ",{"type":47,"tag":961,"props":962,"children":963},"em",{},[964],{"type":53,"value":965},"only",{"type":53,"value":967}," for webhooks and other low-level HTTP integrations.",{"type":47,"tag":949,"props":969,"children":970},{},[971],{"type":53,"value":972},"Always verify the provider's signature before trusting the payload.",{"type":47,"tag":949,"props":974,"children":975},{},[976],{"type":53,"value":977},"Always respond 2xx fast — push slow work onto Pub\u002FSub.",{"type":47,"tag":949,"props":979,"children":980},{},[981,983,989],{"type":53,"value":982},"Store the signing secret in ",{"type":47,"tag":69,"props":984,"children":986},{"className":985},[],[987],{"type":53,"value":988},"secrets struct{...}",{"type":53,"value":990},"; never inline it.",{"type":47,"tag":949,"props":992,"children":993},{},[994,996,1002,1004,1010],{"type":53,"value":995},"For typed JSON endpoints in your own service, use plain ",{"type":47,"tag":69,"props":997,"children":999},{"className":998},[],[1000],{"type":53,"value":1001},"\u002F\u002Fencore:api",{"type":53,"value":1003}," from the ",{"type":47,"tag":69,"props":1005,"children":1007},{"className":1006},[],[1008],{"type":53,"value":1009},"encore-go-api",{"type":53,"value":1011}," skill.",{"type":47,"tag":1013,"props":1014,"children":1015},"style",{},[1016],{"type":53,"value":1017},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":1019,"total":1189},[1020,1034,1046,1062,1078,1090,1106,1121,1138,1155,1164,1175],{"slug":1021,"name":1021,"fn":1022,"description":1023,"org":1024,"tags":1025,"stars":27,"repoUrl":28,"updatedAt":1033},"encore-api","build type-safe APIs with Encore","Define typed API endpoints in Encore.ts using `api(...)` from `encore.dev\u002Fapi`. Covers typed request\u002Fresponse interfaces, path\u002Fquery\u002Fheader\u002Fcookie params, request validation, and `APIError`. For raw endpoints (`api.raw()`) and inbound webhooks, use `encore-webhook` instead.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1026,1029,1030],{"name":1027,"slug":1028,"type":16},"API Development","api-development",{"name":9,"slug":8,"type":16},{"name":1031,"slug":1032,"type":16},"TypeScript","typescript","2026-04-06T18:09:46.044101",{"slug":1035,"name":1035,"fn":1036,"description":1037,"org":1038,"tags":1039,"stars":27,"repoUrl":28,"updatedAt":1045},"encore-auth","implement Encore.ts authentication","Protect Encore.ts endpoints with authentication and authorize callers. Covers `authHandler`, `Gateway`, `getAuthData`, and `auth: true`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1040,1043,1044],{"name":1041,"slug":1042,"type":16},"Auth","auth",{"name":9,"slug":8,"type":16},{"name":1031,"slug":1032,"type":16},"2026-04-06T18:09:47.336322",{"slug":1047,"name":1047,"fn":1048,"description":1049,"org":1050,"tags":1051,"stars":27,"repoUrl":28,"updatedAt":1061},"encore-bucket","store files in Encore.ts buckets","Store unstructured files in Encore.ts using `Bucket` from `encore.dev\u002Fstorage\u002Fobjects` — uploads, images, documents, blobs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1052,1053,1054,1057,1060],{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":1055,"slug":1056,"type":16},"File Storage","file-storage",{"name":1058,"slug":1059,"type":16},"File Uploads","file-uploads",{"name":1031,"slug":1032,"type":16},"2026-05-16T05:59:52.813772",{"slug":1063,"name":1063,"fn":1064,"description":1065,"org":1066,"tags":1067,"stars":27,"repoUrl":28,"updatedAt":1077},"encore-cache","cache data in Redis with Encore.ts","Cache data in Redis from Encore.ts using `CacheCluster` and typed keyspaces from `encore.dev\u002Fstorage\u002Fcache`. Type-safe key\u002Fvalue access with TTLs, atomic increments, and per-keyspace data shapes.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1068,1069,1072,1073,1076],{"name":14,"slug":15,"type":16},{"name":1070,"slug":1071,"type":16},"Caching","caching",{"name":9,"slug":8,"type":16},{"name":1074,"slug":1075,"type":16},"Redis","redis",{"name":1031,"slug":1032,"type":16},"2026-05-16T05:59:56.808328",{"slug":1079,"name":1079,"fn":1080,"description":1081,"org":1082,"tags":1083,"stars":27,"repoUrl":28,"updatedAt":1089},"encore-code-review","review Encore.ts code","Review existing Encore.ts code for best practices and common anti-patterns.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1084,1087,1088],{"name":1085,"slug":1086,"type":16},"Code Review","code-review",{"name":9,"slug":8,"type":16},{"name":1031,"slug":1032,"type":16},"2026-04-06T18:10:01.123999",{"slug":1091,"name":1091,"fn":1092,"description":1093,"org":1094,"tags":1095,"stars":27,"repoUrl":28,"updatedAt":1105},"encore-cron","schedule recurring jobs in Encore.ts","Schedule periodic \u002F recurring work in Encore.ts using `CronJob` from `encore.dev\u002Fcron`. Covers `every: \"1h\"` interval syntax and `schedule: \"0 9 * * 1\"` cron expressions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1096,1099,1100,1101,1104],{"name":1097,"slug":1098,"type":16},"Automation","automation",{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":1102,"slug":1103,"type":16},"Scheduling","scheduling",{"name":1031,"slug":1032,"type":16},"2026-05-16T05:59:54.146651",{"slug":1107,"name":1107,"fn":1108,"description":1109,"org":1110,"tags":1111,"stars":27,"repoUrl":28,"updatedAt":1120},"encore-database","build Encore databases","Work with PostgreSQL in Encore.ts using `SQLDatabase` from `encore.dev\u002Fstorage\u002Fsqldb` — schema migrations and SQL queries.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1112,1115,1116,1119],{"name":1113,"slug":1114,"type":16},"Database","database",{"name":9,"slug":8,"type":16},{"name":1117,"slug":1118,"type":16},"ORM","orm",{"name":1031,"slug":1032,"type":16},"2026-04-06T18:09:54.823017",{"slug":1122,"name":1122,"fn":1123,"description":1124,"org":1125,"tags":1126,"stars":27,"repoUrl":28,"updatedAt":1137},"encore-frontend","connect frontend to Encore backend","Connect a frontend application (React, Next.js, Vue, Svelte, etc.) to an Encore.ts backend.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1127,1128,1131,1134],{"name":9,"slug":8,"type":16},{"name":1129,"slug":1130,"type":16},"Frontend","frontend",{"name":1132,"slug":1133,"type":16},"Next.js","next-js",{"name":1135,"slug":1136,"type":16},"React","react","2026-04-06T18:09:56.091006",{"slug":1139,"name":1139,"fn":1140,"description":1141,"org":1142,"tags":1143,"stars":27,"repoUrl":28,"updatedAt":1154},"encore-getting-started","build and run applications with Encore.ts","Bootstrap a brand-new Encore.ts project from zero. Only for first-time CLI install and `encore app create` — not for architecture or feature questions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1144,1145,1146,1147,1150,1151],{"name":1027,"slug":1028,"type":16},{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":1148,"slug":1149,"type":16},"Local Development","local-development",{"name":1031,"slug":1032,"type":16},{"name":1152,"slug":1153,"type":16},"Web Development","web-development","2026-04-06T18:10:04.885446",{"slug":1009,"name":1009,"fn":1156,"description":1157,"org":1158,"tags":1159,"stars":27,"repoUrl":28,"updatedAt":1163},"build APIs with Encore Go","Define typed API endpoints in Encore Go using `\u002F\u002Fencore:api` annotations. Covers typed request\u002Fresponse structs, path\u002Fquery\u002Fheader\u002Fcookie params, and error returns. For raw endpoints (`\u002F\u002Fencore:api raw`) and inbound webhooks, use `encore-go-webhook` instead.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1160,1161,1162],{"name":1027,"slug":1028,"type":16},{"name":9,"slug":8,"type":16},{"name":25,"slug":26,"type":16},"2026-04-06T18:09:48.578781",{"slug":1165,"name":1165,"fn":1166,"description":1167,"org":1168,"tags":1169,"stars":27,"repoUrl":28,"updatedAt":1174},"encore-go-auth","implement authentication with Encore Go","Protect Encore Go endpoints with authentication and authorize callers. Covers `auth.AuthHandler`, `auth.UserID`, the `Authorization` header, and `\u002F\u002Fencore:api auth`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1170,1171,1172,1173],{"name":1041,"slug":1042,"type":16},{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":25,"slug":26,"type":16},"2026-04-06T18:09:51.065102",{"slug":1176,"name":1176,"fn":1177,"description":1178,"org":1179,"tags":1180,"stars":27,"repoUrl":28,"updatedAt":1188},"encore-go-bucket","store files in Encore Go buckets","Store unstructured files in Encore Go using `objects.NewBucket` from `encore.dev\u002Fstorage\u002Fobjects` — uploads, images, documents, blobs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1181,1182,1183,1184,1185],{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":1055,"slug":1056,"type":16},{"name":25,"slug":26,"type":16},{"name":1186,"slug":1187,"type":16},"Storage","storage","2026-05-16T06:00:03.633918",28,{"items":1191,"total":1189},[1192,1198,1204,1212,1220,1226,1234],{"slug":1021,"name":1021,"fn":1022,"description":1023,"org":1193,"tags":1194,"stars":27,"repoUrl":28,"updatedAt":1033},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1195,1196,1197],{"name":1027,"slug":1028,"type":16},{"name":9,"slug":8,"type":16},{"name":1031,"slug":1032,"type":16},{"slug":1035,"name":1035,"fn":1036,"description":1037,"org":1199,"tags":1200,"stars":27,"repoUrl":28,"updatedAt":1045},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1201,1202,1203],{"name":1041,"slug":1042,"type":16},{"name":9,"slug":8,"type":16},{"name":1031,"slug":1032,"type":16},{"slug":1047,"name":1047,"fn":1048,"description":1049,"org":1205,"tags":1206,"stars":27,"repoUrl":28,"updatedAt":1061},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1207,1208,1209,1210,1211],{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":1055,"slug":1056,"type":16},{"name":1058,"slug":1059,"type":16},{"name":1031,"slug":1032,"type":16},{"slug":1063,"name":1063,"fn":1064,"description":1065,"org":1213,"tags":1214,"stars":27,"repoUrl":28,"updatedAt":1077},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1215,1216,1217,1218,1219],{"name":14,"slug":15,"type":16},{"name":1070,"slug":1071,"type":16},{"name":9,"slug":8,"type":16},{"name":1074,"slug":1075,"type":16},{"name":1031,"slug":1032,"type":16},{"slug":1079,"name":1079,"fn":1080,"description":1081,"org":1221,"tags":1222,"stars":27,"repoUrl":28,"updatedAt":1089},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1223,1224,1225],{"name":1085,"slug":1086,"type":16},{"name":9,"slug":8,"type":16},{"name":1031,"slug":1032,"type":16},{"slug":1091,"name":1091,"fn":1092,"description":1093,"org":1227,"tags":1228,"stars":27,"repoUrl":28,"updatedAt":1105},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1229,1230,1231,1232,1233],{"name":1097,"slug":1098,"type":16},{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":1102,"slug":1103,"type":16},{"name":1031,"slug":1032,"type":16},{"slug":1107,"name":1107,"fn":1108,"description":1109,"org":1235,"tags":1236,"stars":27,"repoUrl":28,"updatedAt":1120},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1237,1238,1239,1240],{"name":1113,"slug":1114,"type":16},{"name":9,"slug":8,"type":16},{"name":1117,"slug":1118,"type":16},{"name":1031,"slug":1032,"type":16}]