diff --git a/graphics/workbench-gui.xcf b/graphics/workbench-gui.xcf
new file mode 100644
index 0000000..ac2b8f2
Binary files /dev/null and b/graphics/workbench-gui.xcf differ
diff --git a/src/java/mmm/tech/base/workbench/TBWBContainer.java b/src/java/mmm/tech/base/workbench/TBWBContainer.java
new file mode 100644
index 0000000..86e5554
--- /dev/null
+++ b/src/java/mmm/tech/base/workbench/TBWBContainer.java
@@ -0,0 +1,43 @@
+package mmm.tech.base.workbench;
+
+
+import mmm.MmmTech;
+import mmm.utils.gui.UGContainer;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.inventory.Slot;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.World;
+
+
+
+public class TBWBContainer
+		extends UGContainer
+{
+	public final TBWBTileEntity tileEntity;
+	public final World world;
+	public final BlockPos position;
+
+
+	public TBWBContainer( final InventoryPlayer playerInv , final TBWBTileEntity tileEntity )
+	{
+		this.tileEntity = tileEntity;
+		this.world = tileEntity.getWorld( );
+		this.position = tileEntity.getPos( );
+
+		this.addPlayerInventory( Slot::new , playerInv , 28 , 112 );
+		this.slotGroups.nextGroup( );
+		this.addGrid( Slot::new , tileEntity.storage , 8 , 13 );
+		this.slotGroups.endGroups( );
+	}
+
+
+	@Override
+	public boolean canInteractWith( final EntityPlayer player )
+	{
+		return this.world.getBlockState( this.position ).getBlock( ) == MmmTech.MACHINES.WORKBENCH
+				&& player.getDistanceSq( this.position.getX( ) + .5 , this.position.getY( ) + .5 ,
+						this.position.getZ( ) + .5 ) <= 64.;
+	}
+
+}
diff --git a/src/java/mmm/tech/base/workbench/TBWBGui.java b/src/java/mmm/tech/base/workbench/TBWBGui.java
new file mode 100644
index 0000000..ac5b91d
--- /dev/null
+++ b/src/java/mmm/tech/base/workbench/TBWBGui.java
@@ -0,0 +1,40 @@
+package mmm.tech.base.workbench;
+
+
+import mmm.Mmm;
+import mmm.utils.gui.A_UGContainerScreen;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.fml.relauncher.Side;
+import net.minecraftforge.fml.relauncher.SideOnly;
+
+
+
+@SideOnly( Side.CLIENT )
+public class TBWBGui
+		extends A_UGContainerScreen< TBWBContainer >
+{
+	private static final ResourceLocation BACKGROUND = new ResourceLocation( Mmm.ID , "textures/gui/workbench.png" );
+
+
+	public TBWBGui( final InventoryPlayer inventoryPlayer , final TBWBTileEntity tileEntity )
+	{
+		super( new TBWBContainer( inventoryPlayer , tileEntity ) );
+		this.container.slotGroups.showAll( );
+		this.xSize = 216;
+		this.ySize = 194;
+	}
+
+
+	@Override
+	protected void drawGuiContainerBackgroundLayer( final float partialTicks , final int mouseX , final int mouseY )
+	{
+		GlStateManager.color( 1f , 1f , 1f , 1f );
+		GlStateManager.enableBlend( );
+		GlStateManager.disableLighting( );
+		this.mc.getTextureManager( ).bindTexture( TBWBGui.BACKGROUND );
+		this.drawTexturedModalRect( this.guiLeft , this.guiTop , 0 , 0 , this.xSize , this.ySize );
+	}
+
+}
diff --git a/src/java/mmm/tech/base/workbench/TBWBTileEntity.java b/src/java/mmm/tech/base/workbench/TBWBTileEntity.java
new file mode 100644
index 0000000..a4ad3f4
--- /dev/null
+++ b/src/java/mmm/tech/base/workbench/TBWBTileEntity.java
@@ -0,0 +1,143 @@
+package mmm.tech.base.workbench;
+
+
+import mmm.MmmTech;
+import mmm.utils.UInventoryGrid;
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.NetworkManager;
+import net.minecraft.network.play.server.SPacketUpdateTileEntity;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.IWorldNameable;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.Constants.NBT;
+
+
+
+public class TBWBTileEntity
+		extends TileEntity
+		implements IWorldNameable
+{
+	private class Inventory
+			extends UInventoryGrid
+	{
+
+		public Inventory( final String name , final int width , final int height )
+		{
+			super( name , width , height );
+		}
+
+
+		@Override
+		public void markDirty( )
+		{
+			TBWBTileEntity.this.markDirty( );
+		}
+
+	}
+
+	public final UInventoryGrid storage;
+	private String customName;
+
+
+	public TBWBTileEntity( )
+	{
+		super( );
+		this.storage = new Inventory( "Storage" , 3 , 5 );
+	}
+
+
+	@Override
+	public String getName( )
+	{
+		return this.hasCustomName( ) ? this.customName : "tile.mmm.tech.base.workbench.name";
+	}
+
+
+	@Override
+	public boolean hasCustomName( )
+	{
+		return this.customName != null && !this.customName.isEmpty( );
+	}
+
+
+	public void setCustomName( final String name )
+	{
+		this.customName = name;
+	}
+
+
+	@Override
+	public boolean shouldRefresh( final World world , final BlockPos pos , final IBlockState oldState ,
+			final IBlockState newSate )
+	{
+		return newSate.getBlock( ) != MmmTech.MACHINES.WORKBENCH;
+	}
+
+
+	@Override
+	public SPacketUpdateTileEntity getUpdatePacket( )
+	{
+		final NBTTagCompound compound = new NBTTagCompound( );
+		this.writeSyncData( compound );
+		return new SPacketUpdateTileEntity( this.pos , 0 , compound );
+	}
+
+
+	@Override
+	public NBTTagCompound getUpdateTag( )
+	{
+		final NBTTagCompound compound = new NBTTagCompound( );
+		this.writeToNBT( compound );
+		return compound;
+	}
+
+
+	@Override
+	public void onDataPacket( final NetworkManager net , final SPacketUpdateTileEntity pkt )
+	{
+		if ( this.worldObj.isRemote ) {
+			this.readSyncData( pkt.getNbtCompound( ) );
+			final IBlockState state = this.worldObj.getBlockState( this.pos );
+			this.worldObj.notifyBlockUpdate( this.pos , state , state , 3 );
+		}
+	}
+
+
+	@Override
+	public void readFromNBT( final NBTTagCompound compound )
+	{
+		super.readFromNBT( compound );
+		if ( compound.hasKey( "CustomName" , 8 ) ) {
+			this.customName = compound.getString( "CustomName" );
+		}
+		this.storage.deserializeNBT( compound.getTagList( "Storage" , NBT.TAG_COMPOUND ) );
+		this.readSyncData( compound );
+	}
+
+
+	private void readSyncData( final NBTTagCompound compound )
+	{
+		// TODO Auto-generated method stub
+	}
+
+
+	@Override
+	public NBTTagCompound writeToNBT( final NBTTagCompound compound )
+	{
+		super.writeToNBT( compound );
+		if ( this.hasCustomName( ) ) {
+			compound.setString( "CustomName" , this.customName );
+		}
+		compound.setTag( "Storage" , this.storage.serializeNBT( ) );
+		this.writeSyncData( compound );
+		return compound;
+	}
+
+
+	private void writeSyncData( final NBTTagCompound compound )
+	{
+		// TODO Auto-generated method stub
+	}
+}
diff --git a/src/java/mmm/tech/base/workbench/TBWorkbench.java b/src/java/mmm/tech/base/workbench/TBWorkbench.java
index 5b70ccc..2116713 100644
--- a/src/java/mmm/tech/base/workbench/TBWorkbench.java
+++ b/src/java/mmm/tech/base/workbench/TBWorkbench.java
@@ -1,10 +1,10 @@
 package mmm.tech.base.workbench;
 
 
