CubeMarFr · Morocco 🇲🇦 + France 🇫🇷 · Prices in MAD + estimated EUR
● SPEEDCUBES • MOROCCO 🇲🇦 + FRANCE 🇫🇷

CubeMarFr.
Speedcubes for Morocco & France.

CubeMarFr brings speedcubes to cubers in Morocco and France. Discover magnetic 2x2, 3x3, Pyraminx, 4x4, 5x5 and other puzzles, with official prices in MAD and indicative EUR estimates.

🇲🇦🇫🇷 Morocco + France💳 MAD + estimated EUR🧩 Curated speedcubes
◆ Curated speedcubing selection
🚚 Delivery in Morocco + France
🇲🇦🇫🇷 Morocco + France
CATALOG

Find your next cube.

A focused selection for cubers in Morocco and France. Live prices, stock and product images are synced from CubeMarFr.
Showing all products
No product matches your search.
Loading products…
+
SPECIAL ORDER

Looking for another product?

Looking for a cube that isn’t in our catalog? Send us a special-order request.
PRICE ON REQUEST
🔒
Secure order totalsPrices and stock are checked by the backend.
🇲🇦
Morocco + FranceOfficial prices in MAD, estimated EUR, and configurable delivery.
📦
Order trackingTrack your order from your CubeMarFr account.
💬
Human supportPolicies and WhatsApp contact are available on-site.
WHY CUBEMARFR

Built around the cuber.

A simpler way to discover speedcubes in Morocco and France, with a small catalog chosen for real cubing needs.
🧩

Focused selection

CubeMarFr is designed around useful speedcubing models rather than filling the catalog with random products.

🇲🇦

Morocco + France

Prices are official in MAD with indicative EUR estimates for customers in France.

📦

Special requests

If the cube you want is not listed, your account can send a special-order request directly to CubeMarFr.

CubeMarFr is being built for the Moroccan cubing community: a clean, focused place to discover magnetic cubes and twisty puzzles with clear information and prices in MAD.

OUR IDEA

CubeMarFr 🇲🇦

CubeMarFr is a speedcubing store project in Morocco. The goal is to offer a small, carefully selected range of interesting cubes instead of a catalog filled with random models.

LAUNCH

We’re preparing the stock.

The store is still being prepared. For now, the buttons above only measure interest: no payment is requested and no order is confirmed until stock is available.

FAQ

Good to know.

Current information while CubeMarFr is still preparing for launch.

CubeMarFr is still preparing for launch. No online payment is taken on the website, and availability must be confirmed before an order is considered final.

Yes. Product prices on CubeMarFr are displayed in MAD.

Use the “Request a product” card in the catalog. After signing in, you can send the product name, quantity and details as a special-order request.

You can browse the public catalog without an account. An account is used for features such as sending requests and managing order-related information.

CUBEMARFR

Launching soon 🧩

Follow the project and get ready for your next PB.

