<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Naoya Kumasegawa</title>
    <description>The latest articles on Forem by Naoya Kumasegawa (@momonoki1990).</description>
    <link>https://forem.com/momonoki1990</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F688109%2F72e7460e-a4d0-46e4-b405-5ac83ba9852d.JPG</url>
      <title>Forem: Naoya Kumasegawa</title>
      <link>https://forem.com/momonoki1990</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/momonoki1990"/>
    <language>en</language>
    <item>
      <title>[Python]Built Todo App with FastAPI 😃</title>
      <dc:creator>Naoya Kumasegawa</dc:creator>
      <pubDate>Tue, 21 Dec 2021 21:49:21 +0000</pubDate>
      <link>https://forem.com/momonoki1990/pythonbuilt-todo-app-with-fastapi-15a7</link>
      <guid>https://forem.com/momonoki1990/pythonbuilt-todo-app-with-fastapi-15a7</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhr06mtdpth42lxe4v2rk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhr06mtdpth42lxe4v2rk.png" alt="todo app front view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the title says, I tried to create a TODO list with FastAPI.&lt;/p&gt;

&lt;p&gt;Originally, I heard that FastAPI's automatic document　generation feature is good, and I was interested in it.&lt;/p&gt;

&lt;p&gt;[Backend]&lt;br&gt;
&lt;a href="https://github.com/momonoki1990/fastapi-todo-list-api" rel="noopener noreferrer"&gt;https://github.com/momonoki1990/fastapi-todo-list-api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[Frontend]&lt;br&gt;
&lt;a href="https://github.com/momonoki1990/fastapi-todo-list-frontend" rel="noopener noreferrer"&gt;https://github.com/momonoki1990/fastapi-todo-list-frontend&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I didn't really need it because I just wanted to try out FastAPI, but I made a front-end for it as well.&lt;br&gt;
I think it's more exciting to have a front-end as well.&lt;/p&gt;

&lt;p&gt;※(2022/01/06)I added user register and login function to the backend, but the frontend did not follow those new functions, so the frontend barely works now 😢&lt;/p&gt;
&lt;h2&gt;
  
  
  Automatic interactive API documentation
&lt;/h2&gt;

&lt;p&gt;If you start the server and go to &lt;code&gt;/docs&lt;/code&gt;, you can access the API documentation.&lt;br&gt;
You can see a list of request and response formats for each resource, and by clicking the "Try it out" button, you can actually execute the request.&lt;/p&gt;

&lt;p&gt;The generation of this document itself is done by simply describing the API routing in a formatted manner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@router.get("", response_model=List[task_schema.TaskResponse])
async def list_tasks(db: AsyncSession = Depends(get_db)):
    return await task_crud.get_tasks(db)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, in the above code, the type of the response body is set by setting &lt;code&gt;response_model=List[task_schema.TaskResponse]&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from pydantic import BaseModel, Field

class TaskResponse(TaskBase):
    id: int = Field(..., gt=0, example=1)
    done: bool = Field(False, description="done task or not")

    class Config:
        orm_mode = True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;task_schema.TaskResponse&lt;/code&gt; is a class that inherits from Pydantic's BaseModel and sets python type hints in its member variables.&lt;br&gt;
It also allows you to add validation and parameter descriptions to an instance called Filed, which will be reflected in the documentation.&lt;/p&gt;

&lt;p&gt;If you set &lt;code&gt;orm_mode = True&lt;/code&gt;, the ORM (SQLAlchemy in this case) model object will be converted to Pydantic response object.&lt;br&gt;
If you do not set it, you will get a validation error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm50zqkeq12j651urww4i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm50zqkeq12j651urww4i.png" alt="response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz4e2wvnppe1tl5cy6wqe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz4e2wvnppe1tl5cy6wqe.png" alt="schema"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was the first time for me to create an API in Python, but I was pleasantly surprised at how intuitive it was to write, how detailed validation could be set by simply passing values as keyword arguments, and how the documentation was automatically generated.&lt;/p&gt;
&lt;h2&gt;
  
  
  SQLAlchemy