+import mmm.core.CGui;
 import mmm.core.CRegistry;
 import mmm.core.api.I_RecipeRegistrar;
-import mmm.tech.base.alloy_furnace.TBAFBlock;
-import net.minecraft.block.Block;
+import net.minecraft.block.BlockContainer;
 import net.minecraft.block.BlockHorizontal;
 import net.minecraft.block.SoundType;
 import net.minecraft.block.material.Material;
@@ -13,10 +13,17 @@ import net.minecraft.block.state.BlockStateContainer;
 import net.minecraft.block.state.IBlockState;
 import net.minecraft.creativetab.CreativeTabs;
 import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
 import net.minecraft.init.Blocks;
 import net.minecraft.init.Items;
+import net.minecraft.inventory.InventoryHelper;
 import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.EnumBlockRenderType;
 import net.minecraft.util.EnumFacing;
+import net.minecraft.util.EnumHand;
+import net.minecraft.util.Mirror;
+import net.minecraft.util.Rotation;
 import net.minecraft.util.math.BlockPos;
 import net.minecraft.world.World;
 import net.minecraftforge.fml.common.registry.GameRegistry;
@@ -24,7 +31,7 @@ import net.minecraftforge.fml.common.registry.GameRegistry;
 
 
 public class TBWorkbench