View the first stock
0 items0 DH
\n`; } function v10OpenInvoice(o){const w=window.open('','_blank','noopener,noreferrer');if(!w){alert('Please allow pop-ups to open the invoice.');return}w.document.open();w.document.write(v10InvoiceHTML(o));w.document.close()} async function v10LoadFinance(){ if(!(await requireAdmin()))return;openAdminData('Finance & margin');adminDataBody.innerHTML='
Loading finance data…
'; const [{data:orders,error:oErr},{data:items,error:iErr}]=await Promise.all([ sb.from('orders').select('id,total_mad,status,created_at,shipping_mad,discount_mad'), sb.from('order_items').select('order_id,unit_price_mad,unit_cost_mad,quantity') ]); if(iErr&&String(iErr.message||'').toLowerCase().includes('unit_cost_mad')){adminDataBody.innerHTML='
Run CubeMarFr-V10-Supabase.sql first.
';return} if(oErr||iErr){adminDataBody.textContent=(oErr||iErr).message;return} const valid=(orders||[]).filter(o=>o.status!=='cancelled'),ids=new Set(valid.map(o=>o.id)); const revenue=valid.reduce((s,o)=>s+Number(o.total_mad||0),0); const productRevenue=(items||[]).filter(i=>ids.has(i.order_id)).reduce((s,i)=>s+Number(i.unit_price_mad||0)*Number(i.quantity||0),0); const cogs=(items||[]).filter(i=>ids.has(i.order_id)).reduce((s,i)=>s+Number(i.unit_cost_mad||0)*Number(i.quantity||0),0); const gross=productRevenue-cogs,avg=valid.length?revenue/valid.length:0,delivered=valid.filter(o=>o.status==='delivered').length; const now=new Date(),start=new Date(now.getFullYear(),now.getMonth(),1),monthRev=valid.filter(o=>new Date(o.created_at)>=start).reduce((s,o)=>s+Number(o.total_mad||0),0); const pct=productRevenue>0?gross/productRevenue*100:0; adminDataBody.innerHTML=`
Total revenue${v10Money(revenue)}
Gross product profit*${v10Money(gross)}
Gross margin*${pct.toFixed(1)}%
Average order${v10Money(avg)}
This month${v10Money(monthRev)}
Non-cancelled orders${valid.length}
Delivered${delivered}
Product cost recorded${v10Money(cogs)}
*Margin note
This is product gross margin only. Shipping paid by CubeMarFr, customs, packaging, taxes, fees and other overhead are not automatically deducted.
`; } async function v10EmailSetup(){if(!(await requireAdmin()))return;openAdminData('Email confirmations');adminDataBody.innerHTML=`
V10 email system is prepared.
Orders call the Supabase Edge Function order-confirmation after secure checkout.

To send real emails, deploy the included Edge Function and set Supabase secrets:
RESEND_API_KEY
ORDER_EMAIL_FROM

