Order Online

Discover the Bold Flavors of Asia at Black Pearl

Where Asia's Flavors Meet, and Every Bite Excites!

Explore Our Menu
A bowl of soup with shrimp and noodles.

About

Bringing the Heart of Asian Flavors to Bellingham, One Dish at a Time

At Black Pearl Asian Fusion Restaurant, we’re all about mixing up the best flavors from across Asia into one delicious dining experience. Right in the heart of Bellingham, we take pride in whipping up both traditional and modern dishes with the freshest ingredients.

<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script>
    const propsContainer = document.querySelector(".props-container");
    const root = document.getElementById("app");
    const listItem = document.getElementById("list-item-main");
    const categoriesContainer = document.getElementById("categories-container");
    const categoriesLink = document.getElementById("category-link");
    const isGrid = document.getElementById("rGrid").textContent;
    if (isGrid === "true") {
        root.classList.add("grid");
        // Add grid-display class to list-item and item-thumbnail-wrapper
        const listItems = document.querySelectorAll(".list-item");
        listItems.forEach(item => {
            item.classList.add("grid-display");
        });

        const thumbnailWrappers = document.querySelectorAll(".item-thumbnail-wrapper");
        thumbnailWrappers.forEach(wrapper => {
            wrapper.classList.add("grid-display");
        });
    }
    let itemsByCategory = {};
    let categoryNames = {uncategorized: "uncategorized"};
    const excludedCategoriesText = document.getElementById("rExcludeList").textContent;
    const excludedCategoryNames = excludedCategoriesText
        .split(",")
        .map((name) => name.trim());

    // Fetch menu data
    async function fetchMenuData() {
        try {
            const dt = new Date();
            const year = dt.getFullYear();
            const month = (dt.getMonth() + 1).toString().padStart(2, "0");
            const day = dt.getDate().toString().padStart(2, "0");
            const date = year + '-' + month + '-' + day
            const merchantId = document.getElementById("rMID").textContent.trim();
            const url = `https://qa-ecommerce-api.spoton.com/v1/restaurants/${merchantId}/menu-groups?orderDateTime=${date}T10:22:25-05:00&orderTypeId=3uxw5e1y0vgz3dwi1we2ioj1lq`;

            const response = await fetch(url);
            if (!response.ok) {
                throw new Error("Network response was not ok for categories");
            }
            const categories = await response.json();
            categories.forEach((category) => {
                categoryNames[category.id] = category.name.trim();
                itemsByCategory[category.id] = category.menuItems;
            });

            createCategoryLinks();
            const firstCategory = Object.keys(itemsByCategory).find(
                (categoryId) => !excludedCategoryNames.includes(categoryNames[categoryId]));
            if (firstCategory) {
                displayItems(firstCategory);
                setActiveCategory(firstCategory);
            }
        } catch (error) {
            console.error("There was a problem with the fetch operation:", error);
        } finally {
            listItem.remove();
        }
    }

    function createCategoryLinks() {
        Object.keys(itemsByCategory).forEach((categoryId) => {
            if (!excludedCategoryNames.includes(categoryNames[categoryId])) {
                let link = categoriesLink.cloneNode(true);          


    if (window.innerWidth < 768){
      console.log("Less than 768");
      link.href = "#app";
   } else{
      console.log("More than 768");
      link.href = "#";
}                
                link.removeAttribute("id");
                link.textContent = categoryNames[categoryId] || categoryId;
                link.dataset.categoryId = categoryId;
                link.addEventListener("click", (e) => {
                    e.preventDefault();
                    setActiveCategory(categoryId);
                    displayItems(categoryId);
                });
                link.classList.remove("hidden");
                categoriesContainer.appendChild(link);
            }
        });
        categoriesLink.remove();
    }

    function setActiveCategory(categoryId) {
        const links = categoriesContainer.getElementsByTagName("a");
        for (let link of links) {
            if (link.dataset.categoryId === categoryId) {
                link.classList.add("active");
            } else {
                link.classList.remove("active");
            }
        }
    }

    function displayItems(categoryId) {
    root.innerHTML = "";
    itemsByCategory[categoryId].forEach((item) => {
        let cloneNode = listItem.cloneNode(true);
        cloneNode.removeAttribute("id");
        cloneNode.classList.remove("hidden");
        cloneNode.querySelector(".list-item-name").textContent = item.name;
        
        // Display price if available and not zero, otherwise, remove the "$" sign
        const priceElement = cloneNode.querySelector(".list-item-price");
        if (item.price && parseFloat(item.price) !== 0) {
            priceElement.textContent = "$" + item.price;
        } else {
            priceElement.textContent = "";
        }

        cloneNode.querySelector(".list-item-description").textContent = item.description;

        // Display image if available, otherwise, hide the wrapper
        if (item.imageUrl) {
            cloneNode.querySelector(".list-item-image").src = item.imageUrl;
        } else {
            cloneNode.querySelector(".item-thumbnail-wrapper").remove();
        }

        // Check if modifiers exist
        if (item.modifiers && item.modifiers.length > 0) {
            // Create a list to store modifiers
            let modifiersList = document.createElement('ul');
            modifiersList.classList.add('modifiers-list');

            // Iterate through modifiers and add them to the list
            item.modifiers.forEach(modifier => {
                let modifierItem = document.createElement('li');
                modifierItem.textContent = `${modifier.name} (${modifier.price})`;
                modifiersList.appendChild(modifierItem);
            });

            // Append the list of modifiers to the menu item
            cloneNode.appendChild(modifiersList);
        }

        root.appendChild(cloneNode);
    });
    propsContainer.remove();
}


    // Call the function to fetch menu data
    fetchMenuData();
</script>

      // Click category       

   async function clickClassic() {
        const result = await fetchMenuData();
        document.querySelector("[data-category-id='c1oha4r1ancznfi0lglk5hpiqi']").click();
    }; 

   clickClassic()
   

First time at this restaurant and it DID NOT DISAPPOINT! I’ve been wanting to try this place out for months, but forget it’s here because it’s kind of in a hidden area. The restaurant is clean and a good spot for a nice meal without so much noise. I’ll definitely be coming back often to satisfy my cravings.

happy young african-american woman
Jasmine A.

Loved the Tofu Pad Tai! There was a bit of a wait for my carry out order but I wasn't getting fast food so I just made a mental note for when I order next. Lady that helped with my order was friendly and helpful and I'm looking forward to trying more of their menu.

happy young asian man
N Steele.

It was my first time ordering here and the only regret I have is that I hadn’t tried it before. I had the  garlic tofu stir fry and avocado basil smoothie. Both items were amazing and I look forward to trying more of their menu.

happy young white man
Navr M.

Visit Us!

We are committed to delivering a dining experience that blends tradition with innovation, ensuring that each dish reflects the heart of Asian cuisine while offering something new and exciting for every guest.

Business Hours

Monday to Saturday 11:00 AM - 9:30 PM

Sunday Closed