diff --git a/projects/garage/BMW Z4M.stl b/projects/garage/BMW Z4M.stl
new file mode 100644
index 0000000..3c75721
Binary files /dev/null and b/projects/garage/BMW Z4M.stl differ
diff --git a/projects/garage/Z4M.scad b/projects/garage/Z4M.scad
new file mode 100644
index 0000000..663b998
--- /dev/null
+++ b/projects/garage/Z4M.scad
@@ -0,0 +1,16 @@
+module scale_uniform(f) {
+    scale([f, f, f])
+        children();
+}
+
+module z4m() {
+    // reference dimensions
+    // cube([73, 171, 51]);
+
+    scale_uniform(1.36)
+    translate([43, 63, 1.4])
+    rotate([0.4, 0, 180])
+    import("BMW Z4M.stl");
+}
+
+z4m();
\ No newline at end of file
diff --git a/projects/garage/box.scad b/projects/garage/box.scad
new file mode 100644
index 0000000..fac6e04
--- /dev/null
+++ b/projects/garage/box.scad
@@ -0,0 +1,50 @@
+function sorted(arr) = !(len(arr)>0) ? [] : let(
+    pivot   = arr[floor(len(arr)/2)],
+    lesser  = [ for (y = arr) if (y  < pivot) y ],
+    equal   = [ for (y = arr) if (y == pivot) y ],
+    greater = [ for (y = arr) if (y  > pivot) y ]
+) concat(
+    sorted(lesser), equal, sorted(greater)
+);
+
+module ccube(dimensions) {
+    ds = sorted(dimensions);
+    echo(ds.y, ds.z, 1, "// thickness", ds.x);
+    cube(dimensions);
+}
+
+module topbottom(dimensions, thickness, back_inset) {
+    ccube([dimensions.x + (thickness * 2), dimensions.y + (thickness * 2) + back_inset, thickness]);
+}
+
+module side(dimensions, thickness) {
+    ccube([thickness, dimensions.y, dimensions.z]);
+}
+
+module frontback(dimensions, thickness) {
+    ccube([dimensions.x + (thickness * 2), thickness, dimensions.z]);
+}
+
+module box(dimensions, thickness, back_inset=0) {    
+    translate([0, 0, 0]);
+    topbottom(dimensions, thickness, back_inset);
+    
+    translate([0, 0, dimensions.z + thickness])
+    topbottom(dimensions, thickness, back_inset);
+    
+    translate([0, thickness, thickness])
+    side(dimensions, thickness);
+
+    translate([dimensions.x + thickness, thickness, thickness])
+    side(dimensions, thickness);
+    
+    translate([0, dimensions.y + thickness, thickness])
+    frontback(dimensions, thickness);
+    
+    translate([0, thickness, thickness])
+    rotate([0, 0, -15])
+    mirror([0, 1, 0])
+    frontback(dimensions, thickness);
+}
+
+box([5, 5, 5], 0.5, 1);
diff --git a/projects/garage/casters.scad b/projects/garage/casters.scad
new file mode 100644
index 0000000..bd8ba9b
--- /dev/null
+++ b/projects/garage/casters.scad
@@ -0,0 +1,82 @@
+function caster_axel(wheel_r, axel_r) = [1 + axel_r, wheel_r + axel_r, 0];
+
+module caster_bracket(wheel_r, wheel_h, axel_r, plate_t, padding=0.125, $fn=$fn) {
+    plate_side = wheel_r + axel_r + 1;
+    
+    module caster_plate(
+        wheel_r,
+        axel_r,
+        plate_t,
+    ) {
+        difference() {
+            linear_extrude(plate_t)
+            polygon([
+                [0, 0],
+                [0, plate_side],
+                [2 + axel_r * 2, plate_side],
+                [plate_side, 2 + axel_r * 2],
+                [plate_side, 0],
+            ]);
+            
+            axel = caster_axel(wheel_r, axel_r);
+            translate(axel)
+            cylinder(r=axel_r, h=plate_t, $fn=$fn);
+        }
+    }
+
+    translate([0, -plate_t, 0])
+    union() {
+        translate([0, plate_t, 0]);
+        caster_plate(wheel_r, axel_r, plate_t);
+
+        translate([0, plate_t, wheel_h + (plate_t + padding * 2)])
+        caster_plate(wheel_r, axel_r, plate_t);
+        
+        cube([plate_side, plate_t, wheel_h + ((plate_t + padding) * 2)]);
+    }
+}
+
+module caster(
+    wheel_r,
+    wheel_h,
+    axel_r,
+    axel_h,
+    bearing_r=0,
+    bearing_h=0,
+    plate_t=0.125,
+    padding=0.125,
+    $fn=$fn,
+) {
+    rotate([-90, 0, -90])
+    translate([-(caster_axel(wheel_r, axel_r).y), bearing_h - (wheel_r * 2) - 1 + plate_t + padding, -((wheel_h/2) + plate_t + padding)])
+    union() {
+        caster_bracket(wheel_r, wheel_h, axel_r, plate_t, padding, $fn=$fn);
+        
+        translate(caster_axel(wheel_r, axel_r)) {
+            translate([0, 0, plate_t + padding])
+            cylinder(r = wheel_r, h=wheel_h, $fn=$fn);
+            
+            translate([0, 0, -padding]) {
+                cylinder(r = axel_r, h = (wheel_h + (2* plate_t) + (padding*4)), $fn=$fn);
+            }
+        }
+        
+        translate([caster_axel(wheel_r, axel_r).y, 0, (wheel_h/2) + plate_t + padding])
+        rotate([90, 0, 0]) {
+            cylinder(r = bearing_r, h=bearing_h);
+            
+            translate([0, 0, bearing_h])
+            cylinder(r=axel_r, h=axel_h, $fn=$fn);
+        }
+    }
+}
+
+caster(
+    // wheel (r, h)
+    5, 1, 
+    // axel (r, h)
+    0.5, 1,
+    // bearing (r, h)
+    0.75, 0.25,
+    $fn=16
+);
\ No newline at end of file
diff --git a/projects/garage/garage.scad b/projects/garage/garage.scad
new file mode 100644
index 0000000..7f4f3bb
--- /dev/null
+++ b/projects/garage/garage.scad
@@ -0,0 +1,192 @@
+use <steel-shelving.scad>
+use <Z4M.scad>
+use <tire-loft.scad>
+use <printer-rack.scad>
+
+// Note 16" stud spacing
+// Note 2.5" downgrade over run of garage; height to minimums
+
+module pass() {
+}
+
+module do() {
+    children();
+}
+
+module garage_perimeter() {
+    union() {
+        polygon([
+            [0, 0],
+            [0, 232],
+            [40, 232],
+            [40, 238],
+            [-6, 238],
+            [-6, -6],
+            [5, -6],
+            [5, 0],
+            [0, 0],
+        ]);
+
+        polygon([
+            [201, 0],
+            [196, 0],
+            [196, -6],
+            [207, -6],
+            [207, 198],
+            [207 - 72, 198],
+            [207 - 72, 238],
+            [207 - 72 - 62, 238],
+            [207 - 72 - 62, 232],
+            [207 - 72 - 6, 232],    
+            [207 - 72 - 6, 192],    
+            [201, 192],    
+        ]);
+    }
+}
+
+// walls
+union() {
+    // FIXME: Draw the walls downgrade
+    linear_extrude(height=96)
+    garage_perimeter();
+    
+    // FIXME: Draw the floor
+
+    // Garage door frame
+    translate([0, -6, 90])
+    cube([201, 6, 6]);
+    
+    // Pedestrian door frame
+    translate([0, 232, 84])
+    cube([129, 6, 12]);
+}
+
+module label(text="label",
+             textsize=4,
+             pos=[0,0,0],
+             dpos=[10,0,10],
+             linesize=0.2,
+             length=20,
+             anglexyz=[0,45,90])
+{
+    p1 = pos + dpos;
+    if ($preview) 
+        color("black") {
+            line(pos, p1, linesize);
+            translate(p1)
+                rotate($vpr)
+                        text(text, size = textsize);
+    }
+}
+
+module line(p1=[0,0,0], p2=[0,0,10], r=.1) {
+    hull() {
+        translate(p1) sphere(r);
+        translate(p2) sphere(r);
+    }
+}
+
+// car (rough, assuming driver side door open)
+translate([45 + 24 + 18, 10, 0])
+color("blue")
+z4m();
+
+// south side workspace
+
+//// power pulls
+translate([0, 0, 44]) {
+    let(outlets=4) {
+        translate([1, 232, 2])
+        rotate([90, 0, 0])
+        cylinder(r=0.5, h=16 + 48 * (outlets - 1));
+        
+        for(i=[0:outlets-1]) {
+            translate([0, 232 - 4 - 16 - i*48, 0])
+            cube([3, 4, 4]);
+        }
+    }
+}
+
+//// printer rack
+translate([4, 232 - 37, 0]) {
+    pass()
+    do() {
+        cube([42, 24, 92]);
+        label("servers", pos=[21, 12, 92]);
+    }
+    do() {
+        translate([33, 0, 0])
+        rotate([0, 0, 90])
+        printer_rack();
+        label("printers", pos=[19, 21, 80]);
+    }
+}
+
+toolchest_size=44;
+
+//// tool chest
+translate([4, 232 - 37 - 1 - toolchest_size, 0]) {
+    do() {
+        color("red")
+        cube([18.6, toolchest_size, 42.5]);
+    
+        label("Tool chest", pos=[9.3, 25, 45.2]);
+    }
+}
+
+//// worktop
+let(tops=2)
+translate([24 + 1, 232 - 1 - 37 - 1 - toolchest_size - 1- (48 * tops), 0]) {
+    rotate([0, 0, 90])
+    shelving(48 * tops, 24, 32, shelves=3);
+    label("Worktop", pos=[-12, (48*tops)/2, 32]);
+}
+
+//// bike hanger
+pass()
+cube([50, 33, 60]);
+
+// north side storage
+translate([201 - 24 - 1, 1, 0]) {
+    for (i=[0:2]) {
+        translate([0, (48 + 1) * i, 0]) {
+            color("red")
+            shelving(24, 48, 78);
+            label("Deep storage", pos=[12, 24, 90]);
+        }
+    }
+}
+
+// Current tire rack
+translate([201, 148, 65]) {
+    rotate([0, 0, 90])
+    tire_loft();
+    label("Tire storage", pos=[-14.5, 22, 30]);
+}
+
+translate([201, 148, 32])
+rotate([0, 0, 90])
+tire_loft();
+
+// sherpa
+translate([201 - 13, 192, 0])
+rotate([0, 0, 270])
+cube([42, 12, 25]);
+
+// trash can
+translate([90, 232-14, 0]) {
+    let (height=28, wall=0.25)
+    difference() {
+        cylinder(h=height, d=23);
+        translate([0, 0, wall])
+        cylinder(h=height, d=23 - (wall * 2));
+    }
+}
+
+// IT gear
+translate([129-19, 232-32, 0]) {
+    translate([0, 0, 84])
+    cube([19, 24, 15]);
+    
+    cube([24, 24, 32]);
+}
diff --git a/projects/garage/printer-rack.scad b/projects/garage/printer-rack.scad
new file mode 100644
index 0000000..f5faf7d
--- /dev/null
+++ b/projects/garage/printer-rack.scad
@@ -0,0 +1,48 @@
+use <box.scad>
+use <casters.scad>
+
+padding = 1.5;
+mdf_thickness = 0.75;
+pin_inset = 3;
+
+function padded(dims, padding) = [for(e=dims) e+padding];
+
+// dimensions for things
+prusa = padded([31.5, 31.5, 35.5], padding);
+cr10 = padded([19, 27, 25], padding);
+repbox = padded([19, 12.5, 12.5], padding);
+cart = [prusa.x, prusa.y, 6.75 + mdf_thickness];
+
+module cart() {
+    for(x=[pin_inset, cart.x - pin_inset])
+    for(y=[pin_inset, cart.y - pin_inset])
+    translate([x, y, 0])
+    caster(
+        // wheel (r, h)
+        3, 1, 
+        // axel (r, h)
+        0.5, 1,
+        // bearing (r, h)
+        0.75, 0.25,
+        $fn=16
+    );
+    
+    translate([0, 0, cart.z - mdf_thickness])
+    ccube([prusa.x + (mdf_thickness * 2), prusa.y + (mdf_thickness * 2), mdf_thickness]);
+}
+
+module printer_rack() {
+    translate([0, 0, 0])
+    cart();
+       
+    //translate([0, 0, cart.z])
+    //box(prusa, mdf_thickness);
+
+    translate([0, 0, cart.z])
+    box([prusa.x, prusa.y, repbox.z], mdf_thickness);
+
+    translate([0, 0, cart.z + repbox.z + mdf_thickness * 2])
+    box([prusa.x, prusa.y, cr10.z], mdf_thickness);
+}
+
+printer_rack();
\ No newline at end of file
diff --git a/projects/garage/steel-shelving.scad b/projects/garage/steel-shelving.scad
new file mode 100644
index 0000000..41f1c8d
--- /dev/null
+++ b/projects/garage/steel-shelving.scad
@@ -0,0 +1,45 @@
+module shelving_leg(height) {
+    linear_extrude(height)
+    polygon([
+        [0, 0],
+        [1, 0],
+        [1, 0.125],
+        [0.125, 0.125],
+        [0.125, 1],
+        [0, 1],
+    ]);
+}
+
+module shelving_legs(width, depth, height) {
+    union() {
+        translate([0, 0, 0])
+        rotate([0, 0, 0])
+        shelving_leg(height);
+
+        translate([width, 0, 0])
+        rotate([0, 0, 90])
+        shelving_leg(height);
+
+        translate([0, depth, 0])
+        rotate([0, 0, -90])
+        shelving_leg(height);
+
+        translate([width, depth, 0])
+        rotate([0, 0, 180])
+        shelving_leg(height);
+    }
+}
+
+module shelving_shelves(width, depth, height, shelves) {
+    for (i = [0:((height-2)/(shelves - 1)):height-2]) {
+        translate([0, 0, i])
+        cube([width, depth, 2]);
+    }
+}
+
+module shelving(width, depth, height, shelves=4) {
+    shelving_legs(width, depth, height);
+    shelving_shelves(width, depth, height, shelves);
+}
+
+shelving(48, 24, 78);
\ No newline at end of file
diff --git a/projects/garage/tire-loft.scad b/projects/garage/tire-loft.scad
new file mode 100644
index 0000000..11ff733
--- /dev/null
+++ b/projects/garage/tire-loft.scad
@@ -0,0 +1,54 @@
+// HyLoft 01031 Folding Storage TireLoft,
+
+module rounded_cylinder(r, h, n) {
+  rotate_extrude(convexity=1) {
+    offset(r=n) offset(delta=-n) square([r,h]);
+    square([n,h]);
+  }
+}
+
+module tire(dia, w, iw) {
+    difference() {
+        rounded_cylinder(dia/2, w, 1);
+        cylinder(r=(iw/2), h=w);
+    }
+}
+
+module loft_end() {
+    cube([1, 22.5, 1]);
+    cube([1, 1, 24.5]);
+    
+    translate([-0.125, 22.5, -0.75])
+    rotate([45, 0, 0])
+    cube([0.125, 1, 32]);
+}
+
+module tire_loft() {
+    color("silver") {
+        loft_end();
+        
+        translate([0, 4, 0.5])
+        rotate([0, 90, 0])
+        cylinder(d=1, h=42);
+
+        translate([0, 22, 0.5])
+        rotate([0, 90, 0])
+        cylinder(d=1, h=42);
+        
+        translate([42, 0, 0])
+        mirror([1, 0, 0])
+        loft_end();
+    }
+
+    // tires
+    for(i=[0:10:30]) {
+        let(dr=2) {
+            translate([i + 1, (28.3/2)-dr, (28.3/2)-dr])
+            rotate([0, 90])
+            color("black")
+            tire(28.3, 9.3, 19);
+        }
+    }
+}
+
+tire_loft();
\ No newline at end of file