how to image upload shopify app using remix and typescript. i am fresher for creating shopify app. i need upload image shopify app using remix and typescript. i have code for file upload related. when i am image upload in my custom app then image upload but when i am check backend side content in file then showing message "1.png Processing error" when debugging and check image uploaded related three step is required 1) upload 2)processing 3)ready in this step first step upload is working but second step and thired step not working. i have no idea for this related. if anyone have solution. so please tell me. i will share my code and image get error. import React, { useCallback, useEffect, useState, useRef } from "react"; import { json } from "@remix-run/node"; import { useActionData, useNavigation, useSubmit } from "@remix-run/react"; import { Page, Layout, Card, Button, BlockStack, Box, InlineStack, DropZone, LegacyStack, Thumbnail, Text, } from "@shopify/polaris"; import { authenticate } from "../shopify.server"; import type { ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/node"; export const loader = async ({ request }: LoaderFunctionArgs) => { await authenticate.admin(request); return null; }; export const action = async ({ request }: ActionFunctionArgs) => { const { admin } = await authenticate.admin(request); const color = ["Red", "Orange", "Yellow", "Green"][ Math.floor(Math.random() * 4) ]; const requestBody = await request.text(); const formData = new URLSearchParams(requestBody); const name = formData.get("filename"); const type = formData.get("filetype"); const size = formData.get("filesize"); const files = [ { name: name, type: type, size: size, }, ]; const prepareFiles = (files: { name: string | null; type: string | null; size: string | null; }[]) => files.map((file) => ({ filename: file.name, mimeType: file.type, resource: file.type?.includes("image") ? "IMAGE" : "FILE", fileSize: file.size?.toString(), httpMethod: "POST", })); const preparedFiles = prepareFiles(files); const uploadFileResponse = await admin.graphql( `#graphql mutation stagedUploadsCreate($input: [StagedUploadInput!]!) { stagedUploadsCreate(input: $input) { stagedTargets { resourceUrl url parameters { name value } } userErrors { field message } } } `, { variables: { input: preparedFiles } }, ); const uplodeFileJson = await uploadFileResponse.json(); const resourceurl = uplodeFileJson.data.stagedUploadsCreate.stagedTargets[0].resourceUrl; const fileCreateResponse = await admin.graphql( `#graphql mutation fileCreate($files: [FileCreateInput!]!) { fileCreate(files: $files) { files { alt createdAt fileStatus fileErrors { code details message } preview { image { url } status __typename } ... on GenericFile { id } ... on Video { id } } userErrors { code field message } } }`, { variables: { files: { alt: "Image", contentType: "IMAGE", originalSource: resourceurl, }, }, }, ); const fileCreateJson = await fileCreateResponse.json(); return ({ stagedUpload: uplodeFileJson, fileCreate: fileCreateJson, resourceurl: resourceurl }); }; export default function Index() { const nav = useNavigation(); const actionData = useActionData(); const submit = useSubmit(); const isLoading = ["loading", "submitting"].includes(nav.state) && nav.formMethod === "POST"; useEffect(() => { if (actionData) { shopify.toast.show("Product created"); } }, [actionData]); const [files, setFiles] = useState<File[]>([]); const inputRef = useRef<HTMLInputElement>(null); const handleDropZoneDrop = useCallback( async (dropFiles: File[], acceptedFiles: File[], rejectedFiles: File[]) => { if (acceptedFiles.length) { setFiles((prevFiles) => [...prevFiles, ...acceptedFiles]); for (const file of acceptedFiles) { console.log(file.name); console.log(file.size); console.log(file.type); } } }, [], ); const validImageTypes = ["image/gif", "image/jpeg", "image/png"]; const fileUpload = !files.length && <DropZone.FileUpload />; const uploadedFiles = files.length > 0 && ( <div style={{ padding: "0" }}> <LegacyStack vertical> {files.map((file, index) => ( <LegacyStack alignment="center" key={index}> <Thumbnail size="small" alt={file.name} source={ validImageTypes.includes(file.type) ? window.URL.createObjectURL(file) : "" } /> <div> {file.name}{" "} <Text variant="bodySm" as="p"> {file.size} bytes </Text> </div> </LegacyStack> ))} </LegacyStack> </div> ); const generateProduct = () => { const filename = files[0]?.name; const filetype = files[0]?.type; const filesize = files[0]?.size; submit({ filename, filetype, filesize }, { replace: true, method: "POST" }); }; return ( <Page> <BlockStack gap="500"> <Layout> <Layout.Section> <Card> <InlineStack gap="300"> <DropZone onDrop={handleDropZoneDrop}> {uploadedFiles} {fileUpload} </DropZone> <Button loading={isLoading} onClick={generateProduct}> Generate a product </Button> </InlineStack> </Card> </Layout.Section> </Layout> </BlockStack> </Page> ); }; I will share some screenshots when I have the image uploaded. https://prnt.sc/uIpxIW6XtgBj