Fix permission removal on Shopify scope edit
Previously, editing Shopify scopes would reset the permissions of the shopify-app-users
role to match the requested scopes. We have fixed this to only remove permissions of scopes that have been removed from the connection.
Released @gadgetinc/react v0.17.0
A new version of @gadgetinc/react has been released. This version includes improvements and bug fixes for autocomponents:
- Updated the
select
property inuseTable
andAutoTable
to completely override the default selection instead of being combined with the default selection (Breaking change) - Updated
AutoForm
to throw an error when given an invalid action - Updated
AutoSubmit
to always show a loading state while submitting - Updated the
AutoTable onClick
callback prop to accept the fullGadgetRecord
corresponding to the row as well as theTableRow
itself - Bug: Fixed an issue with
AutoTable
where custom cell renderers with duplicate headers would have duplicate columns content - Bug: Fixed bug in Polaris
AutoTable
where thecreateNewView
button would erroneously appear on certain parent element widths - Bug: Fixed a bug in
AutoForm
where thedefaultValues
prop values was not included in the submission request if the defaulted field was excluded with the include or exclude properties
Gelly: new manipulation functions for date, datetime, and interval values
Additional functions for working with date, datetime, and interval data have been added to Gelly.
datePart()
and dateTrunc()
allow for the manipulation of intervals and reflect the corresponding Postgres functions date_part and date_trunc.
datePart
allows you to extract a subfield from a value, for example,datePart("day", date: interval("3 days 60 hours"))
would return 3dateTrunc
allows you to truncate an Interval, for example,dateTrunc("month", date: interval("4 months 5 days"))
returns an interval of 4 months
makeDate()
, makeTimestamp()
, and makeInterval()
allow for the creation of time-related values from numeric inputs and have the following signatures:
makeDate(year: number, month?: number, day?: number): Date
makeTimestamp(year: number, month?: number, day?: number, hour?: number, minute? number, second?: number): DateTime
makeInterval(years?: number, months?: number, weeks?: number, days?: number, hours?: number, minutes? number, seconds?: number): Interval
Support for the ShopifyProductMedia and ShopifyProductVariantMedia models
Gadget now supports Shopify's ProductMedia
and ProductVariantMedia
models. These models replace the ProductImage
model, which will soon be deprecated. This change was necessary to sync product related media accurately and deterministically. ProductImage
is synced non-deterministically due to an individual image now belonging to many products.
Learn more about the Media resource here and get more information about this change in our docs.
actAsSession and actAsAdmin added to API clients
The Gadget API client used in action and route contexts has admin privileges by default. This is typically what you want in backend code so you can implement your business logic and use the internal API.
With the introduction of Remix, it is confusing when the API client in loaders has admin privileges but the corresponding API client side has the privileges of the current client session. To fix this we've added two methods to Gadget API clients: api.actAsSession
and api.actAsAdmin
which allow users to switch between the two privilege levels.
In Gadget actions and route handlers, the API client will be admin by default, but api.actAsSession
can be used to switch to the session's privileges. In Remix loaders, the API client will have the privileges of the session that made the request, but api.actAsAdmin
can be used to switch to admin privileges.
CSRF token support
With the introduction of support for Remix SSR, we need to support form submissions with app cookie authentication. Until today this was left as a todo, since all mutations were handled by our API client. However Remix promotes using standard HTML forms for data mutations and we were not allowing requests authenticated with an app cookie to submit forms.
This release adds a csrfToken
property to application session records, that can be used in Remix loaders to add to server-rendered forms. Read more in the documentation.
Remix support
Build Shopify or web apps with Remix in Gadget, using server-side rendering or single-page application mode. Read the announcement here.
Docs chatbot moved to OpenAI Assistants API
The docs chatbot has received a major upgrade behind the scenes. It has moved to the new OpenAI Assistants API which now handles all the heavy lifting of searching the doc embeddings. Try the chatbot.
Data deletion warning on deploy
A warning has been added to the deploy modal that informs users what model or field data will be deleted as a result of deploying their changes to production. Read the docs for more information.
App list deprecation banner added
Gadget is deprecating all framework versions under 1.0 by March 1st, 2025. A banner has been added to the app list page to inform users of this change. It will only show up for users that have apps on deprecated versions.
Gelly bug fix: wrong count of relationship chain when there are no related rows
There was a bug in the implementation of count()
when the counted expression was a relationship chain, for example: count(students.courses)
.
The returned count could be higher than expected if a relationship in the chain had zero rows for some of the rows of the preceding relationship. A relationship chain is compiled into a chain of left joins and we used expression count(1)
for relationship counts. We now make sure to use expression count(id)
for relationship chains which filters out any null rows introduced by the left join.
Longer cache TTL for production frontend assets
We discovered that our default Cloudflare cache configuration for production frontend assets was only 4 hours long. Since frontend assets are versioned by content, we can be much more aggressive with how long browsers can cache them. We now tell browsers to cache production frontend assets for a year. This will help lower LCP times for Shopify.
Changelog available in Gadget editor home page
A changelog of the most recent bug fixes, features, and updates is now available on the Home page in the Gadget editor.
Fix "unable to ggt dev" after renaming Shopify extension directory
Fixed an issue where ggt dev would infinitely loop after renaming or deleting a directory within an extensions folder.
Reset vite caches when hitting Restart node modules in the editor
Vite's filesystem cache sometimes gets corrupted during normal operation, which can break development environments. To fix this, the Vite filesystem cache at node_modules/.vite
needs to be cleared. We now automatically do this cache reset when users hit Restart node modules in the command palette in the editor.
BigCommerce connection
Gadget now has a BigCommerce connection that handles OAuth, frontend session management, webhook subscriptions, and more for developers building single-click apps. The BigDesign library is set up in a React frontend, and the @space48/bigcommerce-api-js client is included for sending requests to the BigCommerce API.
See the connection quickstart and documentation for more information, and learn to build a full-stack single-click app with the tutorial.
Fix Vite restart bug
Fixed a bug related to closing HMR websockets and Vite in development environment frontends:
- when an app was left idle too long and you came back to your app, you would be presented with a blank screen
- when you added a model (or did anything that restarted the sandbox), your app would go blank
Both of these were fixed by making sure that when an app sandbox shuts down, the HMR websocket was closed in the way expected by Vite.
Autocomponents now available
Autocomponents provide high-level React components - data tables and forms - that are pre-configured to read and write data using your app's backend actions. They use a design system under the hood and this initial release focuses on Shopify Polaris.
They are configurable and extensible, and can be used to build complex user interfaces with minimal code.
For more info on building with autocomponents, read our guide.
Vite development server respects version in `package.json`
The vite
dependency version set in package.json
has always been used to build app frontends in production. However we were not respecting this version for the development server. This issue is now fixed, and the same user-defined vite
version is used for the development server and for building production.
Shopify Storefront API access scopes now available
Shopify's Storefront API access scopes are now available as options when setting up your Shopify connection in Gadget. Developers also have the option to enter a comma-separated list of scopes for any scopes not available in the existing list.
Updated background action UI
We've made performance and UX improvements to the background action UI.
The updated background actions page will see a 3-5X improvement in loading, filtering, and search performance. The UX improvements include an easier to find check logs link, relative enqueued and last attempt times, a new cancelled tab, and better handling of long job ids and errors.
Gelly schema changes for `has many through` relationships
Gelly schema for has many through
relationships now includes automatically generated has many
relationships to the through
model.
For example, if student
has many courses
through registration
, the schema for student
now includes student.registrations
. This allows you to filter by field values on the registration
model when querying for student
records.
// filter students by a registered date field on registrations
students {
registrations {
course: course.title
[ where registered > date("2020-12-31") ]
}
}
Gelly updates: multiple improvements and bug fixes
Lots of fixes and improvements have been recently added to Gelly.
Improvements have been made to Gelly's SQL compilation process, resulting in fewer sub-selects and more joins. This includes the following changes and fixes:
- improved relationship traversal - accessing related fields in Gelly now works for all relationship types
- expressions that include multiple relationship chains are now supported
- aggregation target changes for has one relationships
- group by expression fixes
- support for has many through relationships in Gelly
Types can now be inferred for results of arbitrary Gelly expressions thanks to:
- new base types, including updates to Date and DateTime, an Interval type for date arithmetic, and proper Vector support
- ternary expressions no longer cast non-compatable results and require explicit casting
- casting to additional base types is possible, and no longer relies on jsonb
types
- coalesce()
now uses the Postgres coalesce function and requires compatible types
Validation and error reporting has been improved, including:
- more precise and informative error messages including the sourceFilePath
- additional validations have been added
- check for mixing aggregate and non-aggregate expressions in a selection
- check for the use of has many relationships in a scalar context
- check that group by expressions yield a scalar value for each row of the root model
- check that selection aliases do not conflict with root model field names if the are referenced in a group by expression
These changes have also resulted in better integration with Gadget:
- better filter typing on computed fields
- support for has many through relationships in computed fields and model filters
- Gelly deduplicates fragment selections that select the same fields
- Gelly supports traversing across relationships to the same module multiple times in a single expression
Other improvements include bug fixes to arithmetic operator associativity and the addition of an any()
function to Gelly.
Upsert API
The upsert API has been released to all apps. All existing apps will immediately have access to api.internal.<model>.upsert
. Any apps on framework version >=1.1 will have a public upsert API for any model that has both a create and an update action. Read more in our guides.
Lowered default retry count for background actions in development environments
The number of default retires for background actions has been lowered from 10 to 2 in development environments. This results in less noise while developing. A warning will also appear in the logs when a background action fails to execute. The default retry count for background actions is still 10 for all production environments.
Improved product Shopify variant webhook handling
Shopify’s product webhooks now contain the updated_at
field for each variant. Gadget will now use this field to determine if a variant needs to be fetched from Shopify when handling product webhooks. If the variant’s updated_at
field in the webhook payload is newer than what is stored in the product variant's shopifyUpdatedAt
field, Gadget will fetch the updated variant info from Shopify.
Additions and updates to Shopify DraftOrder, FulfillmentService models
Gadget now uses Shopify's GraphQL API to sync DraftOrder and DraftOrderLineItem model data. The DraftOrderPlatformDiscount and DraftOrderPlatformDiscountAllocation models have also been added.
The FulfillmentService model for apps on Shopify API version > 2024-07 will use the GraphQL API for syncing data.
ggt v1.0.5 released
New version of ggt has been released with the following updates:
- uses
esbuild
to bundle, minify, and tree-shake, reducing package size and improving command speed- ggt package size reduced from ~60MB to ~8MB
ggt help
performance improvement from ~350ms to ~170ms
- Fixed an issue causing
ggt deploy
to hang after deploying an app - Fixed an issue causing
ggt dev
to print "Pulled files." when only hidden files were pulled - Fixed an issue causing
ggt
to not work when run with Node.js 18.17 or lower
Added support for Shopify API version 2024-07
Gadget has now added support for Shopify API Version 2024-07. This version includes additions to the Shopify Order, Draft Order, and Customer models, and disconnects deprecated fields on Product Variants. Details and additional changes can be found in our Shopify API version changelog docs.
New JavaScript playground available for backend testing
Quickly test your APIs with the new JavaScript playground. You can now run your environment’s actions in a JS console that has been pre-loaded with your Gadget app’s API client. Read the blog post for more info.
New GADGET_ENV and GADGET_APP environment variables
Access the current environment and app name in code using process.env.GADGET_ENV
and process.env.GADGET_APP
. These can be used in both the frontend and backend, and are useful for adding environment-specific behaviors to apps.
connections available in the gadget-server package
The connections
object has been added to the gadget-server package. You can use this to access credentials or connected clients outside of actions or routes. We have a boot plugin example and more details available in our docs.
Shopify user ID and session token are included in connections
Use connections.shopify.currentSession.userId
to get the ID of the Shopify user making a request. This allows for per-user functionality to be added to embedded Shopify admin apps. You can also read the Shopify session token that was used to authenticate the current request with connections.shopify.currentSession.token
. If you want to learn how to access additional Shopify user data using OAuth token exchange, check out our docs.
Released Gadget framework v1.1
Version 1.1 of the Gadget framework includes the ability to use realtime queries in imperative API clients, a ggt add
command that adds models and actions to a project from the command line, a ~30% smaller API client, improvements to project folderization, API namespace control, and an upgrade to Node 20.12. Read more on framework v1.1.
Added support for new customer account authentication
Gadget now supports making authenticated requests from within Shopify customer account UI extensions. A new access control role, shopify-storefront-customers
can be added to apps during Shopify connection setup, allowing for fine-grain control over which actions customer users can call within extensions. Read our docs to learn more.
New @gadgetinc/shopify-extensions package
A new package that makes it easier to register a session token with your Gadget app's API client. Can be used for both React and JS/TS extensions, and works with a variety of Shopify extension types, including customer account UI or checkout UI extensions. Read the reference docs for more information.
Shopify webhooks as triggers for global actions
Shopify webhooks are now available as triggers for global actions, meaning you can build stateless applications that run custom code on incoming Shopify webhooks without storing the webhook payload in the database, saving on data storage costs. Learn how to use them in our docs.
Added support for Shopify API version 2024-04
Gadget has now added support for Shopify API Version 2024-04.
This update introduces support for up to 2,000 variants per product. Gadget will automatically synchronize all variants, ensuring that users do not need to manually update their product variant data. All the increased compute time required for this new functionality is provided free of charge.
Enhanced webhook payloads now include a variant_gids
field that lists all variant IDs for up to 2,000 variants, but only when the extended variants feature is enabled. This field helps in automatically fetching all variant data beyond the first 100, ensuring comprehensive data access without extra effort.
Added ability to run background actions in bulk
Bulk actions can now be enqueued for execution in the background. Pass a bulk action to api.enqueue
like you might any other action, and each element of the bulk action will run as its own background action.
Application filters on usage reports
Usage reports on the Usage tab are now filterable by specific applications. Allowing users to dig deeper into the triggers, shops, models, and actions that are using the most resources.
Support for running actions in the background
Gadget now supports background actions, enabling actions to run in the background, similar to background jobs. This allows developers to offload time-consuming processes from the main workflow, improving tasks like external API interactions and data processing. Wrap your actions in api.enqueue()
to run them in the background. For more information check out the guide here.
Support for Git based source-control
Gadget applications can now enable source control using Git, through the use of various metadata files! To get started, use Gadget's CLI ggt
to clone your app's files into a local directory and manage any changes between your local directory and the Gadget editor (in real time!). For more information on how to use Git based source-control with Gadget check out our guide here.
Support for unlimited development environments
Gadget now enables developers to created unlimited, development environments for each project, featuring separate databases and code deployment facilities. These environments come with unique URLs and allow for independent version control, enhancing testing and development flexibility. For more information check out the guide here.
Added support for Shopify App Bridge V4
Gadget has now added support for App Bridge v4 from Shopify. For more information on how to upgrade read the guide here.
Export model data to CSV
The data editor within Gadget now provides the ability to export your data to a CSV, to do so navigate to the button in the `More Actions` menu. Exporting a CSV will export all the data for the model matching the current search in the editor to a CSV file, and email a link to that file to the current user. All fields on screen in the data editor will be included in the export, which excludes computed fields and fields of related models.
Add support for Web Workers to Gadget frontends
Gadget's default Vite configuration now supports using Web Workers with no extra configuration. Read more about Web Workers with Vite here.
Scheduler sets scheduled date and time in UTC
The scheduler trigger now allows setting the selected date and time in UTC. A local equivalent of the scheduled date and time will also be shown to users.
Shopify API Version 2024-01
Gadget now supports Shopify API version 2024-01. For a full list of changes see our API changelog here.
Gadget v0.3.1 - Shopify webhook disabling
Gadget framework version v0.3.1 is released with support for shop level webhook disabling and a splitting the implicit daily sync into an explicitly scheduled sync and a webhook reconciliation. For more information check out our guide here.
Add support for exporting logs from the log viewer
Gadget developers can now export the contents they see in the log viewer to a file using the more actions button. All logs matching the search query and time range will be compiled into an .ndjson file and a link to the file will be emailed to the developer.
Shopify webhooks will respond 410 gone if shop is uninstalled
Currently Gadget will attempt to accept webhooks for a shopify shop that is marked as uninstalled in an apps database even though we processing that webhook will fail since that shop record will not have an access token. This means that an app will be billed for webhooks that we know will fail. After this change Gadget will respond to Shopify with a 410 (GONE) code which will eventually cause Shopify to stop sending webhooks for that shop.
Fix support for boot-time only node environment variables
Gadget now supports setting environment variables that are only read once by node.js at boot time, like NODE_EXTRA_CA_CERTS. Previously, these values were ignored to maximize boot performance, but now Gadget will correctly restart the node process in order to reflect changes to these variables.
Request details to action contexts
Most actions are triggered by HTTP requests. Gadget exposes the details of the HTTP request that is causing an action to run at the request property of the action context, so you can get at stuff like the requester's IP address for attribution, or headers for rolling your own auth. Actions don't generally need to care about the request, but if they need to, it's there!
Gadget framework v0.3
The Gadget framework v0.3 introduces support for Fastify V4 and Node 20. All new apps will come with default support for v0.3, existing apps will have to update their version. For a full list of changes and how to update your framework version check out our guide here.
Enable upgrading and downgrading framework versions
Gadget supports a few different framework versions: each is a well-tested, trusted stack of system components. App developers can now control which framework version their app uses in their settings. To upgrade or downgrade, change the framework version in the settings, which will kick off a yarn install to update npm package dependencies for your app to match your system component versions. For more on how to change your framework version follow our documentation guide here.
Google OAuth tokens available in trigger payload
When users choose to use custom credentials for their google oauth they will now receive the oauth tokens in the trigger payload. For apps using custom credentials there is now a toggle to request offline access from users. This will perform the google oauth request with access_type=offline and prompt=consent and will result in a refreshToken being available in the trigger payload. For users using Gadget managed credentials they will no longer be able to edit the scopes that are requested.
Abort a Shopify sync
Shopify syncs on new apps now have an abort action that allows developers to abort a running sync. Syncs that are aborted will be in the "errored" state, and any long running activities will be stopped immedietely. For existing apps refer to our documentation guide on how to add the abort action.
Usage reports
Introducing detailed usage reports in Gadget, offering deep insights into how your apps utilize cloud resources. For more information check out our blog post here.
Added support for App-owned metafields
With the upcoming deprecation of private metafields, Gadget now supports app-owned metafield namespaces. To sync or register webhooks for app-owned metafield namespaces you may use either the app-{your-app-id}--{some-namespace} or $app:{some-namespace} reserved namespaces when setting up model fields. For more information check out our guide here
Email/Password authentication now available on new projects
New Gadget apps can now be created with built-in support for Email/Password authentication. The starter Web and AI template now includes customizable actions enabling users to sign-up, sign-in, verify emails, reset and change passwords. Gadget now takes care of email sending by default with actions, but users have the flexibility to integrate with external email providers such as MailChimp and SendGrid as well as customize the default email templates. For more information check out our docs.
`emails` as an action context option
Each action is passed an emails object, which is an instance of the GadgetMailer (a Gadget wrapper for NodeMailer), that is primarily used to handle and facilitate the sending of emails.
Added support for the Shopify API Version 2023-10
Gadget now supports Shopify API version 2023-10. For the full list of changes see the API changelog here.
Ability to opt out of daily sync for Shopify models without webhooks
The Shopify connection will automatically fetch all recent data in the background daily. This ensures we have all of the shop's data in the case of a missing webhook or for models that don't have webhooks.
Users have asked for control over whether or not Gadget should run an automatic daily sync for models that do not have webhooks. Starting with this change Gadget supports opting out of the automatic daily sync for models that do not have webhooks.
Added support for realtime queries from React frontends
Gadget frontends can now subscribe to backend data changes in realtime with the live: true option for the React hooks.
Pass live: true as an option to one of the finder hooks, and the browser will watch for new data, fetch it, and re-render automatically when it changes within your backend.
For in depth details check out our realtime queries doc.
Changes to how your apps are deployed
We've added a new step to the deployment flow of your app: setting up database. This ensures all the new models and fields you've added since the last deploy are ready to go before your app finally hits production.
With this change, expect the following changes during deploy:
1. If you've added or changed a field on a model that has a lot of records in production, your deploy may take some time, but you should see progress on how many fields have been set up so far.
2. If you've added a uniqueness validation to a field, your deploy will fail if the data for that field isn't unique in production.
Added support for Shopify Session Tokens sent from Checkout Extensions
Gadget now supports authenticating requests made from Shopify Checkout Extensions using Shopify's Session Token feature. Inside a checkout extension that has the network_access capability, you can make a request to your backend Gadget API or an HTTP route.
Within your backend Gadget app, you can access the connections.shopify.current object, knowing that the request is provably for a given shopify shop
Requests made from a Checkout extension are made by customers, and will use the unauthenticated role. This is different than requests made from your embedded app, which also use Session tokens, but are for merchants. Requests made by merchants in the embedded app will use the shopify-app-user role.
For in depth detailes check out our building shopify extensions doc.
Support for caching responses in Gadget's CDN
Gadget now supports caching responses from HTTP routes in its high-performance, pre-configured CDN. If your route serves a Cache-Control header, the response will be cached at the edge and sent back to your users as you see fit.
For more information check out our guide on response caching here.
Add a new high performance App URL entrypoint for Shopify apps
Previously, Gadget recommended that Shopify applications use the /shopify/install URL for their App URL configuration value in Shopify. This URL is where Shopify sends both uninstalled merchants that need to install an app, and already installed merchants that want to start using the application. The performance of this route is sensitive because it is the first touchpoint each merchant has with your application.
Gadget now supports a high-performance entrypoint for Shopify applications that improves an app's LCP time. This route will trigger the OAuth and install flow for new merchants, and redirect existing merchants to / for rendering the frontend experience of your application. This route is optimized by Gadget to be as fast as possible and does not require starting up the serverless runtime for your application, which means the performance will be much more predictably low.
Gadget will default to using this URL for new applications.
For existing applications, you can take advantage of the new route by changing your App URL to be <your app domain>/api/shopify/install-or-render.
For example, for a Shopify app built with Gadget at shopify-example.gadget.app, you can set these values:
Development App URL: https://shopify-example--development.gadget.app/api/shopify/install-or-render Production App URL: https://shopify-example.gadget.app/api/shopify/install-or-render
Added support for CRON intervals in Scheduler Triggers
Gadget now supports defining Scheduler triggers using cron syntax. If you have strange or specific intervals you need to run your jobs at, you can use a cron expression for maximum precision!
Fix BelongsTo fields to the Shopify Shop model being automatically populated
Previously, when processing webhooks from Shopify, Gadget would populate any belongs to field pointing to the shopifyShop on Shopify models. Now, Gadget will only set the value of the default shop field, and leave any other BelongsTo fields to be set by application code.
Encrypt strings in place when string fields are changed to encrypted strings
Previously, when a field was changed from the string field type to the encrypted string field type, Gadget would erase the data in the field and require data to be re-loaded into it.
Now, no data will be erased, and Gadget will transparently encrypt the data at rest without needing it to be reloaded. Existing data will be preserved.
Google OAuth now available on new projects
New Gadget apps can now be created with built-in support for Google OAuth driven authentication. The starter App.jsx template now includes a basic Sign in with Google button and renders a User card with some user information when signed in. Behind the scenes Gadget uses OAuth to authenticate the user with Google, and then creates a User record. The default behavior can be extended with the new @gadgetinc/auth fastify Auth plugin as well as by working with the actions on your User model.
In addition to the back-end model and oauth support, we've added some new front-end components to help you build your own authentication flows. The @gadgetinc/react package now includes several new React hooks and components to help you build your application with users in mind. Read more about it in the @gadgetinc/react docs .
Gelly errors now shown in the editor
Gelly syntax and usage errors will now be displayed in the Gadget editor with red underlines.
Enhanced support for ShopifySessionToken in authorization header for checkout extensions
Introducing improved support for seamless integration of your-session-token in the Authorization header for API requests. This update enables the utilization of session tokens generated through the use of checkout extensions' useSessionToken. Previously, attempts to employ such tokens led to error responses from Gadget.
Upgraded to Vite 4.4.9 for improved performance
Gadget now uses Vite version 4.4.9 for all applications. Vite 4.4 brings many performance improvements and no breaking changes.
For more on what's new in Vite 4.3 and Vite 4.4, see the Vite blog: https://vitejs.dev/blog/announcing-vite4-3.html
Add support for the Shopify Gift Card model
Gadget now supports syncing Shopify's Gift Card resource.
Shopify only supports Gift Card API access for Shopify Plus stores, and only with Custom apps provisioned within the Shopify Admin. Shopify also doesn't expose webhooks for Gift Cards, so the Gift Card model is synced only.
Production Environment not deployed on app creation
When creating a new Gadget app, the automatic deployment of the Production environment will no longer take place by default. Instead, all apps will begin with a development environment and will require a deployment from the Gadget editor to set up the production environment.
Accept and return role names for Role List fields
Previously, Gadget stored the list of roles assigned to a Session or a User using internal, unique identifiers for Roles called role keys. Role keys are annoying to retrieve and use, so now Gadget accepts a list of role names as input for the Role List fields. In the Public API, roles return values are unchanged, and still returned as objects like {name: "readers", key: "readers"}. The Internal API now returns the list of roles as a list of role names, instead of role keys.
For backward compatibility, both the Public API and the Internal API still accept role keys as input, but role names should be preferred.
Upgrade to urql v4 in the generated API client and @gadgetinc/react
Each Gadget app's generated JS client uses the production-grade urql GraphQL client under the hood. The generated JS clients now depend on urql v4 for improved performance, smaller bundle size, React <Suspense/> support, and more. The next version of your app's JS client will depend on the newer version of urql, and you must upgrade @gadgetinc/react to match.
Add support for the isSet filter operator on Boolean fields
Models can now be filtered by if a Boolean field is set at all or not. Use { filter: { someBooleanField: { isSet: true }}} to only return records where the field is set to something (either true or false), and use { filter: { someBooleanField: { isSet: false }}} to only return records where the field is not set (equal to null).
Improved handling of cleared Metafield fields
Gadget will now correctly set your Gadget metafield fields to null if they have been cleared in Shopify. They were previously left with the last non null value.
Company models available for apps with Shopify Partners Plus stores
Gadget now supports b2b models (i.e. Company models) and their associated webhooks that are only available for stores with Shopify Plus Partners accounts.
See the company Shopify API: Admin GraphQL docs for more information about the resource.
Only allow access to the API docs for applications to logged-in users
Previously, Gadget application's API references were accessible to anyone with the URL. Now, API references are only accessible to Gadget users who can edit the application. If you'd like to grant a user access to your application's API reference, add them to your Team so they can access your application's editor.
Add an option to the useFetch hook for pausing the request initially.
The useFetch API client hook now supports a sendImmediately option for explicitly controlling if the request should be sent immediately on render or not.
See the useFetch documentation here for more information on the sendImmediately option.
Vector field type
Gadget models can now store Vectors using the vector field type. Vectors allow sorting and filtering by vector similarity, which is useful for building semantic search and AI applications.
See the vector field docs and the building AI apps guide for more information.
Serving static files in development
We fixed a bug that prevented you from serving static files like images, text files, etc. from /public in your development environment.
Code editor Go To Definition takes you to the definition, not just the file
When using the “Go To Definition” for Gadget types in the code editor you’d be taken to the file of the definition, but not the definition itself. We’ve fixed this bug, and you’ll now be taken to the correct line in the file as well.
Improvements to file and folder management
We’ve improved the experience of how you manage files and folders in Gadget. Drag files and folders to rearrange them. Move them up and down your file tree without having to rename the path, and the destination folder will be highlighted as you go. You can read more about it in this blog post.
Early on we caught a few bugs around overwriting files and folders with duplicate names which we addressed.
Access to environment variables in frontend
You can now access environment variables in your frontend if the variable name starts with GADGET_PUBLIC.
HTTP routes function signature made consistent with other effect context
The function signature for HTTP route handlers were inconsistent with effects elsewhere in Gadget. The other effects deconstructure out useful things automatically, which is a better experience because you don't have to do it yourself when you need these.
We’ve updated routes to do this too, and updated the routes documentation with these changes.
React hooks return objects with the same identity if nothing changes on render
In some circumstances you could trigger an infinite loop in your frontend when using useEffect. It happened because the object returned had a different identity, even if nothing had changed. This was a bug, and has been fixed. If nothing about the query has changed, you get back the same data object, and no-run takes place.
TypeScript IntelliSense for files in frontend folder
When using the Gadget code editor you get TypeScript powered editor hovers in your code files. That didn’t work as expected for files in the frontend folder, which displayed “any” on hover.
This has been fixed, and types now show as expected on hover for all your code files.
Shopify Shop model create action renamed from create to install
When a Shopify merchant installs your app on their store Shopify fires a webhook to your Gadget app. The webhook is captured by the Shopify Shop model, and a record is created with information about the merchant's shop.
We’ve renamed the Shopify Shop model API action that captures this from “create” to “install” to make it clearer to developers what triggers it.
Apps created before this change will be unaffected since it would be a breaking change to change the action name.
Broken Connection workflow on forked apps
After forking an app that had a Shopify connection, the connection page in the newly forked app displayed a banner asking you to complete the connection setup. If you clicked it, you were shown a screen with null app URL and allowed redirection URLs. That was a dead end and a bug, so we fixed it.
Empty folders weren't shown in Gadget when using ggt Filesync
When you created empty folders on your computer with the ggt CLI Filesync they didn’t appear in Gadget until you created a file in them. That’s not a great experience, so we fixed it. Now empty folders get synced from your local computer to Gadget.
Shopify OAuth flow not shown when merchants loads embedded app after you’ve added new scopes to connection
During the closed beta of Gadget's hosted React frontend there was a bug where the embedded Shopify app wouldn’t render correctly if the merchant loaded the page after you had edited your connection to add more scopes.
The expected behavior is for the embedded app UI to display the Shopify OAuth flow, where the merchant can grant access for the newly added scopes. This has been fixed.
ggt Filesync login bug
There was a bug in a ggt Filesync flow where users ran the command `ggt sync --app foo` without being logged in. If you weren't already logged in this command should first log you in, then check if you have an app named 'foo'. But this was made in the reverse order which led to the CLI returning an “unknown application” error. This works as expected now, so sync away!
Improved logs behavior in development environment
We've improved the default behavior of the logs viewer in development. When you browse to the logs "live mode" will automatically be on so you see the latest log entries without having to click a button. Your previously selected time window will still be used, and defaulted to a 5 minute window otherwise. And any logs search parameters used previously will be cleared automatically. More logs, less clicks.
NODE_ENV environment variable values weren’t automatically populated on forked apps
Any app you create automatically has a NODE_ENV variable with values ‘development’ and ‘production’ for the respective environment.
But when you forked an app, these values didn’t propagate and were set to null. The root cause was that we don't want to auto-copy keys stored in the forked apps since these may be sensitive. We’ve made an exception for NODE_ENV. Keep forking.
Use correct Shopify content security policy headers for Gadget frontends
Shopify apps built on Gadget automatically pass the technical requirements in Shopify’s app store review process. During the closed beta of Gadget’s hosted frontends we identified that apps using the frontend for the embedded Shopify app failed Shopify's Content Security Policy headers check, so we promptly fixed that before any users were impacted.