3cspan class=\"title-name\"\u003eFor grip and control\u003c\/span\u003e\n\u003c\/h3\u003e\n\u003cdiv class=\"plus-icon\"\u003e\u003cbr\u003e\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"toggle-inner\"\u003e\n\u003cp\u003eMicrofiber Bar Tape provides excellent grip so that riders can exert maximum control.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"toggle-product\"\u003e\n\u003cdiv data-show-image=\"option-image\" class=\"toggle-title active\"\u003e\n\u003ch3\u003e\n\u003cspan class=\"toggle-img\"\u003e\u003cimg src=\"https:\/\/cdn1.brooksengland.com\/media\/wysiwyg\/moreinfo\/LIGHTWEIGHT.png\"\u003e\u003c\/span\u003e\u003cspan class=\"title-name\"\u003eLightweight\u003c\/span\u003e\n\u003c\/h3\u003e\n\u003cdiv class=\"plus-icon\"\u003e\u003cbr\u003e\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"toggle-inner\"\u003e\n\u003cp\u003eMaterials specially chosen for their remarkable strength-to-weight ratio.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cd
iv class=\"toggle-product\"\u003e\n\u003cdiv data-show-image=\"option-image\" class=\"toggle-title active\"\u003e\n\u003ch3\u003e\n\u003cspan class=\"toggle-img\"\u003e\u003cimg src=\"https:\/\/cdn1.brooksengland.com\/media\/wysiwyg\/moreinfo\/MADE_TO_LAST.png\"\u003e\u003c\/span\u003e\u003cspan class=\"title-name\"\u003eMade to last\u003c\/span\u003e\n\u003c\/h3\u003e\n\u003cdiv class=\"plus-icon\"\u003e\u003cbr\u003e\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"toggle-inner\"\u003e\n\u003cp\u003eDurable materials are chosen for long life and excellent wearing properties.\u003c\/p\u003e\n\u003cp\u003e \u003cbr\u003e\u003c\/p\u003e\n\u003cp data-mce-fragment=\"1\"\u003e\u003cstrong data-mce-fragment=\"1\"\u003eIf any more information is needed, please don't hesitate to get in touch with one of the team:\u003c\/strong\u003e\u003c\/p\u003e\n\u003cp data-mce-fragment=\"1\"\u003e\u003cstrong data-mce-fragment=\"1\"\u003eProjektRide Bike shop Edinburgh.\u003c\/strong\u003e\u003c\/p\u003e\n\u003cp data-m
m/extensions/019bf9e0-3016-7510-aaea-4318e35b6645/restock-rocket-shopify-436/assets/restockrocket-collection.js'
window._RestockRocketConfig.scriptHost = window._RestockRocketConfig.scriptUrlProduct.substring(0, window._RestockRocketConfig.scriptUrlProduct.lastIndexOf('/') + 1)
window._RestockRocketConfig.host = 'https://app.restockrocket.io'
const SETTINGS_CACHE_DURATION = 15 * 60 * 1000; // 15 minutes in milliseconds
function checkSettingsExpiry(settings) {
try {
if (!settings || !settings.updated_at) {
console.debug('STOQ - Invalid settings data structure');
return null;
}
if (!settings.cache) {
console.debug('STOQ - settings caching disabled');
return null;
}
// Check if translations are enabled but missing from cache
// This handles the backfill period where DB has translations but metafield doesn't
if (settings.multi_language_enabled) {
if (!settings.translations) {
// Translations enabled but no
translation data in metafield
// Metafield hasn't been backfilled yet - force refresh
console.debug('STOQ - multi-language enabled but no translation data in cache, fetching fresh');
return null;
}
// Translations object exists in metafield - cache is valid
// If current locale isn't translated, applyTranslations will gracefully use default locale from base fields
if (window._RestockRocketConfig.normalizedLocale &&
!Object.prototype.hasOwnProperty.call(settings.translations, window._RestockRocketConfig.normalizedLocale)) {
console.debug('STOQ - locale not explicitly translated, will use default language from cache');
}
// Don't return null - continue using cache even for untranslated locales
}
const updatedAt = new Date(settings.updated_at);
if (isNaN(updatedAt.getTime())) {
console.debug('STOQ - Invalid updated_at date format in settings');
return null;
}
const
age = Date.now() - updatedAt.getTime();
if (age
<
SETTINGS_CACHE_DURATION) {
console.debug('STOQ - settings changed recently, skipping cache');
return null;
}
return settings;
} catch (error) {
console.debug('STOQ - Error checking settings cache:', error);
return null;
}
}
function createRestockRocketContainer() {
const restockRocketContainer = document.createElement('div');
restockRocketContainer.id = 'restock-rocket';
document.body.appendChild(restockRocketContainer);
}
function createRestockRocketScript(scriptUrl) {
const restockRocketScriptElement = document.createElement('script');
restockRocketScriptElement.setAttribute('defer', 'defer');
restockRocketScriptElement.src = scriptUrl;
document.body.appendChild(restockRocketScriptElement);
}
createRestockRocketContainer()
console.debug('STOQ - extension activated')
function applyTranslations(settings) {
try {
// Skip translation logic entirely iLoading moreForkf multi-language is not enabled
if (!settings || !settings.multi_language_enabled) {
return settings;
}
if (!settings.translations) {
console.debug('STOQ - No translations found, skipping translation');
return settings;
}
const normalizedLocale = window._RestockRocketConfig.normalizedLocale;
const translations = settings.translations;
if (!normalizedLocale) {
// No matching locale has translations; drop payload to save memory
console.debug('STOQ - No matching locale for translations. Available:', Object.keys(translations || {}));
delete settings.translations;
return settings;
}
console.debug(`STOQ - Applying translations for normalized locale: ${normalizedLocale} (original: ${window._RestockRocketConfig.locale})`);
const translatedFields = translations[normalizedLocale];
if (translatedFields && typeof translatedFields === 'object') {
Object.keys(translatedFields).forEach(function(key) {
const value = translatedFields[key];
if (value !== null && value !== undefined && value !== '') {
settings[key] = value;
}
});
} else {
console.debug('STOQ - No translated fields found for locale:', normalizedLocale);
}
delete settings.translations;
return settings;
} catch (e) {
console.debug('STOQ - error applying translations:', e);
return settings;
}
}
// Setup event listener for cart selling plan updates
// This must be called before any scripts are loaded to avoid race conditions
function setupCartSellingPlanUpdater(settings) {
if (!settings || !settings.preorder_enabled) {
return;
}
// Listen for stoq:preorder-api-ready event dispatched by preorder.js
window.addEventListener('stoq:preorder-api-ready', function(event) {
console.debug('STOQ - Preorder API ready, updating cart selling plans');
if (window._RestockRocket && window._RestockRocket.update.
CartSellingPlans) {
window._RestockRocket.updateCartSellingPlans()
.then(hasUpdates => {
if (hasUpdates) {
console.debug('STOQ - cart selling plans updated successfully');
} else {
console.debug('STOQ - no cart selling plan updates needed');
}
})
.catch(error => {
console.error('STOQ - error updating cart selling plans:', error);
});
}
});
}
// First try to get settings from metafields with expiry check
const cachedSettings = window._RestockRocketConfig.cachedSettings;
const validCachedSettings = cachedSettings ? checkSettingsExpiry(cachedSettings) : null;
if (validCachedSettings) {
console.debug('STOQ - using cached settings');
initializeScripts(validCachedSettings);
} else {
console.debug('STOQ - fetching fresh settings');
const headers = {
'X-Shopify-Shop-Domain': window._RestockRocketConfig.shop || window.Shopify.shop,
'ngrok-skip-browser-warning': 'skip'
};
if (window.Shopify?.theme?.role === 'main') {
headers['X-Shopify-Theme-Schema-Name'] = window.Shopify.theme.schema_name;
headers['X-Shopify-Theme-Schema-Version'] = window.Shopify.theme.schema_version;
headers['X-Shopify-Theme-Store-Id'] = window.Shopify.theme.theme_store_id;
}
fetch(
`${window._RestockRocketConfig.host}/api/v1/setting.json?translation_locale=${window._RestockRocketConfig.normalizedLocale}`,
{ headers }
)
.then(function(response) {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(function(settings) {
initializeScripts(settings);
})
.catch(function(error) {
// If request failed and we have cached settings (even if expired), use them as fallback
if (cachedSettings) {
console.debug('STOQ - using expired cached settings as fallback');
initializeScripts(cachedSettings);
} else {
.SR Suntour NVX30, coil spring, preload adjuster, 100 mm QR, 60 mm travel console.error('STOQ - failed to load settings:', error);
}
})
.catch(function(e) {
console.error(e)
})
}
function initializeScripts(settings) {
settings = applyTranslations(settings);
window._RestockRocketConfig.settings = settings;
console.debug(`STOQ - settings configured for ${window._RestockRocketConfig.pageType}`);
// Setup cart selling plan updater BEFORE loading any scripts to avoid race conditions
setupCartSellingPlanUpdater(settings);
if(settings.enable_app) {
const hijackIntegration = window._RestockRocketConfig.integrations.find(function(integration) {
return integration.type === 'hijack' && integration.enabled && integration.page_types.includes(window._RestockRocketConfig.pageType);
})
if(window._RestockRocketConfig.pageType === 'collection' && (settings.show_button_on_collection || settings.preorder_collection_enabled)) {
createRestockRocketScript(window._RestockRocketConfig.scriptUrlCollection);
} else if(window._RestockRocketConfig.pageType === 'index' && (settings.show_button_on_index || settings.preorder_index_enabled)) {
createRestockRocketScript(window._RestockRocketConfig.scriptUrlCollection);
} else if(window._RestockRocketConfig.pageType === 'search' && (settings.show_button_on_search || settings.preorder_search_enabled)) {
createRestockRocketScript(window._RestockRocketConfig.scriptUrlCollection);
} else if(window._RestockRocketConfig.pageType === 'page' && (settings.show_button_on_page || settings.preorder_page_enabled)) {
createRestockRocketScript(window._RestockRocketConfig.scriptUrlCollection);
} else if(window._RestockRocketConfig.pageType === 'product') {
createRestockRocketScript(window._RestockRocketConfig.scriptUrlProduct);
} else if(hijackIntegration) {
createRestockRocketScript(window._RestockRocketConfig.scriptUrlCollection);
} else {
console.debug(`STOQ - no scripts enabled for ${window._RestockRocketC.
onfig.pageType}`);
}
// Dispatch custom event when app is loaded
// Cart selling plan updates will be triggered by stoq:preorder-api-ready event
const appLoadedEvent = new CustomEvent('stoq:loaded', {
detail: {
pageType: window._RestockRocketConfig.pageType,
enabled: settings.enable_app,
settings: settings,
preorderEnabled: settings.preorder_enabled
}
});
console.debug('STOQ - dispatching app loaded event');
window.dispatchEvent(appLoadedEvent);
}
}
Shimano FH-QC300-HM, 32-hole, CentreLock, 8-/9-/10-/11-speed, 135x5 mm QR
Size:
Voile 12″ Nano Strap
£13.00Size:
L, XL
ProWheel alloy, 175 mm length
Product Details
Size:
XS, S, M, L, XL
Shimano RT10, CenterLock, 160 mm
The all-new NANO Series, Voiles smallest straps yet! 1/2″ thick, this micro version of our time tested tiedown offers the same versatility in an even smaller package.
Inspired by a few clever users’ modifications to our standard Voile Straps, the all-new Voile Straps Nano Series is designed with the minimalist in mind. They are available in three sizes, each of which will accommodate a load as narrow as a ballpoint pen. They feature the same weatherproof and UV-resistant material that you know and love. They are textured for extra grip, and are fitted with a glass-filled nylon buckle. So when you need a tiny strap that will over deliver, the Nano Series helps you keep it together.
{
"@context": "http://schema.org/",
"@type": "Product",
"name": "Trek Verve+ 3 Lowstep Gen 2",
"url": "https:\/\/projektride.co.uk\/products\/trek-verve-3-lowstep-gen-2","image": [
"https:\/\/projektride.co.uk\/cdn\/shop\/files\/Verve_Plus_3_Low_23_36942_A_Primary_1200x.webp?v=1724428657"
],"description": "Verve+ 3 Lowstep is an electric hybrid bike that gives your daily cruises, commutes and workouts a boost. It's equipped with a powerful Bosch smart system motor that makes hills feel effortless. Smart system allows you to log and map activities while custom-tuning your ride to fit your needs. The Verve+ 3 Lowstep is available with four different battery sizes at 400 Wh, 545 Wh, 725 Wh and 800 Wh so you can choose what's right for you.\n*Please note – spec applies to all sizes unless listed separately\n\n\nFrameset\n\n\n\n\n\n\n\nFrame\nAlpha Smooth Aluminium, Removable Integrated Battery, internal cable routing, Motor Armour, post-mount disc, 135x5 mm QR\n\n\nFork\nSR Suntour NVX30, coil spring, preload adjuster, 100 mm QR, 60 mm travel\n\n\nMax compatible fork travel\n50 mm\n\n\n\n\n\n\n\n\nWheels\n\n\n\n\n\n\n\nHub front\nShimano TX505, CenterLock\n\n\nHub rear\nShimano FH-QC300-HM, 32-hole, CentreLock, 8-\/9-\/10-\/11-speed, 135x5 mm QR\n\n\nRim\nBontrager Connection, double-wall, 32-hole, 20 mm width, Presta valve\n\n\nTyre\nBontrager E6 Hard-Case Lite, reflective strip, 27.5x2.40\"\n\n\nMax tyre size\n700x50 mm with or without mudguards\n\n\n\n\n\n\n\n\nE-system\n\n\n\n\n\n\n\nCharger\nBosch standard 4A, 230V, smart system\n\n\nController\nBosch Intuvia 100, smart system\n\n\nComputer\nBosch LED remote, smart system\n\n\nMotor\nBosch Performance Line, 250 W, 75 Nm, 20 mph (25 km\/h in Europe)\n\n\n\n\n\n\n\n\nDrivetrain\n\n\n\n\n\n\n\nShifter\nShimano Altus M2010, 9-speed\n\n\nRear derailleur\nShimano Altus M2000, long cage\n\n\n*Crank\n\nSize: XS, S, MProWheel alloy, 170 mm length\n\n\n\n\nSize: L, XLProWheel alloy, 175 mm length\n\n\n\nChainring\nProWheel 38T narrow\/wide steel, w\/alloy guard\n\n\nCassette\nShimano HG200, 11-36, 9-speed\n\n\nChain\nKMC E9S, 9-speed\n\n\nPedal\nslip-proof pedals with reflectors\n\n\n\n\n\n\n\n\nComponents\n\n\n\n\n\n\n\nSaddle\nSelle Royal Nuvola\n\n\nSeatpost\nAlloy, suspension, 31.6 mm, 300 mm length\n\n\nHandlebar\nBontrager aluminium touring\n\n\nGrips\nHerrmans Clik, ergonomic, lock-on\n\n\n*Stem\n\nSize: XS, S, MBontrager alloy, 31.8 mm clamp, adjustable rise, Blendr-compatible, 85 mm length\n\n\n\n\nSize: L, XLBontrager alloy, 31.8 mm clamp, adjustable rise, Blendr-compatible, 105 mm length\n\n\n\nBrake\nTektro HD-M275 hydraulic disc\n\n\n*Brake rotor\n\nSize: XS, S, M, L, XLShimano EM300, CenterLock, 160 mm\n\n\n\nSize: XS, S, M, L, XLShimano RT10, CenterLock, 160 mm\n\n\nBrake Set\nTektro HD-M275 hydraulic disc\n\n\n\n\n\n\n\n\nAccessories\n\n\n\n\n\n\n\n*Light\n\nSize: XS, S, M, L, XLSpanninga S
<
a class="product__media product__media--featured"
href="/collections/all-products/products/life-systems-pocket-first-aid-kit-hire"
title="Life Systems Pocket First Aid Kit - HIRE"
aria-label="Life Systems Pocket First Aid Kit - HIRE"
style="background-image: url(//projektride.co.uk/cdn/shop/files/Screenshot2022-02-24at21.18.22_5c0e6e2d-1913-4fd1-a90d-b486895960b6_600x.png?v=1691610357)">
Life Systems Pocket First Aid Kit - HIRE[email protected]
) where on of the team will be more than happy to help.
ProjektRide Bike Shop Edinburgh
<
div class="product__media-hover-img product__media" style="background-image: url(//projektride.co.uk/cdn/shop/files/Screenshot2022-02-24at21.18.32_9d81277b-124e-4fdc-8a0f-fbfb40a9343d_600x.png?v=1691610357)">
If the item is showing in stock, we aim to post the product within 24 hours. Please allow 5 working days to receive the item. Life Systems Pocket First Aid Kit - HIRE
Postage is free on orders over £50. Orders under £50, our postage charge is £3.99.
We also have a physical store, if you are local please pop in -£0.00