&lt;/h2&gt;

&lt;p&gt;I tried to use SQLAlchemy as an ORM this time, but at first I didn't know what to read in the official documentation...&lt;/p&gt;

&lt;p&gt;To begin with, are there two types of SQLAlchemy ORM and SQL Alchemy Core, and does the latter write down SQL directly?&lt;/p&gt;

&lt;p&gt;In the tutorial, ORM and Core are written mixed together, and at first I didn't know which one was which. Moreover, the way to write queries in ORM seems to have 2.0 style and 1.x style, and I didn't know which one was which.&lt;/p&gt;

&lt;p&gt;However, once I realized that there are ORM and Core, 1.4 style and 2.0 style, and that I can write 2.0 style queries by setting &lt;code&gt;future=True&lt;/code&gt; in 1.4, I knew where to look in the documentation. I also understood that &lt;code&gt;engine&lt;/code&gt; is a setting passed to the DB, and &lt;code&gt;session&lt;/code&gt; is a setting that holds the &lt;code&gt;engine&lt;/code&gt; setting.&lt;/p&gt;

&lt;p&gt;About driver for async process, it seems that aiomysql has stopped being updated and asyncmy is recommended.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhwsrc4m2jt6bf2k1e5vj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhwsrc4m2jt6bf2k1e5vj.png" alt="Warning on aiomysql"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbrmsb0vikd81jc6trnl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbrmsb0vikd81jc6trnl.png" alt="asyncmy is recommended"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(At the bottom of the &lt;a href="https://docs.sqlalchemy.org/en/14/" rel="noopener noreferrer"&gt;top page for each version&lt;/a&gt;, there is Dialect Documentation, which describes the settings and drivers for each DB.)&lt;/p&gt;
&lt;h2&gt;
  
  
  Poetry, black, tox, DB container as test environment
&lt;/h2&gt;

&lt;p&gt;I used the package manager Poery and a formatter called black.&lt;/p&gt;

&lt;p&gt;Since the default package manager in tox, a test management tool, is the standard python pip, I set the &lt;code&gt;install_command&lt;/code&gt; to install the dependent libraries for each test environment using poetry, as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[tox]
skipsdist = true
envlist = flake8, py310
install_command = poetry install -D {packages}

[testenv]
deps = pytest
allowlist_externals = poetry
commands =
    poetry install
    poetry run pytest tests/

[testenv:flake8]
deps = flake8
commands =
    poetry run flake8 src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like black because it needs no settings.&lt;br&gt;
(max-line-length: 88 is too short?)&lt;/p&gt;

&lt;p&gt;Although it is not related to the Python development tools above, I used a Docker container for the test environment DB.&lt;/p&gt;