-		extends Block
+		extends BlockContainer
 		implements I_RecipeRegistrar
 {
 	public static final PropertyDirection FACING = BlockHorizontal.FACING;
@@ -44,6 +51,10 @@ public class TBWorkbench
 
 		CRegistry.setIdentifiers( this , "tech" , "base" , "workbench" );
 		CRegistry.addBlock( this );
+		GameRegistry.registerTileEntity( TBWBTileEntity.class , "mmm:tech/base/workbench" );
+		CGui.registerTileEntityGUI( TBWBTileEntity.class , //
+				"mmm.tech.base.workbench.TBWBContainer" , //
+				"mmm.tech.base.workbench.TBWBGui" );
 	}
 
 
@@ -84,6 +95,60 @@ public class TBWorkbench
 			final EntityLivingBase placer , final ItemStack stack )
 	{
 		worldIn.setBlockState( pos , state.withProperty( //
-				TBAFBlock.FACING , placer.getHorizontalFacing( ).getOpposite( ) ) , 2 );
+				TBWorkbench.FACING , placer.getHorizontalFacing( ).getOpposite( ) ) , 2 );
+	}
+
+
+	@Override
+	public IBlockState withRotation( final IBlockState state , final Rotation rot )
+	{
+		return state.withProperty( TBWorkbench.FACING , rot.rotate( state.getValue( TBWorkbench.FACING ) ) );
+	}
+
+
+	@Override
+	public IBlockState withMirror( final IBlockState state , final Mirror mirrorIn )
+	{
+		return state.withRotation( mirrorIn.toRotation( state.getValue( TBWorkbench.FACING ) ) );
+	}
+
+
+	@Override
+	public TileEntity createNewTileEntity( final World worldIn , final int meta )
+	{
+		return new TBWBTileEntity( );
+	}
+
+
+	@Override
+	public EnumBlockRenderType getRenderType( final IBlockState state )
+	{
+		return EnumBlockRenderType.MODEL;
+	}
+
+
+	@Override
+	public boolean onBlockActivated( final World worldIn , final BlockPos pos , final IBlockState state ,
+			final EntityPlayer playerIn , final EnumHand hand , final ItemStack heldItem , final EnumFacing side ,
+			final float hitX , final float hitY , final float hitZ )
+	{
+		final TileEntity te = worldIn.getTileEntity( pos );
+		if ( ! ( te instanceof TBWBTileEntity ) || playerIn.isSneaking( ) ) {
+			return false;
+		}
+		CGui.openTileEntityGUI( playerIn , worldIn , pos );
+		return true;
+	}
+
+
+	@Override
+	public void breakBlock( final World worldIn , final BlockPos pos , final IBlockState state )
+	{
+		final TileEntity tileEntity = worldIn.getTileEntity( pos );
+		if ( tileEntity instanceof TBWBTileEntity ) {
+			final TBWBTileEntity wbte = (TBWBTileEntity) tileEntity;
+			InventoryHelper.dropInventoryItems( worldIn , pos , wbte.storage );
+		}
+		super.breakBlock( worldIn , pos , state );
 	}
 }
