5.0 ( 2  Reviews )

Arches - Starter set

€39.00

Imagine your world

Endless Creativity

Arches unlock a world of imagination. Whether that's tunnels, towers, racetracks, or abstract creatures, there’s no limit to what you can create. With just one shape, you can invent stories, structures, and games, over and over again.

Sustainably Made to Last

Arches are made in Europe using recycled plastic. They’re tough, safe, and built to last for years of open-ended play. Because we use recycled materials, small color variations may occur, a playful reminder that sustainability makes every set unique.

Click & Connect Magic

Arches feature a unique clicking system on the short- and on the long end, providing you with a satisfying click when you combine your Arches! And the best part? They stay connected! Opening a whole new dimension to playing with Arches.

Curve your creativity

Combine Arches & Roads

Build winding tracks that rise, loop, and dive. Create overpasses, tunnels, jumps, or whatever your imagination dreams up. Arches add a whole new dimension to our beloved roads!

Create Your Own Games

One moment it’s a ramp for marbles, the next it’s a finish line, a hoop, or a goal. Add beanbags, dinosaurs, cars, or anything from the toy box. Suddenly, Arches become the spark that connects it all!

Product Specification:

100%

Made in Europe

Arches are injection moulded in Bosnia Herzogovina.

100%

European Raw Materials

The raw materials from Arches are sourced in The Netherlands.

🇪🇺 Europe - CE + EN 71 - 1,2,3

🇺🇸 USA – ASTM F963 + CPSIA

🇨🇦 Canada – SOR/ 2011-17

🇦🇺 Australia - AS/NZS 8124 - 1,2,3

🇯🇵 Japan – Physical, Flammability

100%

Plastic Free

Our packaging is plastic-free and fully recyclable. Pure play, responsibly packed.

Manufacturing

Safe & Tested

Packaging

×
/** * FREE GIFT AUTOMATION — Waytoplay Toys * Automatically adds the Flyer (free gift) when cart reaches €75, * and removes it when the cart drops below €75. * * Works alongside the existing "Happy Holidays!" Buy X Get Y discount * which handles the price reduction at checkout. * * Theme: Showcase * Free gift: Flyer (variant ID 48114081399130) * Threshold: €75.00 */ (function () { const FREE_GIFT_VARIANT_ID = 48114081399130; const THRESHOLD_CENTS = 7500; // €75.00 const GIFT_PROPERTY_KEY = '_free_gift'; const GIFT_PROPERTY_VALUE = 'happy-holidays'; let isEvaluating = false; // ── Helpers ──────────────────────────────────────────────────────────────── async function fetchCart() { const res = await fetch('/cart.js'); return res.json(); } async function addGift() { await fetch('/cart/add.js', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: FREE_GIFT_VARIANT_ID, quantity: 1, properties: { [GIFT_PROPERTY_KEY]: GIFT_PROPERTY_VALUE }, }), }); } async function removeGift() { // Find the specific line number of the gift (1-based index in Shopify) const cart = await fetchCart(); const lineIdx = cart.items.findIndex(isGiftItem); if (lineIdx === -1) return; await fetch('/cart/change.js', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ line: lineIdx + 1, quantity: 0 }), }); } function isGiftItem(item) { return ( item.variant_id === FREE_GIFT_VARIANT_ID && item.properties && item.properties[GIFT_PROPERTY_KEY] === GIFT_PROPERTY_VALUE ); } /** * Subtotal excluding the gift itself, so its price doesn't affect * the threshold calculation. */ function subtotalWithoutGift(cart) { return cart.items.reduce((sum, item) => { return isGiftItem(item) ? sum : sum + item.line_price; }, 0); } // ── Refresh the Showcase cart drawer ────────────────────────────────────── function refreshCart() { // Showcase theme uses a custom element / event-based cart drawer. // Try the most common event names used by Showcase and similar themes: document.dispatchEvent(new CustomEvent('cart:refresh')); document.dispatchEvent(new CustomEvent('theme:cart:update')); // Also dispatch on window for themes that listen there: window.dispatchEvent(new CustomEvent('cart:refresh')); // Re-fetch and update the cart count badge if the theme exposes it: fetch('/cart.js') .then(r => r.json()) .then(cart => { // Update any cart count elements the theme renders document.querySelectorAll('[data-cart-count], .cart-count, .js-cart-count').forEach(el => { el.textContent = cart.item_count; }); }) .catch(() => {}); } // ── Core logic ───────────────────────────────────────────────────────────── async function evaluateGift() { if (isEvaluating) return; isEvaluating = true; try { const cart = await fetchCart(); const subtotal = subtotalWithoutGift(cart); const giftInCart = cart.items.some(isGiftItem); const qualifies = subtotal >= THRESHOLD_CENTS; if (qualifies && !giftInCart) { await addGift(); refreshCart(); } else if (!qualifies && giftInCart) { await removeGift(); refreshCart(); } } catch (e) { console.warn('[FreeGift]', e); } finally { isEvaluating = false; } } // ── Intercept cart mutations ─────────────────────────────────────────────── const _origFetch = window.fetch; window.fetch = async function (...args) { const url = typeof args[0] === 'string' ? args[0] : (args[0]?.url ?? ''); const isCartMutation = /\/cart\/(add|change|update)\.js/.test(url); const response = await _origFetch.apply(this, args); if (isCartMutation) { // Wait a tick so the cart has settled before we evaluate response.clone().json().then(() => { setTimeout(evaluateGift, 300); }).catch(() => {}); } return response; }; // ── Check on page load ──────────────────────────────────────────────────── document.addEventListener('DOMContentLoaded', evaluateGift); })();