&lt;p&gt;(It's almost the same as the DB container for development, except that it's not persisted in volume.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db-test:
    image: mysql:8.0
    environment:
      MYSQL_DATABASE: "todo"
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
      TZ: "Asia/Tokyo"
    volumes:
      - ./my.conf:/etc/mysql/conf.d/my.cnf
    ports:
      - 33050:3306
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  By the way, about frontend(Vite, Chakra UI)
&lt;/h2&gt;

&lt;p&gt;I used a setup tool called &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; because I heard it was faster and better than create-react-app. I do think it was faster until the template was created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/keefdrive/create-react-app-vs-vite-2amn"&gt;Create react app vs Vite&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I heard that you can write CSS like Tailwind, and I was curious about it, so I gave it a try.&lt;br&gt;
Like the following &lt;code&gt;gridGap&lt;/code&gt; and &lt;code&gt;py&lt;/code&gt;(padding-top,bottom), it seems to be possible to write all CSS as React props, and I personally like it because it seems to be intuitive and I don't have to worry about class names like Tailwind CSS.&lt;br&gt;
I also found &lt;code&gt;VStack&lt;/code&gt; &lt;code&gt;HStack&lt;/code&gt; for creating horizontal and vertical flex containers useful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="App"&amp;gt;
      &amp;lt;Container&amp;gt;
        &amp;lt;VStack gridGap="8" py="16"&amp;gt;
          &amp;lt;Heading as="h1" size="4xl"&amp;gt;
            My Todo List
          &amp;lt;/Heading&amp;gt;
          &amp;lt;InputForm tasks={tasks} setTasks={setTasks} /&amp;gt;
          &amp;lt;List tasks={tasks} setTasks={setTasks} /&amp;gt;
        &amp;lt;/VStack&amp;gt;
      &amp;lt;/Container&amp;gt;
    &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>fastapi</category>
      <category>react</category>
      <category>chakraui</category>
    </item>
    <item>
      <title>Built a Shopify store with Next.js 😁</title>
      <dc:creator>Naoya Kumasegawa</dc:creator>
      <pubDate>Tue, 17 Aug 2021 22:03:42 +0000</pubDate>
      <link>https://forem.com/momonoki1990/built-a-shopify-store-with-next-js-38c4</link>
      <guid>https://forem.com/momonoki1990/built-a-shopify-store-with-next-js-38c4</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokcnppc0hrxy2v3wpekv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokcnppc0hrxy2v3wpekv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've built a Shopify storefront with Next.js.&lt;br&gt;
I've been using Shopify for work for a while now, and I was interested in Next.js because it supports various rendering methods such as SSR, SSG and ISR, so I decided to combine the two and build a store.&lt;br&gt;
The design is based on Shopify's default Debut theme (which is now Dawn).&lt;/p&gt;

&lt;h3&gt;
  
  
  Technology used, etc.
&lt;/h3&gt;

&lt;p&gt;Store: &lt;a href="https://nextjs-shopify-store.vercel.app" rel="noopener noreferrer"&gt;https://nextjs-shopify-store.vercel.app&lt;/a&gt;&lt;br&gt;
Repository: &lt;a href="https://github.com/naoya-kuma1990/nextjs-shopify-store" rel="noopener noreferrer"&gt;https://github.com/naoya-kuma1990/nextjs-shopify-store&lt;/a&gt;&lt;br&gt;
Technologies used: React, Next.js, TypeScript, Tailwind CSS, Material UI, Shopify JavaScript Buy SDK, Store Front API (Graph QL)&lt;br&gt;
Implemented pages: Collection (product list), product details, cart, search results&lt;/p&gt;

&lt;h3&gt;
  
  
  Rate Limit for Next.js and Store Front API
&lt;/h3&gt;

&lt;p&gt;As I mentioned at the beginning of this article, Next.js is a React framework that supports SSR and ISR. I used it this time because I thought that "when it comes to e-commerce sites, it's natural to support SEO, and if you want to achieve that with React, Next.js is the way to go". However, as it turns out, the site I made this time fails SEO because all the major information fetching, such as product information fetching, are performed on the client side lol.&lt;br&gt;
This is because there is a cost limit called "&lt;a href="https://shopify.dev/api/usage/rate-limits" rel="noopener noreferrer"&gt;API Rate Limits&lt;/a&gt;" on access to Shopify's API, and access is restricted depending on the type of API. You can read more about it in the official website, but basically, each store (strictly speaking, the private app that is the access point) has a set number of points, and if the points are consumed, the request will become an error until the points are recovered.&lt;br&gt;
Therefore, the two Admin APIs (REST and GraphQL) can quickly become too costly to run every time a large number of users access the site, so there is Store Front API . Unlike the Admin API, this one is limited by IP. As a result, the Store Front API does not incur any cost overruns, as long as a certain amount of information is hit from the client side.&lt;br&gt;
For these reasons, SSR is not the first choice for building a store front using Shopify's API, as SSR would mean hitting the API for every user access, which would quickly lead to cost overruns no matter which API you use.&lt;br&gt;
The options are to use an ISR to hit the API at regular intervals and render it as a static page, or to use a CSR to hit the Store Front API each time. This time I chose CSR.&lt;/p&gt;

&lt;p&gt;Get information in useEffect in page component&lt;br&gt;
&lt;a href="https://github.com/momonoki1990/nextjs-shopify-store/blob/main/pages/collections/%5Bhandle%5D.tsx#L30-L60" rel="noopener noreferrer"&gt;https://github.com/momonoki1990/nextjs-shopify-store/blob/main/pages/collections/%5Bhandle%5D.tsx#L30-L60&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Query the Store Front API using a custom client&lt;br&gt;
&lt;a href="https://github.com/momonoki1990/nextjs-shopify-store/blob/main/lib/graphql/collection/getCollectionWithProducts.ts#L69-L136" rel="noopener noreferrer"&gt;https://github.com/momonoki1990/nextjs-shopify-store/blob/main/lib/graphql/collection/getCollectionWithProducts.ts#L69-L136&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  JavaScript SDK and custom clients
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://shopify.github.io/js-buy-sdk/" rel="noopener noreferrer"&gt;JavaScript Buy SDK&lt;/a&gt; is an SDK for hitting the Store Front API. Basically, you can use this SDK for product information and cart operations, so I thought I'd use it entirely, but there were some problems. The SDK is only used for cart operations such as adding and deleting products, while the GraphQL client library (&lt;code&gt;graphql-request&lt;/code&gt;) is used for retrieving product information and search functions on the product page, directly hitting the Store Front API. This is because, first of all, JS Buy SDK seems to have an old type definition of TypeScript, and the type information does not match the property that can actually be retrieved, and it is necessary to extend the type definition partially by oneself. This was the first time for me to extend the type definitions, so I learned a lot, but it was troublesome to determine which properties were typed and which were not. Also, the basic properties supported by the SDK are only a part of the information that can be retrieved by the Store Front API as described in the official documentation, and when I tried to extend the SDK, it seemed to be so cumbersome (for example, the collection page does not support sorting of products). (Sorting is achieved with the SDK &lt;a href="https://github.com/Shopify/js-buy-sdk/issues/527" rel="noopener noreferrer"&gt;like this&lt;/a&gt;)&lt;br&gt;
Therefore, I decided to use the SDK only for cart operations where the SDK is sufficient, extending the library's typedefs, and to define a custom client to directly access to the Store Front API for the rest.&lt;/p&gt;

&lt;p&gt;JS Buy SDK&lt;br&gt;
&lt;a href="https://github.com/momonoki1990/nextjs-shopify-store/blob/main/lib/client.ts" rel="noopener noreferrer"&gt;https://github.com/momonoki1990/nextjs-shopify-store/blob/main/lib/client.ts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Custom Client&lt;br&gt;
&lt;a href="https://github.com/momonoki1990/nextjs-shopify-store/blob/main/lib/graphql/customClient.ts" rel="noopener noreferrer"&gt;https://github.com/momonoki1990/nextjs-shopify-store/blob/main/lib/graphql/customClient.ts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Extending the SDK type definitions&lt;br&gt;
&lt;a href="https://github.com/momonoki1990/nextjs-shopify-store/blob/main/types/shopify-buy.d.ts" rel="noopener noreferrer"&gt;https://github.com/momonoki1990/nextjs-shopify-store/blob/main/types/shopify-buy.d.ts&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom hooks
&lt;/h3&gt;

&lt;p&gt;I made a custom hook for a operation of a cart.&lt;/p&gt;

&lt;p&gt;Custom hooks (useCart)&lt;br&gt;
&lt;a href="https://github.com/momonoki1990/nextjs-shopify-store/blob/a91df30dd6fe4f6e6f057294dbbbb71876602ec9/lib/useCart.ts#L17-L130" rel="noopener noreferrer"&gt;https://github.com/momonoki1990/nextjs-shopify-store/blob/a91df30dd6fe4f6e6f057294dbbbb71876602ec9/lib/useCart.ts#L17-L130&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tailwind CSS and Material UI
&lt;/h3&gt;

&lt;p&gt;To recreate Shopify's default theme Debut (Dawn is the default theme now), I used Tailwind CSS and Material UI components for animations like drawers and skeletons (dummies displayed during the initial drawing). I personally used Tailwind CSS when I wrote my theme in Liquid and was very impressed with how it solved the problem of CSS being global. However, I still found it very useful to use Tailwind to integrate styling with HTML and reduce the amount of writing.&lt;br&gt;
We also used Tailwind in conjunction with Material UI, but as Tailwind is using class name and Material UI is a component, there were no conflicts. I don't think it's recommended to use different CSS frameworks together, so I don't think I'd personally recommend it for a real project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hydrogen and Oxygen.
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Hydrogen includes commerce-specific components such as a cart, variant picker and media gallery to take the complexity out of building a custom storefront.&lt;br&gt;
At the same time, "Oxygen" was announced. This is a fast and global way to host Hydrogen directly on Shopify, optimised for eCommerce.&lt;br&gt;
&lt;a href="https://www.shopify.jp/blog/unite-2021" rel="noopener noreferrer"&gt;Hydrogen and Oxygen are now available&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See also: &lt;a href="https://shopify.dev/hydrogen" rel="noopener noreferrer"&gt;Hydrogen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A React framework called Hydrogen, which provides components and Hooks that look like I wrote by myself, and a server called Oxygen, which hosts Hydrogen, are being released.&lt;/p&gt;

&lt;p&gt;With the tide of front-end development completely shifting to SPA frameworks, developing themes with Liquid has been a challenge in its own right, but Shopify is going to join the bandwagon, which will improve the UX, development speed, and development experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Others
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Can't show the total number of pages in the collection page.&lt;br&gt;
It would be nice if there was a property for the total number of pages, but the Store Front API doesn't allow us to get the total number of products in a collection. So, after retrieving a certain number of products in a collection (up to 250), we can determine if there is a next page from &lt;code&gt;pageInfo.haxNextPage&lt;/code&gt;, but can't display the total number of pages, like "1 / 12". The solution I can think of is to use ISR to get information about the collection at regular intervals on the collection page, get the collection information from the Store Front API or GraphQL Admin API, and then get the total number of products.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Products displayed in the store&lt;br&gt;
I'm using an app called &lt;a href="https://www.shopify.jp/oberlo" rel="noopener noreferrer"&gt;Oberlo&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The checkout (after "proceed to checkout") is the same as the theme, which takes you to the payment page provided by Shopify&lt;br&gt;
&lt;a href="https://github.com/momonoki1990/nextjs-shopify-store/blob/main/lib/useCart.ts#L110" rel="noopener noreferrer"&gt;https://github.com/momonoki1990/nextjs-shopify-store/blob/main/lib/useCart.ts#L110&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sorting products in a collection&lt;br&gt;
&lt;a href="https://github.com/momonoki1990/nextjs-shopify-store/blob/main/lib/graphql/collection/getCollectionWithProducts.ts#L87" rel="noopener noreferrer"&gt;https://github.com/momonoki1990/nextjs-shopify-store/blob/main/lib/graphql/collection/getCollectionWithProducts.ts#L87&lt;/a&gt;&lt;br&gt;
The arguments of the query are listed in "arguments" of "products" in &lt;a href="https://shopify.dev/api/storefront/reference/common-objects/queryroot" rel="noopener noreferrer"&gt;QueryRoot&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keyword search for product titles&lt;br&gt;
&lt;a href="https://github.com/momonoki1990/nextjs-shopify-store/blob/a91df30dd6fe4f6e6f057294dbbbb71876602ec9/lib/graphql/product/" rel="noopener noreferrer"&gt;https://github.com/momonoki1990/nextjs-shopify-store/blob/a91df30dd6fe4f6e6f057294dbbbb71876602ec9/lib/graphql/product/&lt;/a&gt; getProductsByTitle.ts#L52-L90&lt;br&gt;
Partial matching on query&lt;br&gt;
Shopify GraphQL partial matching on query filter&lt;br&gt;
&lt;a href="https://stackoverflow.com/questions/51742384/shopify-graphql-partial-matching-on-query-filter" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/51742384/shopify-graphql-partial-matching-on-query-filter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you for reading !&lt;/p&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
      <category>shopify</category>
      <category>tailwindcss</category>
    </item>
  </channel>
</rss>
