How I Integrated Etsy With a Static Website Without a Database

Static websites are fast, cheap to host, and easy to maintain. The only problem starts when the content changes frequently.

A friend of mine sells personalized products on Etsy.

After a while, they wanted something more than just an Etsy store.

A dedicated website would help with branding, discoverability, SEO, and give them a place to tell the story behind their products.

Very quickly we ran into a practical question: Who is going to maintain all of this?

Nobody wanted to manage products twice.

Every new product would require:

  1. Creating the listing in Etsy.
  2. Uploading the same product again to the website.
  3. Updating prices in two places.
  4. Updating images in two places.
  5. Keeping categories synchronized manually.

That sounded like a maintenance nightmare.

The real question quickly became:

How can we keep Etsy as the only place where products are managed while still having a completely custom website?


The Traditional Approach

The obvious approach would be introducing:

  • a database,
  • an admin panel,
  • a CMS,
  • or some kind of synchronization dashboard.

Technically, all of those would work.

But they would also create a second source of truth.

Now the same product exists in two places:

  • Etsy
  • Website database

Sooner or later they drift apart.

The website shows one thing.

The Etsy store shows another.

The problem isn’t synchronization.

The problem is duplication.


Etsy Should Be The Source Of Truth

The decision was simple:

Products should only exist in Etsy.

Everything else should be generated automatically.

That means:

  • New product on Etsy → appears on the website automatically.
  • Product price changes on Etsy → updates on the website automatically.
  • Product image changes on Etsy → updates on the website automatically.
  • New category created on Etsy → appears on the website automatically.

No manual work.

No duplicate content management.


The Architecture

The final architecture looked like this:

             Etsy API

     ┌───────────┼─────────────┐
     │           │           │
     ▼           ▼           ▼
 Listings    Sections     Images
     │           │           │
     └───────────┼─────────────┘

      Etsy Catalog Generator


      output/products.json


           Custom Website

Instead of communicating with Etsy directly from the frontend, a small PHP script periodically generates a static JSON catalog.

The website simply consumes that file.


Why Not Call Etsy Directly From The Frontend?

That was one of the first ideas.

Something like this:

fetch("https://openapi.etsy.com/...")

There are several problems with this approach:

  • Every page load depends on Etsy availability.
  • API latency affects page speed.
  • Rate limits become a concern.
  • The website is no longer truly static.

Generating a local catalog solved all of those problems.


Aggregating Multiple Etsy Endpoints

One interesting detail is that Etsy does not expose everything through a single endpoint.

Building the catalog required combining multiple API responses.

Listings

GET /shops/{shop_id}/listings/active

Images

GET /listings/{listing_id}/images

Categories

GET /shops/{shop_id}/sections

The generator combines all of them into a single normalized catalog.

The frontend never needs to know where the data originally came from.


Pagination Matters

This is a detail that is easy to miss.

The Etsy API paginates listing results.

A shop with 20 products works perfectly during development.

A shop with 250 products suddenly doesn’t.

The generator automatically follows pagination until every product has been fetched.

$offset = 0;
$listings = [];

do {

    $response = $this->request(...);

    $results = $response['results'] ?? [];

    $listings = array_merge(
        $listings,
        $results
    );

    $offset += self::PAGE_SIZE;

} while (count($results) === self::PAGE_SIZE);

That guarantees that the generated catalog always contains the complete store.


Categories Are Discovered Automatically

If Etsy already knows what the categories are, the website shouldn’t need to know them separately.

foreach ($sections as $section) {

    $categories[] = [

        'id' => (int) $section['shop_section_id'],

        'name' => $section['title']

    ];
}

Creating a new category in Etsy automatically makes it appear on the website.

No code changes required.


Why PHP for This?

I’m primarily a .NET developer.

This wasn’t about finding the perfect language.

It was about finding the smallest possible solution.

A small PHP script that runs, generates a JSON file and exits solved the problem perfectly.

Could this have been built with ASP.NET?

Absolutely.

Would it have been simpler?

Probably not.

Sometimes the best solution isn’t the most sophisticated one.

It’s simply the one with the fewest moving parts.


The Result

The result is a fully customized website with completely automated product synchronization.

Products are managed in exactly one place.

Etsy remains the source of truth.

The website remains fast, static, and easy to host.

Most importantly:

Nobody has to enter the same product twice.


Open Source

During the implementation I extracted the catalog generator into its own open-source project.

If you’d like to explore the code or use it in your own projects:

https://github.com/hanificetinkaya/etsy-catalog-generator

And if you’d like to see the real website that originally motivated this project:

https://mellyandbobby.de/

You might even find something you like there.