Custom Brick Model Design Service: Professional Design, Parts List and Instructions

Not every project needs us to supply the parts. If you want a professionally designed brick model but plan to source the bricks yourself, this service gives you everything you need to do exactly that. A complete digital design, multiple renders showing the finished model from every angle, a full parts list, and step-by-step digital building instructions. Everything is ready to hand to a supplier or take to Bricklink, and we’re available to support you through buying the parts if you need us.

Here’s what the design service covers and who it’s best suited for.

What you receive

The design deliverables are the same professional standard whether we supply the parts or not. The difference is that you receive the digital files rather than everything delivered to your door as a ready to build set.

Every design only project includes a complete 3D digital model of your build, multiple high quality renders showing the finished piece from different angles so you can see exactly what you’re getting before you source a single part, a full and accurate parts list broken down by part type, colour, and quantity, and step by step digital building instructions that you can follow to build your model.

You also receive free aftercare support. If you run into questions during the build, can’t source a specific part, or want advice on a substitution, we’re available to help. The service doesn’t end at delivery.

Who this service is for

The design only service suits buyers who want the creative and technical work handled professionally but are comfortable sourcing their own parts and doing the build themselves. That typically means hobbyists and enthusiasts who already know their way around Bricklink or have used a parts supplier already and want a custom design they couldn’t produce themselves. It also suits smaller businesses or individuals who want to keep the project cost down while still getting a design that’s genuinely professional rather than something put together without specialist knowledge.

If you already have access to parts through your own supplier, or if the build itself is something you or your team want to take on as part of the experience, this is the most cost effective route to a professionally designed custom brick model. The design quality is the same regardless of whether you’re ordering a full supply commission or a design only package.

The design process

Every design only project goes through the same process as a full commission up to the point of production. You brief us on what you want built, sharing reference images and any relevant details about the subject, the scale, and the intended use. We review what you’ve sent and come back with a quote. If we need more information before we can quote accurately, we’ll suggest a short call to make sure we’ve understood everything correctly.

Once the brief is confirmed and the quote agreed, we get to work on the design. You’ll receive renders to review at key stages and can request adjustments until you’re completely satisfied with the design. We don’t issue the final files until you’ve signed off on everything. The finished package, the renders, the parts list, and the building instructions, is then delivered digitally so you can start sourcing parts straight away.

Sourcing your parts

Most clients who choose the design only service source their parts through Bricklink, which is the most widely used marketplace for individual brick parts worldwide. The parts list we provide is formatted to make the sourcing process as straightforward as possible, with each part identified by type, colour, and quantity. If you’re not familiar with Bricklink or you’re sourcing parts for the first time, our aftercare support covers this and we can advise on the best approach for your specific parts list.

We have created a video guide that will help you use Bricklink but if at any point you decide you’d prefer us to source and supply the parts rather than doing it yourself, we can discuss converting the project to a full supply commission. The design work you’ve already paid for carries over and you won’t be charged for it again.

Pricing

Design only projects are priced individually based on the complexity of the model and the time involved in the design process. Because every subject is different, the design fee varies, but you’ll always have a clear quote before committing to anything. There are no surprises and the design fee is the only cost involved in this service.

Get in touch with your brief and we’ll come back with a quote and a clear timeline for the design work.

Frequently asked questions

Can I upgrade to a full supply commission after receiving the design?

Yes. If you decide after receiving the design that you’d prefer us to source and supply the parts, we can convert the project to a full supply commission. The design fee you’ve already paid carries over and won’t be charged again.

What format are the building instructions in?

Building instructions are delivered digitally in a step-by-step format that can be accessed on any device. They follow the same format as the instructions included in our full supply commissions.

What file formats do you deliver the design in?

Design files and renders are delivered in standard image formats (jpg or png files) suitable for viewing on any device. If you have specific file format requirements, let us know at the briefing stage and we’ll accommodate them where possible.

How accurate is the parts list?

The parts list is produced directly from the digital design, so every part in the list corresponds exactly to a part in the model. Part types, colours, and quantities are all specified so you can source directly from the list without needing to interpret or convert anything.

What does free aftercare support include?

Aftercare covers questions about the build process, advice on sourcing specific parts or using Bricklink, guidance on substitutions if a particular part isn’t available, and any clarifications about the building instructions. We’re available to support you through the build for as long as you need.

