diff --git a/admin-tools/README.md b/admin-tools/README.md new file mode 100644 index 00000000..5b32e6ec --- /dev/null +++ b/admin-tools/README.md @@ -0,0 +1,34 @@ +# Admin App Tools Extension + +Admin app tools extensions enable app developers to provide data and search functionality to Sidekick in the Shopify Admin. These extensions allow Sidekick to query your app's external data sources and surface results to merchants. + +Learn more about Admin app tools extensions in Shopify's [developer documentation](https://shopify.dev/docs/apps/build/sidekick/build-app-data). + +--- + +## Get started with this extension + +This extension demonstrates adding search functionality for Sidekick. After deployment, Sidekick will be able to run the search tool to query for the app's data. + +### Key files + +- `src/index.js` - Main extension code that defines the search tool execution logic +- `tools.json` - Schema definition for the search tool's inputs and outputs + +### How it works + +1. The extension registers a `search` tool using `shopify.tools.register()` +2. When Sidekick is asked to search for a resource, your search function is called with the query +3. Your function returns results matching the schema defined in `tools.json` + +### Customizing the search + +Edit `src/index.js` to implement your search logic: + +1. Fetch data from your app's backend or API +2. Filter/search the data based on the `query` input +3. Return results in the expected format with pagination info + +### Testing locally + +Run `shopify app dev` and click on the "admin.app.tools.data" preview link in the Dev Console to test your extension in development mode diff --git a/admin-tools/instructions.md b/admin-tools/instructions.md new file mode 100644 index 00000000..075c9844 --- /dev/null +++ b/admin-tools/instructions.md @@ -0,0 +1,18 @@ +## When to Use This App's Tools + +Use these tools when the merchant asks about: + +- Data or records from apps + +## Important Guidelines + +- Use the `query` parameter to pass the merchant's search terms +- Results are paginated - use `first` and `after` parameters for large result sets + +## Common Workflows + +### Searching for Data + +1. Understand what the merchant is looking for +2. Use the search tool with their query +3. Present the results with relevant details (title, type, URL if available) diff --git a/admin-tools/locales/en.default.json.liquid b/admin-tools/locales/en.default.json.liquid new file mode 100644 index 00000000..4fbfab2f --- /dev/null +++ b/admin-tools/locales/en.default.json.liquid @@ -0,0 +1,4 @@ +{ + "name": "{{ name }}", + "description": "Search extension for your app" +} diff --git a/admin-tools/locales/fr.json.liquid b/admin-tools/locales/fr.json.liquid new file mode 100644 index 00000000..d280be39 --- /dev/null +++ b/admin-tools/locales/fr.json.liquid @@ -0,0 +1,4 @@ +{ + "name": "{{ name }}", + "description": "Extension de recherche pour votre application" +} diff --git a/admin-tools/package.json.liquid b/admin-tools/package.json.liquid new file mode 100644 index 00000000..8a69544c --- /dev/null +++ b/admin-tools/package.json.liquid @@ -0,0 +1,9 @@ +{ + "name": "{{ handle }}", + "private": true, + "version": "1.0.0", + "license": "UNLICENSED", + "dependencies": { + "@shopify/ui-extensions": "~2025.10.12" + } +} diff --git a/admin-tools/shopify.extension.toml.liquid b/admin-tools/shopify.extension.toml.liquid new file mode 100644 index 00000000..fa50cf28 --- /dev/null +++ b/admin-tools/shopify.extension.toml.liquid @@ -0,0 +1,15 @@ +api_version = "2025-10" + +[[extensions]] +# Change the merchant-facing name of the extension in locales/en.default.json +name = "t:name" +handle = "{{ handle }}" +type = "ui_extension" +{% if uid %}uid = "{{ uid }}"{% endif %} +description = "t:description" + +[[extensions.targeting]] +module = "./src/index.{{ srcFileExtension }}" +target = "admin.app.tools.data" +tools = "./tools.json" +instructions = "./instructions.md" diff --git a/admin-tools/src/index.liquid b/admin-tools/src/index.liquid new file mode 100644 index 00000000..2e58d9e2 --- /dev/null +++ b/admin-tools/src/index.liquid @@ -0,0 +1,17 @@ +export default async function extension() { + shopify.tools.register('search', (input) => { + const {query = '', first = 10, after} = input; + + // TODO: Implement your search logic here + + return { + results: [], + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + startCursor: null, + endCursor: null, + }, + }; + }); +} diff --git a/admin-tools/tools.json b/admin-tools/tools.json new file mode 100644 index 00000000..bc53bc86 --- /dev/null +++ b/admin-tools/tools.json @@ -0,0 +1,77 @@ +[ + { + "name": "search", + "description": "Search for data from this app's external data source", + "inputSchema": { + "type": "object", + "properties": { + "query": { + "type": "string", + "description": "Search query string" + }, + "after": { + "type": "string", + "description": "Cursor for pagination - returns elements after this cursor" + }, + "first": { + "type": "integer", + "description": "Number of results to return (default: 10)" + } + }, + "required": [] + }, + "outputSchema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the result" + }, + "type": { + "type": "string", + "description": "The type/category of the result" + }, + "url": { + "type": "string", + "description": "URL to view or edit the resource" + }, + "title": { + "type": "string", + "description": "Display title for the result" + } + }, + "required": ["id", "type"] + } + }, + "pageInfo": { + "type": "object", + "properties": { + "hasNextPage": { + "type": "boolean", + "description": "Whether there are more results available" + }, + "hasPreviousPage": { + "type": "boolean", + "description": "Whether there are previous results available" + }, + "startCursor": { + "type": "string", + "nullable": true, + "description": "Cursor for the first item in results" + }, + "endCursor": { + "type": "string", + "nullable": true, + "description": "Cursor for the last item in results" + } + } + } + } + } + } +] diff --git a/admin-tools/tsconfig.json.liquid b/admin-tools/tsconfig.json.liquid new file mode 100644 index 00000000..a5da8e40 --- /dev/null +++ b/admin-tools/tsconfig.json.liquid @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ES2020", + "checkJs": true, + "allowJs": true, + "moduleResolution": "node", + "esModuleInterop": true, + "noEmit": true + } +} diff --git a/templates.json b/templates.json index 03f0e631..03a4a247 100644 --- a/templates.json +++ b/templates.json @@ -399,6 +399,25 @@ ], "minimumCliVersion": "3.85.3" }, + { + "identifier": "app_tools", + "name": "Admin app tools", + "defaultName": "app-tools", + "group": "UI extensions", + "supportLinks": [], + "url": "https://github.com/Shopify/extensions-templates", + "type": "ui_extension", + "extensionPoints": [], + "supportedFlavors": [ + { + "name": "JavaScript", + "value": "vanilla-js", + "path": "admin-tools" + } + ], + "organizationExpFlags": ["d7c1b4ad"], + "minimumCliVersion": "3.90.0" + }, { "identifier": "admin_print_legacy", "name": "Admin print action",