{"componentChunkName":"component---src-templates-page-tsx","path":"/documentation","result":{"pageContext":{"site":{"_createdAt":"2021-04-03T15:19:10Z","_id":"siteGlobal","_rev":"d92KCXoIF3L3WkqnGhf1iD","_type":"siteGlobal","_updatedAt":"2021-04-03T16:22:50Z","content":{"_type":"globalContent","meta":{"_type":"metaCard","metaTitle":"Midway"},"socail":{"_type":"social","socialLinks":[{"_key":"8b3bf1e31f62","_type":"socialLink","icon":"twitter","url":"https://twitter.com/spaghetti_emoji"}]},"social":{"_type":"social","socialLinks":[{"_key":"dcd340745794","_type":"socialLink","icon":"twitter","url":"https://twitter.com/spaghetti_emoji"},{"_key":"09c10dd4f543","_type":"socialLink","icon":"github","url":"https://github.com/ctrl-alt-del-world/midway"}]}},"defaultMeta":{"_type":"metaCard","metaTitle":"Midway"},"social":[{"_key":"dcd340745794","_type":"socialLink","icon":"twitter","url":"https://twitter.com/spaghetti_emoji"},{"_key":"09c10dd4f543","_type":"socialLink","icon":"github","url":"https://github.com/ctrl-alt-del-world/midway"}]},"_createdAt":"2020-02-17T01:13:14Z","_id":"c4e83b99-15c8-4a78-861f-9e0e6f456e24","_rev":"SPwFZecNFXjN8cXr0A7s1F","_type":"page","_updatedAt":"2020-10-16T01:32:58Z","content":{"_type":"pageContent","main":{"_type":"pageModule","modules":[{"_key":"cb910d6357ab","_type":"standardText","text":[{"_key":"c56eb08eeac0","_type":"block","children":[{"_key":"c56eb08eeac00","_type":"span","marks":[],"text":"Introduction"}],"markDefs":[],"style":"h1"},{"_key":"e1e81ae0c945","_type":"block","children":[{"_key":"e1e81ae0c9450","_type":"span","marks":[],"text":"This Repo houses a Sanity Studio, Gatsby starter, and Shopify Implementation. Please follow the instructions below for the best "},{"_key":"c546a0296e3c","_type":"span","marks":[],"text":"experience"},{"_key":"86af9131226a","_type":"span","marks":[],"text":", this is not a vanilla starter, it has some opinions with how you should get started. If you're struggling or it's not for you, try to steal some of the studio/functions etc and repurpose things your way. "}],"markDefs":[],"style":"normal"},{"_key":"a0ac3497763c","_type":"block","children":[{"_key":"a0ac3497763c0","_type":"span","marks":[],"text":""}],"markDefs":[],"style":"normal"}]},{"_key":"aa227ffa7a6e","_type":"nestedPages","page":[{"_key":"27e9d787e3c4","_type":"pageItem","description":"A guide to up and running from scratch","linkedPage":{"_ref":"0bfffd9b-bc11-47ba-b0d1-6a63867704e1","_type":"reference"},"title":"Getting Started"}],"title":"Up and Running"},{"_key":"4fa8f09bbcad","_type":"nestedPages","page":[{"_key":"2e6aaaefa160","_type":"pageItem","description":"Our core e-commerce component, we'll set up our accounts, domain, and webhooks for syncing products.","linkedPage":{"_ref":"172cb257-9c1e-4fc8-aed6-bab09d99046c","_type":"reference"},"title":"Shopify"},{"_key":"4cd161b0d050","_type":"pageItem","description":"General configuration for our frontend and hosting solution.","linkedPage":{"_ref":"a31fc901-93a4-4790-bdaa-423bdefae484","_type":"reference"},"title":"Gatsby + Netlify"},{"_key":"a577812fe9b4","_type":"pageItem","description":"Mostly out of the box schema configurations.","linkedPage":{"_ref":"16c7fdaa-e319-469c-95d4-83cb92457878","_type":"reference"},"title":"Sanity Configuration"}],"title":"Configuration Guides"}],"slug":{"_type":"slug","current":"documentation"},"title":"Documentation"},"meta":{"_type":"metaCard","metaTitle":"Documentation | Midway"}},"meta":{"_type":"metaCard","metaTitle":"Documentation | Midway"},"modules":[{"_key":"cb910d6357ab","_type":"standardText","text":[{"_key":"c56eb08eeac0","_type":"block","children":[{"_key":"c56eb08eeac00","_type":"span","marks":[],"text":"Introduction"}],"markDefs":[],"style":"h1"},{"_key":"e1e81ae0c945","_type":"block","children":[{"_key":"e1e81ae0c9450","_type":"span","marks":[],"text":"This Repo houses a Sanity Studio, Gatsby starter, and Shopify Implementation. Please follow the instructions below for the best "},{"_key":"c546a0296e3c","_type":"span","marks":[],"text":"experience"},{"_key":"86af9131226a","_type":"span","marks":[],"text":", this is not a vanilla starter, it has some opinions with how you should get started. If you're struggling or it's not for you, try to steal some of the studio/functions etc and repurpose things your way. "}],"markDefs":[],"style":"normal"},{"_key":"a0ac3497763c","_type":"block","children":[{"_key":"a0ac3497763c0","_type":"span","marks":[],"text":""}],"markDefs":[],"style":"normal"}]},{"_key":"aa227ffa7a6e","_type":"nestedPages","page":[{"_key":"27e9d787e3c4","_type":"pageItem","description":"A guide to up and running from scratch","linkedPage":{"_createdAt":"2020-04-08T19:50:42Z","_id":"0bfffd9b-bc11-47ba-b0d1-6a63867704e1","_rev":"SPwFZecNFXjN8cXr0A7pf3","_type":"page","_updatedAt":"2020-10-16T01:29:52Z","content":{"_type":"pageContent","main":{"_type":"pageModule","modules":[{"_key":"d4eea37fe5fa","_type":"standardText","text":[{"_key":"ab777121a6eb","_type":"block","children":[{"_key":"ab777121a6eb0","_type":"span","marks":[],"text":"Getting Started"}],"markDefs":[],"style":"h1"},{"_key":"63a2598f956a","_type":"block","children":[{"_key":"63a2598f956a0","_type":"span","marks":[],"text":"This guide assumes a totally fresh start, for more "},{"_key":"40a83330beb2","_type":"span","marks":[],"text":"in-depth"},{"_key":"89a0ab7a4053","_type":"span","marks":[],"text":" information, please follow the other guides that tailor to each experience. But hopefully this should be a good start to run Sanity, and run the Frontend + get products from Shopify into your studio."}],"markDefs":[],"style":"normal"},{"_key":"2e4bd8fe91ae","_type":"block","children":[{"_key":"2e4bd8fe91ae0","_type":"span","marks":["italic"],"text":"I estimate this will take around"},{"_key":"2e4bd8fe91ae1","_type":"span","marks":["italic","strong"],"text":" ~1 hour"},{"_key":"2e4bd8fe91ae2","_type":"span","marks":["italic"],"text":" to get up and running with products syncing into your studio and rendering on the frontend."}],"markDefs":[],"style":"normal"},{"_key":"5aa079c6280b","_type":"block","children":[{"_key":"5aa079c6280b0","_type":"span","marks":[],"text":"Create a "},{"_key":"3b6943b0dde6","_type":"span","marks":["9d47cf6f9505"],"text":"template"},{"_key":"eadb63c762cc","_type":"span","marks":[],"text":" from the repo (easier than cloning it)."}],"markDefs":[{"_key":"9d47cf6f9505","_type":"link","href":"https://github.com/ctrl-alt-del-world/midway/generate"}],"style":"normal"},{"_key":"64afed05c67a","_type":"block","children":[{"_key":"64afed05c67a0","_type":"span","marks":[],"text":"Running the Studio"}],"markDefs":[],"style":"h2"},{"_key":"0a87fb0a05e8","_type":"block","children":[{"_key":"0a87fb0a05e80","_type":"span","marks":[],"text":"First we'll run the Studio as that's more straight forward. If you are new to Sanity I recommend hoping over to their "},{"_key":"0a87fb0a05e81","_type":"span","marks":["037bb958d620"],"text":"docs"},{"_key":"0a87fb0a05e82","_type":"span","marks":[],"text":" as they are extensive."}],"markDefs":[{"_key":"037bb958d620","_type":"link","href":"https://www.sanity.io/docs/getting-started"}],"style":"normal"},{"_key":"ab3e4fce7c77","_type":"block","children":[{"_key":"ab3e4fce7c770","_type":"span","marks":[],"text":"Navigate to the "},{"_key":"ab3e4fce7c771","_type":"span","marks":["tick"],"text":"/studio"},{"_key":"ab3e4fce7c772","_type":"span","marks":[],"text":" directory and "},{"_key":"ab3e4fce7c773","_type":"span","marks":["tick"],"text":"npm install"},{"_key":"ab3e4fce7c774","_type":"span","marks":[],"text":". From there you'll want to initialize a studio."}],"markDefs":[],"style":"normal"},{"_key":"0a0eae194a13","_type":"block","children":[{"_key":"0a0eae194a130","_type":"span","marks":[],"text":"Run "},{"_key":"0a0eae194a131","_type":"span","marks":["tick"],"text":"sanity init"},{"_key":"0a0eae194a132","_type":"span","marks":[],"text":" (having issues keeping my config out of sanity will update when I resolve that, this will init a new studio)"}],"markDefs":[],"style":"normal"},{"_key":"2b352be2efe0","_type":"block","children":[{"_key":"2b352be2efe00","_type":"span","marks":[],"text":"Run "},{"_key":"2b352be2efe01","_type":"span","marks":["tick"],"text":"yarn start"},{"_key":"2b352be2efe02","_type":"span","marks":[],"text":" or "},{"_key":"2b352be2efe03","_type":"span","marks":["tick"],"text":"npm start"},{"_key":"2b352be2efe04","_type":"span","marks":[],"text":"."}],"markDefs":[],"style":"normal"},{"_key":"580dfd2249bf","_type":"block","children":[{"_key":"580dfd2249bf0","_type":"span","marks":[],"text":"This will take you through the sanity setup, once completed your studio should be running locally at http://localhost:3333."}],"markDefs":[],"style":"normal"},{"_key":"bba9f577553b","_type":"block","children":[{"_key":"bba9f577553b0","_type":"span","marks":[],"text":"You'll notice an empty studio to start, I'd recommend making a Homepage with a slug: "},{"_key":"bba9f577553b1","_type":"span","marks":["tick"],"text":"home"},{"_key":"bba9f577553b2","_type":"span","marks":[],"text":". This will serve as your Index. You'll notice we don't have any products either, we're going to be syncing those directly from Shopify. We won't allow products to be created in Sanity, this pattern is in part to keep product data managed in Shopify and only extended in Sanity."}],"markDefs":[],"style":"normal"},{"_key":"796e8a4f3609","_type":"block","children":[{"_key":"796e8a4f36090","_type":"span","marks":["strong"],"text":"Deploy your studio"}],"markDefs":[],"style":"normal"},{"_key":"f4ec894309a0","_type":"block","children":[{"_key":"f4ec894309a00","_type":"span","marks":[],"text":"We'll also want to deploy the studio, simply run "},{"_key":"f4ec894309a01","_type":"span","marks":["tick"],"text":"yarn deploy"},{"_key":"f4ec894309a02","_type":"span","marks":[],"text":" in the studio root to do that. You'll want to date the project_id and dataset name and apply that to your Netlify environment variables or your .env file in the next section. (you can find the id + dataset in the sanity.json file). To get an API token you'll need to login to manage.sanity.io and create one for your project."}],"markDefs":[],"style":"normal"},{"_key":"1ada2c328c81","_type":"block","children":[{"_key":"1ada2c328c810","_type":"span","marks":[],"text":""}],"markDefs":[],"style":"normal"},{"_key":"efe4bff4d5d4","_type":"block","children":[{"_key":"efe4bff4d5d40","_type":"span","marks":[],"text":"Running the Gatsby Frontend"}],"markDefs":[],"style":"h2"},{"_key":"69fed86860ad","_type":"block","children":[{"_key":"69fed86860ad0","_type":"span","marks":[],"text":"Again this is not a `how do I use Gatsby guide` so please "},{"_key":"63007de4a2e5","_type":"span","marks":[],"text":"familiarize"},{"_key":"06f95deaa53c","_type":"span","marks":[],"text":" yourself with Gatsby before diving in. We're doing some opinionated things with the routing/context/typescript, so I apologize if this isn't for everyone but hopefully you find aspects of it portable to your future projects."}],"markDefs":[],"style":"normal"},{"_key":"5962d39394b8","_type":"block","children":[{"_key":"5962d39394b80","_type":"span","marks":[],"text":"I rely heavily on Netlify for development purposes, and that includes managing environment variables inside of Netlify. "}],"markDefs":[],"style":"normal"},{"_key":"34d61c50f5d0","_type":"block","children":[{"_key":"34d61c50f5d00","_type":"span","marks":[],"text":"You can however run this without Netlify dev (which for the Shopify sync'ing you'll need to later on)."}],"markDefs":[],"style":"normal"},{"_key":"3d4e13c5eb33","_type":"block","children":[{"_key":"3d4e13c5eb330","_type":"span","marks":[],"text":"Rename the env.example file to .env and update the sanity information with the studio you just setup."}],"markDefs":[],"style":"normal"},{"_key":"6a8a618fa799","_type":"block","children":[{"_key":"6a8a618fa7990","_type":"span","marks":[],"text":"Assuming you created a "},{"_key":"6a8a618fa7991","_type":"span","marks":["tick"],"text":"home"},{"_key":"6a8a618fa7992","_type":"span","marks":[],"text":" running "},{"_key":"6a8a618fa7993","_type":"span","marks":["tick"],"text":"gatsby develop"},{"_key":"6a8a618fa7994","_type":"span","marks":[],"text":" will run your Gatsby frontend and you should see whatever content you put into the homepage."}],"markDefs":[],"style":"normal"},{"_key":"dfb2cba5628a","_type":"block","children":[{"_key":"dfb2cba5628a0","_type":"span","marks":["italic"],"text":"The navigation is manually powered at the moment, so links to shop-all and documentation will error as they're not in your system."}],"markDefs":[],"style":"normal"},{"_key":"312a7cc23354","_type":"block","children":[{"_key":"312a7cc233540","_type":"span","marks":[],"text":"Deploy to Netlify"}],"markDefs":[],"style":"h3"},{"_key":"ed4eb0a9c730","_type":"block","children":[{"_key":"ed4eb0a9c7300","_type":"span","marks":[],"text":"We'll want our site up on Netlify, we need this in order to leverage the full power of Netlify functions. If you are comfortable handling functions on your own, you can look at the lambda directory and go from there."}],"markDefs":[],"style":"normal"},{"_key":"b5721be081fc","_type":"block","children":[{"_key":"b5721be081fc0","_type":"span","marks":[],"text":"I recommend going the github route, this is easiest as to sync the work you are doing into github sooner then later. So first get everyone on github and make sure you have a Netlify account (again not a netlify guide). Add a new site to Netlify via Git and select the repo with your studio + site. "}],"markDefs":[],"style":"normal"},{"_key":"779939e34503","_type":"block","children":[{"_key":"779939e345030","_type":"span","marks":[],"text":"Build command: "},{"_key":"779939e345031","_type":"span","marks":["tick"],"text":"npm run build"}],"markDefs":[],"style":"normal"},{"_key":"5e31447c67ba","_type":"block","children":[{"_key":"5e31447c67ba0","_type":"span","marks":[],"text":"Publish directory: "},{"_key":"5e31447c67ba1","_type":"span","marks":["tick"],"text":"web/public"}],"markDefs":[],"style":"normal"},{"_key":"2359d7a09a77","_type":"block","children":[{"_key":"2359d7a09a770","_type":"span","marks":[],"text":"You will need to set the publish directory in Netlify to "},{"_key":"2359d7a09a771","_type":"span","marks":["tick"],"text":"web"},{"_key":"2359d7a09a772","_type":"span","marks":[],"text":"."}],"markDefs":[],"style":"normal"},{"_key":"ee4cb2923921","_type":"block","children":[{"_key":"ee4cb29239210","_type":"span","marks":[],"text":"Assuming everything is up and running you should now see the local site you were running up on github and it will continue to deploy as you push to master, (we'll set Sanity deployments up later)."}],"markDefs":[],"style":"normal"},{"_key":"b7188a1c1858","_type":"block","children":[{"_key":"b7188a1c18580","_type":"span","marks":[],"text":"I recommend moving the environment variables you setup into Netlify to keep everything in one place, as you'll be running Netlify dev those creds will be pulled down locally."}],"markDefs":[],"style":"normal"},{"_key":"e9200dfd6b72","_type":"block","children":[{"_key":"e9200dfd6b720","_type":"span","marks":[],"text":"----"}],"markDefs":[],"style":"normal"},{"_key":"cdf36b832366","_type":"block","children":[{"_key":"cdf36b8323660","_type":"span","marks":[],"text":"Jump back over to your local instance, go to the web directory and ensure you are linked to the correct deployment. You can do this by running "},{"_key":"cdf36b8323661","_type":"span","marks":["tick"],"text":"netlify link"},{"_key":"cdf36b8323662","_type":"span","marks":[],"text":". "}],"markDefs":[],"style":"normal"},{"_key":"fb7e7f39947c","_type":"block","children":[{"_key":"fb7e7f39947c0","_type":"span","marks":[],"text":"We could simply run "},{"_key":"fb7e7f39947c1","_type":"span","marks":["tick"],"text":"netlify dev"},{"_key":"fb7e7f39947c2","_type":"span","marks":[],"text":" and things would start up as expected. I do however have a script for running all the required tasks if you prefer to know what you're running. Whatever works for you. (yarn run dev)."}],"markDefs":[],"style":"normal"},{"_key":"c8ac6a7e3938","_type":"block","children":[{"_key":"c8ac6a7e39380","_type":"span","marks":[],"text":"Product Sync from Shopify to Sanity"}],"markDefs":[],"style":"h2"},{"_key":"3e6bb21c6eb1","_type":"block","children":[{"_key":"3e6bb21c6eb10","_type":"span","marks":[],"text":"You'll need a Shopify dev store (or real store setup for this) and a few test products."}],"markDefs":[],"style":"normal"},{"_key":"4f1f739ae4a5","_type":"block","children":[{"_key":"4f1f739ae4a50","_type":"span","marks":[],"text":"Navigate to the Notifications section of your store:\n"},{"_key":"4f1f739ae4a51","_type":"span","marks":["tick"],"text":"yourstore.myshopify.com/admin/settings/notifications"}],"markDefs":[],"style":"normal"},{"_key":"ec6b9a31f277","_type":"block","children":[{"_key":"ec6b9a31f2770","_type":"span","marks":[],"text":"You'll want to create 3 webhooks, all pointing to your Netlify instance. Product create, update, delete. Set them to application/json type and point them to your site:\n"},{"_key":"ec6b9a31f2771","_type":"span","marks":["tick"],"text":"site.netlify.com/.netlify/functions/shopify-sync"}],"markDefs":[],"style":"normal"},{"_key":"e33a03a32873","_type":"block","children":[{"_key":"e33a03a328730","_type":"span","marks":[],"text":"You will need to have your Sanity env variables setup which you can see here "},{"_key":"e33a03a328731","_type":"span","marks":["9f87f279991f"],"text":"https://github.com/ctrl-alt-del-world/midway/blob/master/web/src/lambda/shopify-sync.ts"}],"markDefs":[{"_key":"9f87f279991f","_type":"link","href":"https://github.com/ctrl-alt-del-world/midway/blob/master/web/src/lambda/shopify-sync.ts"}],"style":"normal"},{"_key":"b219cb39ee63","_type":"block","children":[{"_key":"87cb398a8b1c","_type":"span","marks":[],"text":"Shopify webhooks are signed, the webhook as such needs to decrypt the data in order to keep from outside parties updating your studio. That SHOPIFY_SECRET comes from the webhook area at the bottom of the notifications area."}],"markDefs":[],"style":"normal"},{"_key":"be89e0968638","_type":"block","children":[{"_key":"be89e09686380","_type":"span","marks":[],"text":"If everything is set up correctly, you can navigate to a product, and update a description and save it and your product should be saved into your Sanity instance!"}],"markDefs":[],"style":"normal"},{"_key":"59d14a368ea8","_type":"block","children":[{"_key":"59d14a368ea80","_type":"span","marks":[],"text":"Advanced Configuration"}],"markDefs":[],"style":"h3"},{"_key":"bb1ef49314e1","_type":"block","children":[{"_key":"bb1ef49314e10","_type":"span","marks":[],"text":"If you need more customization of the sync, or want more control or understanding of what is going on, you can set the Shopify notifications to your local machine, this will allow you to see product sync data in the console. In order to do this you'll need a tunnel service like "},{"_key":"bb1ef49314e11","_type":"span","marks":["e575fb3a4bbf"],"text":"ngrok"},{"_key":"bb1ef49314e12","_type":"span","marks":[],"text":"."}],"markDefs":[{"_key":"e575fb3a4bbf","_type":"link","href":"https://ngrok.com/"}],"style":"normal"},{"_key":"9e4f53263467","_type":"block","children":[{"_key":"9e4f532634670","_type":"span","marks":[],"text":"Once installed you can run "},{"_key":"9e4f532634671","_type":"span","marks":["tick"],"text":"ngrok http 8000"},{"_key":"9e4f532634672","_type":"span","marks":[],"text":" on the running port of your frontend instance. This will give you a secure tunnel to direct your Shopify notification to that accesses your local machine. Keep in mind when your machine isn't running nrok the requests will fail. Shopify will remove notifications if too many requests fail (10-30? failed requests)."}],"markDefs":[],"style":"normal"},{"_key":"99727a4c59df","_type":"block","children":[{"_key":"99727a4c59df0","_type":"span","marks":[],"text":"Displaying Products on your Frontend"}],"markDefs":[],"style":"h2"},{"_key":"2d99f4eeda82","_type":"block","children":[{"_key":"2d99f4eeda820","_type":"span","marks":[],"text":"Now that we have products syncing into Sanity,"},{"_key":"e947f50dccd2","_type":"span","marks":[],"text":" our site should build product pages! In order to ensure the best experience, login to your Sanity instance and ensure your products have images associated to them. (I do not sync product images from Shopify to Sanity)."}],"markDefs":[],"style":"normal"},{"_key":"e3f8046bbf9a","_type":"block","children":[{"_key":"e3f8046bbf9a0","_type":"span","marks":[],"text":"From there you can also create a collection (in our current frontend I had a shop-all route in the header) that displays all products in a Product Grid module. You could also add a product grid module to the homepage and show products that way. You'll then be able to view products, adding products/cart "},{"_key":"282cbd0af333","_type":"span","marks":[],"text":"initialize"}],"markDefs":[],"style":"normal"},{"_key":"8e2854669e37","_type":"block","children":[{"_key":"8e2854669e370","_type":"span","marks":[],"text":"Initialize your Gatsby Cart & allow for Product add to cart"}],"markDefs":[],"style":"h2"},{"_key":"f9485a584caf","_type":"block","children":[{"_key":"f9485a584caf0","_type":"span","marks":[],"text":"We use the Shopify Buy SDK to add items and "},{"_key":"106f3a3473f8","_type":"span","marks":[],"text":"initialize"},{"_key":"cbbe552493a8","_type":"span","marks":[],"text":" the user cart. We do this with the Shopify Storefront API. If you navigate to the siteContext, you'll see where we "},{"_key":"69b32fc3f420","_type":"span","marks":[],"text":"initialize"},{"_key":"c2bbc0377886","_type":"span","marks":[],"text":" the Shopify client on line 19. "},{"_key":"f9485a584caf1","_type":"span","marks":["32528f3e3d91"],"text":"https://github.com/ctrl-alt-del-world/midway/blob/master/web/src/context/siteContext.tsx#L19"}],"markDefs":[{"_key":"32528f3e3d91","_type":"link","href":"https://github.com/ctrl-alt-del-world/midway/blob/master/web/src/context/siteContext.tsx#L19"}],"style":"normal"},{"_key":"692ccf5e3516","_type":"block","children":[{"_key":"692ccf5e35160","_type":"span","marks":[],"text":"You'll want to replace the domain and the store token. You can do this by creating a private app in Shopify and enabling the storefront API in that private app. Keep in mind the storefront token is "},{"_key":"c7c0a36b83b1","_type":"span","marks":[],"text":"public"},{"_key":"5cc18c8633ae","_type":"span","marks":[],"text":" (hence why I don't mind mine being in the repo)."}],"markDefs":[],"style":"normal"},{"_key":"49fc56c24660","_type":"block","children":[{"_key":"49fc56c246600","_type":"span","marks":[],"text":"If you follow along in the siteContext file you'll see we're "},{"_key":"281c35f41376","_type":"span","marks":[],"text":"initializing"},{"_key":"c61d33c702c6","_type":"span","marks":[],"text":" carts as well as enabling functionality like fetching cart total, adding and removing items, and opening and closing the cart in state."}],"markDefs":[],"style":"normal"},{"_key":"0ee3d4a23432","_type":"block","children":[{"_key":"0ee3d4a234320","_type":"span","marks":[],"text":""}],"markDefs":[],"style":"normal"},{"_key":"3c26ecf6d22d","_type":"block","children":[{"_key":"3c26ecf6d22d0","_type":"span","marks":[],"text":"You should now have everything you need to use/start your headless ecom experience. I talk more about the Shopify accounts in the Shopify guide."}],"markDefs":[],"style":"normal"},{"_key":"e8755414d976","_type":"block","children":[{"_key":"e8755414d9760","_type":"span","marks":[],"text":""}],"markDefs":[],"style":"normal"},{"_key":"09732d7466fd","_type":"block","children":[{"_key":"09732d7466fd0","_type":"span","marks":[],"text":"Site rebuilds via Sanity"}],"markDefs":[],"style":"h3"},{"_key":"8e37e984767b","_type":"block","children":[{"_key":"8e37e984767b0","_type":"span","marks":[],"text":"You can also trigger site rebuilds with Sanity saves, you can do this with Netlify build hooks. You can create a build hook and in your Sanity API settings "}],"markDefs":[],"style":"normal"},{"_key":"3e5a9c94655e","_type":"block","children":[{"_key":"3e5a9c94655e0","_type":"span","marks":[],"text":""}],"markDefs":[],"style":"normal"},{"_key":"cfb65373ddcd","_type":"block","children":[{"_key":"cfb65373ddcd0","_type":"span","marks":[],"text":""}],"markDefs":[],"style":"normal"}]}],"slug":{"_type":"slug","current":"getting-started"},"title":"Getting Started"},"meta":{"_type":"metaCard","metaTitle":"Getting Started with Midway"}}},"title":"Getting Started"}],"title":"Up and Running"},{"_key":"4fa8f09bbcad","_type":"nestedPages","page":[{"_key":"2e6aaaefa160","_type":"pageItem","description":"Our core e-commerce component, we'll set up our accounts, domain, and webhooks for syncing products.","linkedPage":{"_createdAt":"2020-03-31T02:48:47Z","_id":"172cb257-9c1e-4fc8-aed6-bab09d99046c","_rev":"RVi0KmyCmyl0NVQLZseS7T","_type":"page","_updatedAt":"2020-11-28T04:34:24Z","content":{"_type":"pageContent","main":{"_type":"pageModule","modules":[{"_key":"1e9413eb63f6","_type":"standardText","text":[{"_key":"2b6c844c9dc9","_type":"block","children":[{"_key":"2b6c844c9dc90","_type":"span","marks":[],"text":"Shopify Configuration"}],"markDefs":[],"style":"h1"},{"_key":"d0fa22788028","_type":"block","children":[{"_key":"d0fa227880280","_type":"span","marks":[],"text":"We use Shopify to handle commerce things like: products, inventory, customers, checkout, taxes etc... For the sake of our headless experience we have need of some specific configurations. In the Midway repository we only include a single file for Shopify, the "},{"_key":"d0fa227880281","_type":"span","marks":["tick"],"text":"theme.liquid"},{"_key":"d0fa227880282","_type":"span","marks":[],"text":". The reasoning for this is because we need to set up redirects from the Shopify experience."}],"markDefs":[],"style":"normal"},{"_key":"ae2e2dde8167","_type":"block","children":[{"_key":"ae2e2dde81670","_type":"span","marks":[],"text":"Handling Shopify Customers"}],"markDefs":[],"style":"h3"},{"_key":"c4cdec6b1b51","_type":"block","children":[{"_key":"c4cdec6b1b510","_type":"span","marks":[],"text":"In order to enable accounts in our headless experience we need to redirect the default Shopify account functionality to our headless site. This is because we can't control the routing of the account activation, reset, or password resets from a Shopify environment. At the time of writing this we still need to implement this redirect hack to allow our headless environment to be fully functional. This is because the emails that go out from inside a Shopify experience are have an integrated URL that points to the integrated default domain in your Shopify configuration. We recommend that the Shopify checkout/experience live in a nested subdomain of your main site, for example: checkout.sitename.com. This will allow for a more seamless customer experience, instead of "},{"_key":"b8e4ee7f6806","_type":"span","marks":[],"text":"something"},{"_key":"6cca1dec9dc5","_type":"span","marks":[],"text":" like mysite-experience.myshopify.com being your checkout url. "}],"markDefs":[],"style":"normal"},{"_key":"870e99109c13","_type":"block","children":[{"_key":"870e99109c130","_type":"span","marks":["strong"],"text":"Steps to configuring Shopify store for headless accounts:"}],"markDefs":[],"style":"normal"},{"_key":"9755f50fa05b","_type":"block","children":[{"_key":"9755f50fa05b0","_type":"span","marks":[],"text":"Create a subdomain route for the store and make it your default domain."}],"level":1,"listItem":"number","markDefs":[],"style":"normal"},{"_key":"0fe5ddbea3e8","_type":"block","children":[{"_key":"0fe5ddbea3e80","_type":"span","marks":[],"text":"Ensure the Shopify client in your codebase talks to the sudomain route so your cart weburl is the subdomain route."}],"level":1,"listItem":"number","markDefs":[],"style":"normal"},{"_key":"0b1a9ec0d859","_type":"block","children":[{"_key":"0b1a9ec0d8590","_type":"span","marks":[],"text":"Update your theme.liquid with a redirect script listed below."}],"level":1,"listItem":"number","markDefs":[],"style":"normal"},{"_key":"70b8335b3561","_type":"block","children":[{"_key":"70b8335b35610","_type":"span","marks":[],"text":"Create an "},{"_key":"70b8335b35611","_type":"span","marks":["tick"],"text":"account/"},{"_key":"70b8335b35612","_type":"span","marks":[],"text":" route in your "},{"_key":"717b4d5341ae","_type":"span","marks":[],"text":"experience"},{"_key":"a7382556415b","_type":"span","marks":[],"text":" (you can find all the account related components in Midway in the "},{"_key":"70b8335b35613","_type":"span","marks":["tick"],"text":"auth/"},{"_key":"70b8335b35614","_type":"span","marks":[],"text":" directory inside the components."}],"level":1,"markDefs":[],"style":"normal"},{"_key":"8e762c213bd1","_type":"block","children":[{"_key":"8e762c213bd10","_type":"span","marks":[],"text":"Place the following code at the top of your "},{"_key":"8e762c213bd11","_type":"span","marks":["tick"],"text":"theme.liquid"},{"_key":"8e762c213bd12","_type":"span","marks":[],"text":" file:"}],"markDefs":[],"style":"normal"},{"_key":"e5a419ecf083","_type":"block","children":[{"_key":"e5a419ecf0830","_type":"span","marks":["code"],"text":"<script>\n  var l = window.location\n\n  if (/^\\/a\\//.test(l.pathname)) {\n    // do nothing\n  } else {\n    var href = 'midway-starter.netlify.com'\n    if (l.pathname) href += '/' + l.pathname\n    if (l.has) href += l.hash\n    if (l.search) href += l.search\n\n    href = href.replace('//', '/')\n    window.top.location.href = 'https://' + href\n  }\n</script>"}],"markDefs":[],"style":"normal"},{"_key":"c9bf1062a10e","_type":"block","children":[{"_key":"c9bf1062a10e0","_type":"span","marks":[],"text":"Understanding Accounts in Headless"}],"markDefs":[],"style":"h3"},{"_key":"cbec9b7dce12","_type":"block","children":[{"_key":"cbec9b7dce120","_type":"span","marks":[],"text":"You will also need to make sure accounts are enabled on your Shopify instance. They should not be required, but optional. This will allow people to register/activate accounts."}],"markDefs":[],"style":"normal"},{"_key":"81cc5411acbc","_type":"block","children":[{"_key":"81cc5411acbc0","_type":"span","marks":[],"text":"In the Gatsby instance, assuming everything is setup, you should be able to create an account in the Shopify instance. From there everything else is business as usual. However customers going through a more traditional flow, like making a purchase and having an account created that way you'll need to follow some additional steps. "}],"markDefs":[],"style":"normal"},{"_key":"68df2bf65c2e","_type":"block","children":[{"_key":"68df2bf65c2e0","_type":"span","marks":[],"text":"Shopify does not necessarily automatically send out invite emails for accounts created in headless environments. As a result you will need to use a Bulk invite plugin. These plugins let you set up intervals for inviting users into the system. Once that email comes from Shopify the customer will be directed to the Shopify instance with an activate route. This route will redirect to your experience with the redirect you set up above. From there they can enter in a password and create their account."}],"markDefs":[],"style":"normal"},{"_key":"2a43da4948ca","_type":"block","children":[{"_key":"2a43da4948ca0","_type":"span","marks":[],"text":"Shopify Product Sync"}],"markDefs":[],"style":"h2"},{"_key":"5f547ec9685d","_type":"block","children":[{"_key":"5f547ec9685d0","_type":"span","marks":[],"text":"We also need to get our products into Sanity. While this isn't a 100% required it's one of the underlying reasons for using Sanity as a CMS in combination with your Shopify experience. We'll connect the Shopify products directly into Sanity so that we can extend them, add modules, customize variants, etc. The applications to extending your shopping experience start with syncing the basic Shopify product structure into Sanity. "}],"markDefs":[],"style":"normal"},{"_key":"7a369ef41f07","_type":"block","children":[{"_key":"7a369ef41f070","_type":"span","marks":[],"text":"Given our current example, we'll be using Netlify Functions. For anyone rolling your own the only thing you will need to do is change the route you are pointing the sync to."}],"markDefs":[],"style":"normal"},{"_key":"1537400fba7d","_type":"block","children":[{"_key":"1537400fba7d0","_type":"span","marks":[],"text":"I will only cover loosely what is going on here, please find the entire "},{"_key":"1537400fba7d1","_type":"span","marks":["tick"],"text":"shopify-sync.tx"},{"_key":"1537400fba7d2","_type":"span","marks":[],"text":" file "},{"_key":"1537400fba7d3","_type":"span","marks":["9b4128da3444"],"text":"here"},{"_key":"1537400fba7d4","_type":"span","marks":[],"text":". This file lives in our functions directory in our Netlify instance. You'll notice this function is actually a capture, we put it at the end of a webhook to accept data, and then transport it into our Sanity instance. We're fetching our environment "},{"_key":"7e051100595c","_type":"span","marks":[],"text":"variables"},{"_key":"c4655dd6e3d8","_type":"span","marks":[],"text":" specifically from Netlify running "},{"_key":"1537400fba7d5","_type":"span","marks":["tick"],"text":"netlify dev"},{"_key":"1537400fba7d6","_type":"span","marks":[],"text":". We are parsing the product and saving it to a Product type that we have "},{"_key":"aea673baa867","_type":"span","marks":[],"text":"configured"},{"_key":"1c6ffa24c115","_type":"span","marks":[],"text":" in Sanity. We are then checking for nested variants and saving that to a Product Variant type in Sanity. We do this for a number of reason, allowing us to extend variant specific data, ability to associate variants to other products (like bundles), or simply allowing us to create variant cards on the frontend for direct quick adds. "}],"markDefs":[{"_key":"9b4128da3444","_type":"link","href":"https://github.com/ctrl-alt-del-world/midway/blob/master/web/src/lambda/shopify-sync.ts"}],"style":"normal"},{"_key":"78adcedc0bb8","_type":"block","children":[{"_key":"78adcedc0bb80","_type":"span","marks":["strong"],"text":"Configuring your Webhooks to talk to Sanity"}],"markDefs":[],"style":"normal"},{"_key":"1c636f00e6ec","_type":"block","children":[{"_key":"1c636f00e6ec0","_type":"span","marks":[],"text":"Assuming you have no questions about the actual Sync file, we'll need to configure Shopify to actually push data into Sanity. "}],"markDefs":[],"style":"normal"},{"_key":"fe0177b4c3ca","_type":"block","children":[{"_key":"fe0177b4c3ca0","_type":"span","marks":[],"text":"In Shopify navigate to the following area:"}],"markDefs":[],"style":"normal"},{"_key":"d884a24e3c61","_type":"block","children":[{"_key":"d884a24e3c610","_type":"span","marks":["tick"],"text":"Settings->Notifications->Webhooks"}],"markDefs":[],"style":"normal"},{"_key":"d545e971b608","_type":"block","children":[{"_key":"d545e971b6080","_type":"span","marks":[],"text":"You'll see you have the ability to create webhooks, we're going to want to create 3 webhooks: Product creation, Product update, & Product delete. Set the format to JSON, and then specify the URL pointing to the above Shopify sync file. For anyone more experienced you can also point it to an ngrok on your local machine for faster debugging/testing. In the case of our working example my url route is:"}],"markDefs":[],"style":"normal"},{"_key":"ee9732c34c2a","_type":"block","children":[{"_key":"ee9732c34c2a0","_type":"span","marks":["tick"],"text":"https://midway-starter.netlify.com/.netlify/functions/shopify-sync"}],"markDefs":[],"style":"normal"},{"_key":"fb2dd0f016bc","_type":"block","children":[{"_key":"fb2dd0f016bc0","_type":"span","marks":[],"text":"If you are running locally you should be able to see data logging in your console. Additionally saving a product in your Shopify if configured correctly should save a product into your Sanity instance."}],"markDefs":[],"style":"normal"},{"_key":"c0a865f95b29","_type":"block","children":[{"_key":"c0a865f95b290","_type":"span","marks":[],"text":"From there you'll want to ensure your Shopify Products have the following:"}],"markDefs":[],"style":"normal"},{"_key":"b0abd4949ac5","_type":"block","children":[{"_key":"b0abd4949ac50","_type":"span","marks":[],"text":"Sku"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"5eb080f40079","_type":"block","children":[{"_key":"5eb080f400790","_type":"span","marks":[],"text":"Variants"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"faa026f07391","_type":"block","children":[{"_key":"faa026f073910","_type":"span","marks":[],"text":"Inventory"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"cbd9e6db8b64","_type":"block","children":[{"_key":"cbd9e6db8b640","_type":"span","marks":[],"text":"Pricing"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"24f18ca53517","_type":"block","children":[{"_key":"24f18ca535170","_type":"span","marks":[],"text":"Images associated to every Variant (for building our cart object, emails)"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"568674f0e3f9","_type":"block","children":[{"_key":"568674f0e3f90","_type":"span","marks":[],"text":""}],"markDefs":[],"style":"normal"}]}],"slug":{"_type":"slug","current":"shopify"},"title":"Shopify"},"meta":{"_type":"metaCard","metaTitle":"Shopify Configuration | Midway"}}},"title":"Shopify"},{"_key":"4cd161b0d050","_type":"pageItem","description":"General configuration for our frontend and hosting solution.","linkedPage":{"_createdAt":"2020-03-31T16:46:20Z","_id":"a31fc901-93a4-4790-bdaa-423bdefae484","_rev":"IJlYCsRLc2NxvQB7dt9s1l","_type":"page","_updatedAt":"2020-11-28T04:37:20Z","content":{"_type":"pageContent","main":{"_type":"pageModule","modules":[{"_key":"7218132f773b","_type":"standardText","text":[{"_key":"dbb2a9ddab46","_type":"block","children":[{"_key":"dbb2a9ddab460","_type":"span","marks":[],"text":"Gatsby + Netlify Configuration"}],"markDefs":[],"style":"h1"},{"_key":"aa94f29a5bdf","_type":"block","children":[{"_key":"aa94f29a5bdf0","_type":"span","marks":[],"text":"The core of this application is the Gatsby environment. We tie together the Sanity and Shopify aspects in our "},{"_key":"aa94f29a5bdf1","_type":"span","marks":["tick"],"text":"web/"},{"_key":"aa94f29a5bdf2","_type":"span","marks":[],"text":" directory. We're using Netlify functions to handle the Shopify accounts as well as running our Shopify Sync function that injects data from Shopify into our Sanity instance. "}],"markDefs":[],"style":"normal"},{"_key":"746e7d71c96f","_type":"block","children":[{"_key":"746e7d71c96f0","_type":"span","marks":[],"text":"If you choose to not use Netlify you'll need to configure something yourself or using your own comparable method. The core of this application runs on "},{"_key":"746e7d71c96f1","_type":"span","marks":["tick"],"text":"netlify dev"},{"_key":"746e7d71c96f2","_type":"span","marks":[],"text":" enabling us to use Netlify environment "},{"_key":"e7b6ca6265bf","_type":"span","marks":[],"text":"variables"},{"_key":"172605586d5e","_type":"span","marks":[],"text":". In order to get up and running you need to set the following variables up in your netlify instance:"}],"markDefs":[],"style":"normal"},{"_key":"bc249f179fdb","_type":"block","children":[{"_key":"bc249f179fdb0","_type":"span","marks":[],"text":"SANITY_API_TOKEN"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"b3e8471971cb","_type":"block","children":[{"_key":"b3e8471971cb0","_type":"span","marks":[],"text":"SANITY_DATASET"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"65cbad48344c","_type":"block","children":[{"_key":"65cbad48344c0","_type":"span","marks":[],"text":"SANITY_PROJECT_ID"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"23130e5274fd","_type":"block","children":[{"_key":"23130e5274fd0","_type":"span","marks":[],"text":"SHOPIFY_GRAPHQL_URL"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"87523bbf2baf","_type":"block","children":[{"_key":"87523bbf2baf0","_type":"span","marks":[],"text":"SHOPIFY_TOKEN"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"7a54d34fcc3c","_type":"block","children":[{"_key":"025183569572","_type":"span","marks":[],"text":"SHOPIFY_API_KEY"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"a356505aa3ea","_type":"block","children":[{"_key":"c4a2e39d0ec4","_type":"span","marks":[],"text":"SHOPIFY_API_PASSWORD"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"927693e03d7c","_type":"block","children":[{"_key":"927693e03d7c0","_type":"span","marks":[],"text":"For those of you not familiar with the Shopify aspect, you'll need to create a "},{"_key":"927693e03d7c1","_type":"span","marks":["cd04205739cd"],"text":"private app"},{"_key":"927693e03d7c2","_type":"span","marks":[],"text":" in your Shopify backend. "}],"markDefs":[{"_key":"cd04205739cd","_type":"link","href":"https://help.shopify.com/en/manual/apps/private-apps"}],"style":"normal"},{"_key":"02bfb94287d4","_type":"block","children":[{"_key":"02bfb94287d40","_type":"span","marks":[],"text":"Running Netlify Functions locally"}],"markDefs":[],"style":"h3"},{"_key":"bd26677bd1a5","_type":"block","children":[{"_key":"bd26677bd1a50","_type":"span","marks":[],"text":"We use a proxy in our "},{"_key":"bd26677bd1a51","_type":"span","marks":["tick"],"text":"gatsby-config"},{"_key":"bd26677bd1a52","_type":"span","marks":[],"text":" that allows us to run our lambda functions locally via "},{"_key":"bd26677bd1a53","_type":"span","marks":["tick"],"text":"netlify dev"},{"_key":"bd26677bd1a54","_type":"span","marks":[],"text":". This allows us to set up webhooks (in the Shopify guide example) that can talk to our local machine. I recommend doing this with ngrok:"}],"markDefs":[],"style":"normal"},{"_key":"6f9062cad37d","_type":"block","children":[{"_key":"6f9062cad37d0","_type":"span","marks":[],"text":"npm install ngrok -g"}],"level":1,"listItem":"number","markDefs":[],"style":"normal"},{"_key":"f9179094fbe0","_type":"block","children":[{"_key":"f9179094fbe00","_type":"span","marks":[],"text":"ngrok [:PORT] http"}],"level":1,"listItem":"number","markDefs":[],"style":"normal"},{"_key":"14ea27ebdc68","_type":"block","children":[{"_key":"14ea27ebdc680","_type":"span","marks":[],"text":"Point Shopify webhook to the above url + /.netlify/functions/shopify-sync"}],"level":1,"listItem":"number","markDefs":[],"style":"normal"},{"_key":"93730ba8b620","_type":"block","children":[{"_key":"93730ba8b6200","_type":"span","marks":[],"text":"Gatsby + Typescript"}],"markDefs":[],"style":"h3"},{"_key":"59fe49dc59f7","_type":"block","children":[{"_key":"59fe49dc59f70","_type":"span","marks":[],"text":"Our Gatsby environment is Typed, for anyone not familiar with this I recommend reading up on Typescript, it essentially calls for knowing/handling data in a way that prevents as many breaking changes, and makes our code easier to read and less prone to breaking. "}],"markDefs":[],"style":"normal"},{"_key":"1fec9bcd379d","_type":"block","children":[{"_key":"1fec9bcd379d0","_type":"span","marks":[],"text":"Theming + Magic Tricks"}],"markDefs":[],"style":"h3"},{"_key":"5b46119cdbf1","_type":"block","children":[{"_key":"5b46119cdbf12","_type":"span","marks":[],"text":"We include a SASS library called magic-tricks in the base theme, this is something with utility classing + basic grid support for flex, inline, and css grid. Totally optional and should be easy enough to remove. The repo also has POSTCSS support which is what it was originally built with."}],"markDefs":[],"style":"normal"}]}],"slug":{"_type":"slug","current":"gatsby-netlify"},"title":"Gatsby + Netlify"},"meta":{"_type":"metaCard","metaTitle":"Gatsby + Netlify Configuration | Midway"}}},"title":"Gatsby + Netlify"},{"_key":"a577812fe9b4","_type":"pageItem","description":"Mostly out of the box schema configurations.","linkedPage":{"_createdAt":"2020-03-31T17:03:42Z","_id":"16c7fdaa-e319-469c-95d4-83cb92457878","_rev":"lmX14ZJjgL5VG9gaMTSt2s","_type":"page","_updatedAt":"2020-10-16T01:34:33Z","content":{"_type":"pageContent","main":{"_type":"pageModule","modules":[{"_key":"e8a7dc833399","_type":"standardText","text":[{"_key":"4352b82b235e","_type":"block","children":[{"_key":"4352b82b235e0","_type":"span","marks":[],"text":"Sanity Configuration"}],"markDefs":[],"style":"h1"},{"_key":"4278c496dbad","_type":"block","children":[{"_key":"4278c496dbad0","_type":"span","marks":[],"text":"Our Sanity instance needs little introduction, out of the box it's set up to deploy to graphQL, has support for pages, products, and product variants. "}],"markDefs":[],"style":"normal"},{"_key":"ad7d65fa4e90","_type":"block","children":[{"_key":"ad7d65fa4e900","_type":"span","marks":[],"text":"I also add some global configuration objects for the sake of showcasing some of the "},{"_key":"c7b513c8ec1f","_type":"span","marks":[],"text":"extendability"},{"_key":"ff67471e635d","_type":"span","marks":[],"text":" of the system. We're also using the Tabs plugin which allows us to organize our Studio experience. I wanted to have the ability to put common repeatable elements like our Meta information into a tabbed experience. "}],"markDefs":[],"style":"normal"},{"_key":"6e0592d6e9d7","_type":"block","children":[{"_key":"6e0592d6e9d70","_type":"span","marks":["italic"],"text":"I will be rolling in additional features to the Sanity experience like: Panes, Previews, and potentially Google Analytics support of some kind."}],"markDefs":[],"style":"normal"}]}],"slug":{"_type":"slug","current":"sanity-configuration"},"title":"Sanity Configuration"},"meta":{"_type":"metaCard","metaTitle":"Sanity Configuration | Midway"}}},"title":"Sanity Configuration"}],"title":"Configuration Guides"}],"slug":"documentation","title":"Documentation"}},"staticQueryHashes":[]}