How long does the design process take?

Turnaround depends on the complexity of the design. Simpler models can be turned around more quickly than complex architectural or figural builds. We’ll give you a realistic timeline at the quoting stage so you know what to expect before the work begins.

Get your custom brick model designed

If you want a professionally designed brick model without the full supply service, get in touch with your brief and we’ll come back with a quote. Free aftercare included with every design. No minimum complexity, no minimum size.

Want the parts supplied too? Find out about our full custom brick model kit service or browse all our services.

<div class="badge-base LI-profile-badge" data-locale="en_US" data-size="large" data-theme="dark" data-type="HORIZONTAL" data-vanity="ferdi-vol" data-version="v1"><a class="badge-base__link LI-simple-link" href="https://www.linkedin.com/in/%E2%9C%85-ferdi-vol-corporate-gifts/?trk=profile-badge"></a></div>
/* Auto generated, hash = 5dceu9kevqjdyuy2uw1atqrsu */
//TODO: Break this file down so that we can actually unit test it.
(function(window) {
  /**
  * Renders all unrendred LinkedIn Badges on the page
  */
  window.LIRenderAll = function () {
    var CALLBACK_NAME     = 'LIBadgeCallback', //Must match callback on helpers.js
        BADGE_NAMES       = '.LI-profile-badge, .LI-entity-badge',
        // TODO -- tracking param for other badge types
        TRACKING_PARAM    = 'profile-badge',
        responsesReceived = 0, //Keeps track of number of responses recieved for proper cleanup when finished
        expectedResponses = 0, //Keeps track of number of responses to expect
        scripts           = [ ], //Keeps track of scripts added for proper cleanup when finished
        childScripts      = {}, //Keeps track of child scripts to render
        badges            = Array.prototype.slice.call(document.querySelectorAll(BADGE_NAMES));

    var i, len, badge, rendered;
    for (i = 0, len = badges.length;  i < len; i++) {
      badge    = badges[i];
      rendered =  badge.getAttribute('data-rendered');
      if (!rendered) {
        expectedResponses++;
        badge.setAttribute('data-rendered', true);
        renderBadge(badge);
      }
    }

    function isCNDomain() {
      if (typeof window !== "undefined") {
        var hostName = window.location && window.location.hostname ||  '';
        return (/linkedin(-ei)?.cn$/).test(hostName);
      }

      return false;
    }

    function generateUrl(isEI) {
      var domainPrefix = isEI ? 'https://badges.linkedin-ei' : 'https://badges.linkedin';
      if (isCNDomain()) {
        return domainPrefix + ".cn/";
      }

      return domainPrefix + ".com/";
    }

    function getBadgeKeyQueryParams(badge) {
      return Array.prototype.slice.call(badge.attributes).filter(function (attr) {
        return attr.name.lastIndexOf('data-key-', 0) !== -1;
      }).map(function (attr) {
        // Most browsers automatically lowercase the attribute name when its being read
        // We are calling lowercase on it again to ensure consistency for any browsers that are lagging behind.
        return encodeURIComponent(attr.name.replace('data-', '').toLowerCase()) + '=' + encodeURIComponent(attr.value);
      });
    }

    /*
    * Renders a single badge on the page
    * @param badge: div element of badge to render
    */
    function renderBadge(badge) {
      var size       = badge.getAttribute('data-size'),
          locale     = badge.getAttribute('data-locale'),
          type       = badge.getAttribute('data-type'),
          theme      = badge.getAttribute('data-theme'),
          vanity     = badge.getAttribute('data-vanity'),
          version    = badge.getAttribute('data-version'),
          isEI       = badge.hasAttribute('data-ei'),
          entity     = badge.getAttribute('data-entity'),
          isCreatePage = badge.hasAttribute('data-iscreate'),
          uid        = Math.round(1000000 * Math.random()),
          baseUrl = generateUrl(isEI),
          queryParams = [
            'locale=' + encodeURIComponent(locale),
            'badgetype=' + encodeURIComponent(type),
            'badgetheme=' + encodeURIComponent(theme),
            'uid=' + encodeURIComponent(uid),
            'version=' + encodeURIComponent(version)
          ],
          url;

      if (version === 'v2') {
        baseUrl += 'view';
        queryParams.push('badgesize=' + encodeURIComponent(size));
        queryParams.push('entity=' + encodeURIComponent(entity));
        queryParams = queryParams.concat(getBadgeKeyQueryParams(badge));
      } else {
        baseUrl += 'profile';
        queryParams.push('maxsize=' + encodeURIComponent(size));
        queryParams.push('trk=' + encodeURIComponent(TRACKING_PARAM));
        queryParams.push('vanityname=' + encodeURIComponent(vanity));
      }

      if (isCreatePage) {
        queryParams.push('fromCreate=true');
      }

      url = baseUrl + '?' + queryParams.join('&');
      badge.setAttribute('data-uid' , uid);
      jsonp(url); //Calls responseHandler when done
    }

    /**
    * Handles a response from the server. Finds badge matching badgeUid and inserts badgeHtml there
    * @param badgeHtml: String representing contents of the badge
    * @param badgeUid: UID of the badge to target
    **/
    function responseHandler(badgeHtml, badgeUid) {
      responsesReceived ++;

      var i, badge, uid, isCreate;
      var defaultWidth = 330 // max possible width
      var defaultHeight = 300 // max possible height

      for (i = 0, len = badges.length; i < len; i++) {
        badge = badges[i];
        // isCreate needed to prevent reloading artdeco script tag
        isCreate = badge.getAttribute('data-iscreate');
        uid   = parseInt(badge.getAttribute('data-uid'), 10);
        if (uid === badgeUid) {
          var badgeMarkup = `<body>${badgeHtml}</body>`
          var iframe = document.createElement('iframe');
          iframe.onload = function() {
            var iframeBody = iframe.contentWindow.document.body;
            // 5 px buffer to avoid the badge border being cut off.
            iframe.setAttribute('height', (iframeBody.scrollHeight || defaultHeight) + 5);
            iframe.setAttribute('width', (iframeBody.scrollWidth || defaultWidth) + 5);
          };
          iframe.setAttribute('frameBorder', '0');
          iframe.style.display = 'block';
          badge.appendChild(iframe);
          iframe.contentWindow.document.open();
          iframe.contentWindow.document.write(badgeMarkup);
          iframe.contentWindow.document.close();
          replaceScriptTags(badge, isCreate);
        }
      }
      tryClean();
    }

  // These functions are needed because badge markup is added via innerHtml property which does not run script tags
  function replaceScriptTags(node, isCreate) {
    if (shouldReplaceNode(node, isCreate)) {
      node.parentNode.replaceChild(cloneScriptNode(node), node);
      childScripts[node.src] = true;
    } else {
      var i = 0,
          children = node.childNodes;
      while (i < children.length) {
        replaceScriptTags(children[i++], isCreate);
      }
    }
    return node;
  }

  function shouldReplaceNode(node, isCreate) {
    return isScriptNode(node) && !childScripts[node.src] && (!isCreate || (isCreate && !node.getAttribute('data-isartdeco')));
  }

  function isScriptNode(node) {
    return node.tagName === 'SCRIPT';
  }

  function cloneScriptNode(node){
    var script  = document.createElement("script");
    for( var i = node.attributes.length-1; i >= 0; i-- ) {
      script.setAttribute( node.attributes[i].name, node.attributes[i].value );
    }
    return script;
  }

    // Gets all incoming responses
    window[CALLBACK_NAME] = responseHandler;

    /**
    * Tries to clean added tags
    **/
    function tryClean() {
      //Clean up after all requests are done..
      //Accounts for people including script more than once
      var done = (responsesReceived >= expectedResponses && expectedResponses > 0) || responsesReceived >= badges.length;
      if (done) {
        delete window[CALLBACK_NAME];

        // remove all script tags
        scripts.map(function(script){
          document.body.removeChild(script);
        });

      }
    }

    /*
    * Makes Jsonp request, responses handles by CALLBACK_NAME
    * @param url String: url of server to make request to
    */
    function jsonp(url) {
      var script = document.createElement('script');
      script.src = url;
      scripts.push(script);
      document.body.appendChild(script);
    }
  };

  if (document.readyState === 'complete') {
    window.LIRenderAll();
  } else {
    window.addEventListener('load', window.LIRenderAll, false);
  }

})(window);
Popular Posts