No private API key is stored in the public website.
`} document.getElementById('adminFinanceBtn')?.addEventListener('click',v10LoadFinance); document.getElementById('adminEmailSetupBtn')?.addEventListener('click',v10EmailSetup); async function v10FetchHistory(orderId){const {data,error}=await sb.from('order_status_history').select('status,note,created_at').eq('order_id',orderId).order('created_at',{ascending:true});return error?[]:(data||[])} function v10TimelineHTML(h){return `
${(h||[]).map(x=>`
${v8Esc(v10StatusLabel(x.status))}${x.note?`
${v8Esc(x.note)}
`:''}${new Date(x.created_at).toLocaleString()}
`).join('')||'
No tracking events yet.
'}
`} const v10V9LoadAdminOrders=v9LoadAdminOrders; v9LoadAdminOrders=async function(){ const box=document.getElementById('adminOrdersList');box.innerHTML='Loading…'; let {data,error}=await sb.from('orders').select('id,order_number,created_at,customer_name,phone,city,address,total_mad,status,promo_code,discount_mad,shipping_mad,tracking_code,tracking_url,status_note,order_items(product_name,unit_price_mad,unit_cost_mad,quantity)').order('created_at',{ascending:false}); if(error&&String(error.message||'').toLowerCase().includes('tracking_code'))return v10V9LoadAdminOrders(); if(error){box.textContent='Order error: '+error.message;return} const rows=data||[];window.v9AdminOrders=rows; box.innerHTML=`
`; const draw=()=>{let q=document.getElementById('v9OrderSearch').value.toLowerCase(),st=document.getElementById('v9OrderStatus').value,sort=document.getElementById('v9OrderSort').value;let list=rows.filter(o=>{const ref=v10Ref(o);return(!st||o.status===st)&&(!q||`${ref} ${o.customer_name} ${o.city} ${o.phone} ${o.tracking_code||''}`.toLowerCase().includes(q))});list.sort((a,b)=>sort==='old'?new Date(a.created_at)-new Date(b.created_at):sort==='high'?Number(b.total_mad)-Number(a.total_mad):new Date(b.created_at)-new Date(a.created_at)); document.getElementById('v9OrdersHost').innerHTML=list.map(o=>`
#${v8Esc(v10Ref(o))} · ${v8Esc(o.customer_name)}
${new Date(o.created_at).toLocaleString()} · ${v8Esc(o.city)} · ${v8Esc(o.phone)}
${v8Esc(o.status)}
${(o.order_items||[]).map(i=>`${i.quantity}× ${v8Esc(i.product_name)} · ${v10Money(i.unit_price_mad)}`).join('
')}
${v8Esc(o.address)}
Tracking / customer update
`).join('')||'
No matching orders.
'; document.querySelectorAll('[data-v9-status]').forEach(sel=>sel.onchange=async()=>{const {error}=await sb.from('orders').update({status:sel.value}).eq('id',sel.dataset.v9Status);if(error)alert(error.message);else{try{await sb.functions.invoke('order-confirmation',{body:{order_id:sel.dataset.v9Status,event:'status'}})}catch(e){}v9LoadAdminOrders()}}); document.querySelectorAll('[data-v10-save-track]').forEach(b=>b.onclick=async()=>{const id=b.dataset.v10SaveTrack,tracking_code=document.querySelector(`[data-v10-track-code="${id}"]`).value.trim()||null,tracking_url=document.querySelector(`[data-v10-track-url="${id}"]`).value.trim()||null,status_note=document.querySelector(`[data-v10-note="${id}"]`).value.trim()||null;const {error}=await sb.from('orders').update({tracking_code,tracking_url,status_note}).eq('id',id);if(error)alert(error.message);else{try{await sb.functions.invoke('order-confirmation',{body:{order_id:id,event:'status'}})}catch(e){}alert('Tracking saved.')}}); document.querySelectorAll('[data-v10-invoice]').forEach(b=>b.onclick=()=>{const o=rows.find(x=>x.id===b.dataset.v10Invoice);if(o)v10OpenInvoice(o)}); document.querySelectorAll('[data-v9-copy]').forEach(b=>b.onclick=()=>navigator.clipboard?.writeText(b.dataset.v9Copy));}; ['v9OrderSearch','v9OrderStatus','v9OrderSort'].forEach(id=>document.getElementById(id).addEventListener(id==='v9OrderSearch'?'input':'change',draw));draw(); } loadAdminOrders=v9LoadAdminOrders; const v10OldMyOrders=v8MyOrders; v8MyOrders=async function(){ if(!currentUser){openAuth();return} const o=document.getElementById('customerDataOverlay'),b=document.getElementById('customerDataBody');document.getElementById('customerDataTitle').textContent='My orders';b.innerHTML='Loading…';v8OpenOverlay(o); let {data,error}=await sb.from('orders').select('id,order_number,total_mad,status,created_at,customer_name,phone,city,address,promo_code,discount_mad,shipping_mad,tracking_code,tracking_url,status_note,order_items(product_name,unit_price_mad,quantity)').eq('user_id',currentUser.id).order('created_at',{ascending:false}); if(error&&String(error.message||'').toLowerCase().includes('tracking_code'))return v10OldMyOrders();if(error){b.textContent=error.message;return} const rows=data||[],histories=await Promise.all(rows.map(x=>v10FetchHistory(x.id))); b.innerHTML=rows.map((x,i)=>`
#${v8Esc(v10Ref(x))}${v8Esc(v10StatusLabel(x.status))}
${new Date(x.created_at).toLocaleString()}
${(x.order_items||[]).map(it=>`${it.quantity}× ${v8Esc(it.product_name)}`).join(' · ')}
${v10Money(x.total_mad)}${x.status_note?`
${v8Esc(x.status_note)}
`:''}${x.tracking_code?`
Tracking: ${v8Esc(x.tracking_code)} ${x.tracking_url?`· Track shipment`:''}
`:''}${v10TimelineHTML(histories[i])}
`).join('')||'
No orders yet.
'; b.querySelectorAll('[data-customer-invoice]').forEach(btn=>btn.onclick=()=>{const row=rows.find(x=>x.id===btn.dataset.customerInvoice);if(row)v10OpenInvoice(row)}); } document.getElementById('myOrdersBtn').onclick=v8MyOrders; console.info('CubeMarFr V10 PRODUCTION SUITE active');