Building an Amazon Storefront in React

How I rebuilt my Chinese Hotpot project site into an Amazon Associates store front.

Once a Blog, but not so much now

One of the oldest domains I still own (not including all the projects I have long since abandoned...) is called ChineseHotpot.co.uk. It has been many things over the years. It started as a blog site on a terribly clunky platform. I eventually shifted to WordPress, which was better, but I couldn't quite get the control over the platform that I wanted. I then migrated to a Hugo blog, and it sort of worked.

In terms of content, it was originally conceived as a place where my Chinese wife and I could talk about our multicultural family, some of the things we get up to in China, and how a Chinese person settles into UK life. As a blog idea, it brought in an audience, more so than this site does in fact, but it was always meant to be a team effort. The other side of the team just wasn't that interested, and my well of ideas started to run dry.

The domain was sitting there doing nothing

As content dried up and visitors naturally slowed down, I decided to reinvent the website and use it as one of my portfolio pieces. Since I owned the domain anyway, I might as well use it for something.

I started to build a Store Front in React using create-react-app. At the time, I had planned to target some of the larger Chinese food retailers in the UK. I reached out to a couple, but they weren't interested in my idea/build. One told me that they'd just undertaken a huge website refresh of their own and didn't see any reason to change it. Another told me that they'd tried the web-based store-front already, and it didn't work for them. Others just didn't respond to my attempts at engagement.

Never build a product without a target buyer

If I consider the project to be a product, then it was a glorious failure. I built what no one wanted, which is a cardinal sin.

However, it should be noted that when I went down this path, it was a learning exercise. I thought it might land me a front-end dev job somewhere. In fact, my approach to the food retailers in the UK was that they might want to hire me as a developer working for them, not just selling them something and leaving it. That didn't exactly work, but I still learnt a whole bunch.

The old store front

Amazon Associates

I still own the domain, and it's due for renewal. It's never turned a penny over to me. What I should really do is release it back into the ocean of domain names for someone with a better idea to take ownership and build something that people want. But... it does have that strange sentimental connection for me, perhaps because of what it once was before my wife got bored with the idea.

I don't want to build another blog. Apart from this one and some guest pieces I sometimes write for others, I really don't want to try and maintain another one.

Instead, I'm planning to use this domain as a place for connecting potential buyers with Chinese food, cooking items, and cultural items available from Amazon. Yes, all of those products are already available on Amazon, but until I can come up with a better idea, this is the route I'm going to take for now.

Aim and Target Structure

As a new Amazon Associates member, I am not able to access the Product API, so I'm limited to using what they call SiteStripe links. This is basically where you have to find the products you're interested in, copy a link that contains your Associates ID, and then place that code on your website. However, I want some flexibility to allow for using the API in the future.

I'm also going to complement the items with some blog posts (oh no, not more blogging), but the target isn't to build a blog, it is to celebrate Chinese culture in the UK. I also hope to drag my wife back into this.

Structure

We're going to build the website using Vite/React and probably Tailwind for styling, but I'm not there yet.

We will need to have Pages and Components:

my-storefront/
├── public/
│   └── index.html
├── src/
│   ├── components/
│   │   ├── Header.jsx
│   │   ├── ProductCard.jsx
│   │   └── BlogPost.jsx
│   ├── pages/
│   │   ├── Home.jsx
│   │   └── Blog.jsx
│   ├── App.jsx
│   ├── index.css
│   └── main.jsx
├── package.json
└── vite.config.js

I will also need styling, and I'm thinking of using styled-components. Oh, and of course, we should consider supporting a Dark-mode option and mobile-first designs right from the start.

We'll start with basic styling for now. It's always best to focus on functionality and do the styling later.

Header

const Header = ({ toggleTheme }) => {
    return (
        <Navbar>
            <div>
                <Link to='/'>Home</Link>
                <Link to='/blog'>Blog</Link>
            </div>
            <button onClick={toggleTheme}>Toggle Dark Mode</button>
        </Navbar>
    );
};

export default Header;

ProductCard

For the Product Listings, I'm expecting to be able to have a single page, which will likely evolve into categories of products, but for now, a single page that calls a product component. I'll have to think about how I populate those components in bulk a little later.

const ProductCard = ({ product }) => {
    return (
        <Card>
            <h2>{product.name}</h2>
            <img src={product.image} alt={product.name} />
            <a href={product.link} target='_blank' rel='noopener noreferrer'>View on Amazon</a>
        </Card>
    );
};

export default ProductCard;

BlogPost

Of course, I want a simple blog as well. I plan to use MarkDown, but I'm not really thinking about a blog-roll as such at the moment.

const BlogPost = ({ post }) => {
    return (
        <Post>
            <h2>{post.title}</h2>
            <ReactMarkDown>{post.content}</ReactMarkDown>
        </Post>
    );
};

export default BlogPost;

Home Page

For the Home Page, I'm going to try holding my products in an array, but this will not work long-term, although it might work long enough until I get access to the Amazon Products API, in which case I can scrap some of this anyway.

const Home = () => {
    
    // somewhere to put products for now, 
    // we'll probably need to move this later else will get too big
    const products = [
        // products here
    ];

    return (
        <HomePage>
            <h1>Chinese Hotpot</h1>
            <div>
                {products.map(product => (
                    <ProductCard key={product.id} product={product} />
                ))}
            </div>
        </HomePage>
    );
};

export default Home;

I'm at a tricky stage. I will need to come back to this part of the blog later. I think I need to move my products into their own Products page, but for now, let's leave it as it is.

Blog Page

Okay, when I thought of the structure, I didn't think about accessing the blog posts. My temporary solution is inefficient and will need more work in a later revision.

const Blog = () => {

    // I don't think this is optimal,
    // but until I see how other blogs do this
    // I'll just make an array of posts in this space
    const posts = [
        // blog posts here (but this will not work long term)
    ];

    return (
        <BlogPage>
            <h1>Blog</h1>
            <div>
                {posts.map(post => (
                    <BlogPost key={post.id} post={post} />
                ))}
            </div>
        </BlogPage>
    );
};

export default Blog;

The App

Now we need to bring it all together. At this point, if I were to run the app, we'd just see the Vite demo page, so we need to remove all of that and load the pages, components, and routes that we need in this new website.

const App = () => {

  // let's get darkmode as a state with a default OFF
  const [darkMode, setDarkMode] = useState(false);

  // we need to allow a change to that default darkMode state
  const toggleTheme = () => {
    setDarkMode(!darkMode);
    document.body.classList.toggle('dark-mode');
  };

  return (
    <Router>
      <Header toggleTheme={toggleTheme} />
      <Routes>
        <Route exact path="/" Component={Home} />
        <Route path="/blog" component={Blog} />
      </Routes>
    </Router>
  );
};

export default App;

That should be it, although I'll add the styling later.

Basic layout of the new storefront

By the time you see this blog post, I should have figured out the styling and hopefully have a product database, likely as a JSON file for now. The live project should be available at ChineseHotpot.co.uk, and the GitHub repo with the full code should be available here.