diff --git a/src/java/mmm/utils/gui/UGContainer.java b/src/java/mmm/utils/gui/UGContainer.java
index 36c3370..6cbfaec 100644
--- a/src/java/mmm/utils/gui/UGContainer.java
+++ b/src/java/mmm/utils/gui/UGContainer.java
@@ -1,6 +1,7 @@
 package mmm.utils.gui;
 
 
+import mmm.utils.UInventoryGrid;
 import net.minecraft.inventory.Container;
 import net.minecraft.inventory.IInventory;
 import net.minecraft.inventory.Slot;
@@ -33,6 +34,24 @@ public abstract class UGContainer
 	}
 
 
+	public void addGrid( final I_SlotFactory slotAdder , final UInventoryGrid inv , final int x , final int y )
+	{
+		this.addGrid( slotAdder , inv , x , y , 2 , 2 );
+	}
+
+
+	public void addGrid( final I_SlotFactory slotAdder , final UInventoryGrid inv , final int x , final int y ,
+			final int xSpacing , final int ySpacing )
+	{
+		for ( int row = 0 , i = 0 ; row < inv.height ; ++row ) {
+			for ( int column = 0 ; column < inv.width ; ++column , ++i ) {
+				this.addSlotToContainer( slotAdder.createSlot( inv , i , //
+						x + column * ( 16 + xSpacing ) , y + row * ( 16 + ySpacing ) ) );
+			}
+		}
+	}
+
+
 	public void addPlayerInventory( final I_SlotFactory slotAdder , final IInventory inv , final int x , final int y ,
 			final int spacing )
 	{
diff --git a/src/java/mmm/utils/gui/UGSlotGroups.java b/src/java/mmm/utils/gui/UGSlotGroups.java
index eb83d46..c5ec2aa 100644
--- a/src/java/mmm/utils/gui/UGSlotGroups.java
+++ b/src/java/mmm/utils/gui/UGSlotGroups.java
@@ -44,6 +44,25 @@ public class UGSlotGroups
 	}
 
 
+	public void hideAll( )
+	{
+		for ( int i = 0 ; i < this.slotX.length ; i++ ) {
+			final Slot slot = this.slots.get( i );
+			slot.xDisplayPosition = slot.yDisplayPosition = -4000;
+		}
+	}
+
+
+	public void showAll( )
+	{
+		for ( int i = 0 ; i < this.slotX.length ; i++ ) {
+			final Slot slot = this.slots.get( i );
+			slot.xDisplayPosition = this.slotX[ i ];
+			slot.yDisplayPosition = this.slotY[ i ];
+		}
+	}
+
+
 	public UGSlotGroups showGroup( final int index )
 	{
 		final int first = this.firstSlots.getInt( index );
diff --git a/src/resources/assets/mmm/lang/en_US.lang b/src/resources/assets/mmm/lang/en_US.lang
index 921495b..5186c70 100644
--- a/src/resources/assets/mmm/lang/en_US.lang
+++ b/src/resources/assets/mmm/lang/en_US.lang
@@ -80,6 +80,8 @@ tile.mmm.materials.trap.mud.name=Mud
 tile.mmm.materials.trap.swamp_pit.name=Silty Quicksand
 
 
+tile.mmm.tech.base.workbench.name=Workbench
+
 tile.mmm.tech.base.alloy_furnace.inactive.name=Alloy Furnace
 container.mmm.alloy_furnace.contents=Furnace Contents
 container.mmm.alloy_furnace.recipe=Alloy Selection
diff --git a/src/resources/assets/mmm/textures/gui/workbench.png b/src/resources/assets/mmm/textures/gui/workbench.png
new file mode 100644
index 0000000..ae128ce
Binary files /dev/null and b/src/resources/assets/mmm/textures/gui/workbench.png differ