diff --git a/FWGL/Backend/JavaScript.hs b/FWGL/Backend/JavaScript.hs
new file mode 100644
--- /dev/null
+++ b/FWGL/Backend/JavaScript.hs
@@ -0,0 +1,587 @@
+{-# LANGUAGE NullaryTypeClasses, TypeFamilies, UndecidableInstances #-}
+
+{-| The GHCJS/WebGL backend. This just exports the instances for 'BackendIO'
+    and 'GLES'. -}
+module FWGL.Backend.JavaScript () where
+
+import Control.Applicative
+import Control.Concurrent
+import qualified Data.HashMap.Strict as H
+import Data.IORef
+import Data.Word
+import FRP.Yampa
+import FWGL.Backend
+import FWGL.Backend.JavaScript.Event
+import qualified FWGL.Backend.JavaScript.WebGL as JS
+import FWGL.Graphics.Color
+import FWGL.Input
+import FWGL.Vector
+import GHCJS.Foreign
+import GHCJS.Types
+import GHCJS.Marshal
+
+foreign import javascript unsafe
+        "var img = new Image();                        \
+        \img.src = $1;                                 \
+        \img.onload = function() { return $2(img); };  "
+        loadImageRaw :: JSString -> JSFun (JSRef a -> IO ()) -> IO ()
+
+foreign import javascript unsafe "document.querySelector($1)"
+        query :: JSString -> IO (JSRef a)
+
+foreign import javascript unsafe "$2.getAttribute($1)"
+        getAttributeRaw :: JSString -> JSRef a -> IO JSString
+
+getAttribute :: String -> JSRef a -> IO String
+getAttribute attr e = fromJSString <$> getAttributeRaw (toJSString attr) e
+
+foreign import javascript unsafe "window.requestAnimationFrame($1)"
+        requestAnimationFrame :: JSFun (JSRef Double -> IO ()) -> IO ()
+
+foreign import javascript unsafe "$1.focus()" focus :: JSRef a -> IO ()
+
+instance BackendIO where
+        loadImage url f = asyncCallback1 NeverRetain callback
+                          >>= loadImageRaw (toJSString url) 
+                where callback img =
+                        do (Just w) <- getProp "width" img >>= fromJSRef
+                           (Just h) <- getProp "height" img >>= fromJSRef
+                           f (img, w, h)
+
+        setup initState draw sigf =
+                do element <- query $ toJSString "canvas"
+                   eventSrc <- source handledEvents element
+                   ctx <- JS.getCtx element
+                   (Just w) <- getProp "clientWidth" element >>= fromJSRef
+                   (Just h) <- getProp "clientHeight" element >>= fromJSRef
+                   focus element -- ... no
+                   drawStateRef <- initState w h ctx >>= newIORef
+                   reactStateRef <- reactInit (return $ initInput w h)
+                                              (\ _ _ -> actuate ctx drawStateRef)
+                                              sigf
+                   onFrame $ frame reactStateRef eventSrc Nothing
+                where frame rsf src last crf =
+                        do events <- clear src
+                           (Just cur) <- fromJSRef crf
+                           let tm = case last of
+                                         Just l -> cur - l
+                                         Nothing -> 0
+                           react rsf (tm, Just $ Input events)
+                           onFrame $ frame rsf src (Just cur)
+        
+                      onFrame handler = asyncCallback1 NeverRetain handler
+                                        >>= requestAnimationFrame
+
+                      initInput w h = Input $ H.singleton Resize [
+                                EventData {
+                                        dataFramebufferSize = Just (w, h),
+                                        dataPointer = Nothing,
+                                        dataButton = Nothing,
+                                        dataKey = Nothing
+                                }]
+                                     
+                      actuate ctx ref out = readIORef ref >>=
+                                            draw out ctx >>=
+                                         -- execDraw (drawBegin >> drawScene s) >>=
+                                            writeIORef ref >> return False
+                      handledEvents = [ MouseUp
+                                      , MouseDown
+                                      , MouseMove
+                                      , KeyUp
+                                      , KeyDown
+                                      , Resize ]
+
+instance GLES where
+        type Ctx = JS.Ctx
+        type GLEnum = Word
+        type GLUInt = Word
+        type GLInt = Int
+        type GLPtr = Word
+        type GLPtrDiff = Word
+        type GLSize = Int
+        type GLString = JSString
+        type GLBool = Bool
+        type Buffer = JS.Buffer
+        type UniformLocation = JS.UniformLocation
+        type Texture = JS.Texture
+        type Shader = JS.Shader
+        type Program = JS.Program
+        type FrameBuffer = JS.FrameBuffer
+        type RenderBuffer = JS.RenderBuffer
+        -- type ActiveInfo = JS.ActiveInfo
+        -- type ShaderPrecisionFormat = JS.ShaderPrecisionFormat
+        type Array = JS.ArrayBufferView
+        type Float32Array = JS.Float32Array
+        type Int32Array = JS.Int32Array
+        type Image = JS.Image
+
+        true = True
+        false = False
+        nullGLPtr = 0
+        toGLString = toJSString
+        noBuffer = JS.noBuffer
+        noTexture = JS.noTexture
+        noArray = JS.noArray
+
+        encodeM2 (M2 (V2 a1 a2) (V2 b1 b2)) = JS.listToJSArray [ a1, a2, b1, b2]
+                                              >>= JS.float32Array
+
+        encodeM3 (M3 (V3 a1 a2 a3)
+                     (V3 b1 b2 b3)
+                     (V3 c1 c2 c3)) = JS.listToJSArray [ a1, a2, a3
+                                                       , b1, b2, b3
+                                                       , c1, c2, c3]
+                                      >>= JS.float32Array
+        encodeM4 (M4 (V4 a1 a2 a3 a4)
+                     (V4 b1 b2 b3 b4)
+                     (V4 c1 c2 c3 c4)
+                     (V4 d1 d2 d3 d4) ) = JS.listToJSArray [ a1, a2, a3, a4
+                                                           , b1, b2, b3, b4
+                                                           , c1, c2, c3, c4
+                                                           , d1, d2, d3, d4 ]
+                                          >>= JS.float32Array
+        encodeFloats v = JS.listToJSArray v >>= JS.float32View
+
+        -- TODO: decent implementation
+        encodeV2s v = JS.toJSArray next (False, v) >>= JS.float32View
+                where next (False, xs@(V2 x _ : _)) = Just (x, (True, xs))
+                      next (True, V2 _ y : xs) = Just (y, (False, xs))
+                      next (_, []) = Nothing
+
+        encodeV3s v = JS.toJSArray next (0, v) >>= JS.float32View
+                where next (0, xs@(V3 x _ _ : _)) = Just (x, (1, xs))
+                      next (1, xs@(V3 _ y _ : _)) = Just (y, (2, xs))
+                      next (2, V3 _ _ z : xs) = Just (z, (0, xs))
+                      next (_, []) = Nothing
+
+        -- TODO
+        encodeV4s = error "encodeV4s: TODO"
+
+        encodeUShorts v = JS.listToJSArray v >>= JS.uint16View
+
+        encodeColors v = JS.toJSArray next (0, v) >>= JS.uint8View
+                where next (0, xs@(Color x _ _ _ : _)) = Just (x, (1, xs))
+                      next (1, xs@(Color _ y _ _ : _)) = Just (y, (2, xs))
+                      next (2, xs@(Color _ _ z _ : _)) = Just (z, (3, xs))
+                      next (3, Color _ _ _ w : xs) = Just (w, (0, xs))
+                      next (_, []) = Nothing
+
+        glActiveTexture = JS.glActiveTexture
+        glAttachShader = JS.glAttachShader
+        glBindAttribLocation = JS.glBindAttribLocation
+        glBindBuffer = JS.glBindBuffer
+        glBindFramebuffer = JS.glBindFramebuffer
+        glBindRenderbuffer = JS.glBindRenderbuffer
+        glBindTexture = JS.glBindTexture
+        glBlendColor = JS.glBlendColor
+        glBlendEquation = JS.glBlendEquation
+        glBlendEquationSeparate = JS.glBlendEquationSeparate
+        glBlendFunc = JS.glBlendFunc
+        glBlendFuncSeparate = JS.glBlendFuncSeparate
+        glBufferData = JS.glBufferData
+        glBufferSubData = JS.glBufferSubData
+        glCheckFramebufferStatus = JS.glCheckFramebufferStatus
+        glClear = JS.glClear
+        glClearColor = JS.glClearColor
+        glClearDepth = JS.glClearDepth
+        glClearStencil = JS.glClearStencil
+        glColorMask = JS.glColorMask
+        glCompileShader = JS.glCompileShader
+        glCompressedTexImage2D = JS.glCompressedTexImage2D
+        glCompressedTexSubImage2D = JS.glCompressedTexSubImage2D
+        glCopyTexImage2D = JS.glCopyTexImage2D
+        glCopyTexSubImage2D = JS.glCopyTexSubImage2D
+        glCreateBuffer = JS.glCreateBuffer
+        glCreateFramebuffer = JS.glCreateFramebuffer
+        glCreateProgram = JS.glCreateProgram
+        glCreateRenderbuffer = JS.glCreateRenderbuffer
+        glCreateShader = JS.glCreateShader
+        glCreateTexture = JS.glCreateTexture
+        glCullFace = JS.glCullFace
+        glDeleteBuffer = JS.glDeleteBuffer
+        glDeleteFramebuffer = JS.glDeleteFramebuffer
+        glDeleteProgram = JS.glDeleteProgram
+        glDeleteRenderbuffer = JS.glDeleteRenderbuffer
+        glDeleteShader = JS.glDeleteShader
+        glDeleteTexture = JS.glDeleteTexture
+        glDepthFunc = JS.glDepthFunc
+        glDepthMask = JS.glDepthMask
+        glDepthRange = JS.glDepthRange
+        glDetachShader = JS.glDetachShader
+        glDisable = JS.glDisable
+        glDisableVertexAttribArray = JS.glDisableVertexAttribArray
+        glDrawArrays = JS.glDrawArrays
+        glDrawElements = JS.glDrawElements
+        glEnable = JS.glEnable
+        glEnableVertexAttribArray = JS.glEnableVertexAttribArray
+        glFinish = JS.glFinish
+        glFlush = JS.glFlush
+        glFramebufferRenderbuffer = JS.glFramebufferRenderbuffer
+        glFramebufferTexture2D = JS.glFramebufferTexture2D
+        glFrontFace = JS.glFrontFace
+        glGenerateMipmap = JS.glGenerateMipmap
+        -- glGetActiveAttrib = JS.glGetActiveAttrib
+        -- glGetActiveUniform = JS.glGetActiveUniform
+        glGetAttribLocation = JS.glGetAttribLocation
+        -- glGetBufferParameter = JS.glGetBufferParameter
+        -- glGetParameter = JS.glGetParameter
+        glGetError = JS.glGetError
+        -- glGetFramebufferAttachmentParameter = JS.glGetFramebufferAttachmentParameter
+        glGetProgramInfoLog = JS.glGetProgramInfoLog
+        -- glGetRenderbufferParameter = JS.glGetRenderbufferParameter
+        -- glGetShaderParameter = JS.glGetShaderParameter
+        -- glGetShaderPrecisionFormat = JS.glGetShaderPrecisionFormat
+        glGetShaderInfoLog = JS.glGetShaderInfoLog
+        glGetShaderSource = JS.glGetShaderSource
+        -- glGetTexParameter = JS.glGetTexParameter
+        -- glGetUniform = JS.glGetUniform
+        glGetUniformLocation = JS.glGetUniformLocation
+        -- glGetVertexAttrib = JS.glGetVertexAttrib
+        -- glGetVertexAttribOffset = JS.glGetVertexAttribOffset
+        glHint = JS.glHint
+        glIsBuffer = JS.glIsBuffer
+        glIsEnabled = JS.glIsEnabled
+        glIsFramebuffer = JS.glIsFramebuffer
+        glIsProgram = JS.glIsProgram
+        glIsRenderbuffer = JS.glIsRenderbuffer
+        glIsShader = JS.glIsShader
+        glIsTexture = JS.glIsTexture
+        glLineWidth = JS.glLineWidth
+        glLinkProgram = JS.glLinkProgram
+        glPixelStorei = JS.glPixelStorei
+        glPolygonOffset = JS.glPolygonOffset
+        glReadPixels = JS.glReadPixels
+        glRenderbufferStorage = JS.glRenderbufferStorage
+        glSampleCoverage = JS.glSampleCoverage
+        glScissor = JS.glScissor
+        glShaderSource = JS.glShaderSource
+        glStencilFunc = JS.glStencilFunc
+        glStencilFuncSeparate = JS.glStencilFuncSeparate
+        glStencilMask = JS.glStencilMask
+        glStencilMaskSeparate = JS.glStencilMaskSeparate
+        glStencilOp = JS.glStencilOp
+        glStencilOpSeparate = JS.glStencilOpSeparate
+        glTexImage2DBuffer = JS.glTexImage2DBuffer
+        glTexImage2DImage = JS.glTexImage2DElement
+        glTexParameterf = JS.glTexParameterf
+        glTexParameteri = JS.glTexParameteri
+        glTexSubImage2D = JS.glTexSubImage2D
+        glUniform1f = JS.glUniform1f
+        glUniform1fv = JS.glUniform1fv
+        glUniform1i = JS.glUniform1i
+        glUniform1iv = JS.glUniform1iv
+        glUniform2f = JS.glUniform2f
+        glUniform2fv = JS.glUniform2fv
+        glUniform2i = JS.glUniform2i
+        glUniform2iv = JS.glUniform2iv
+        glUniform3f = JS.glUniform3f
+        glUniform3fv = JS.glUniform3fv
+        glUniform3i = JS.glUniform3i
+        glUniform3iv = JS.glUniform3iv
+        glUniform4f = JS.glUniform4f
+        glUniform4fv = JS.glUniform4fv
+        glUniform4i = JS.glUniform4i
+        glUniform4iv = JS.glUniform4iv
+        glUniformMatrix2fv = JS.glUniformMatrix2fv
+        glUniformMatrix3fv = JS.glUniformMatrix3fv
+        glUniformMatrix4fv = JS.glUniformMatrix4fv
+        glUseProgram = JS.glUseProgram
+        glValidateProgram = JS.glValidateProgram
+        glVertexAttrib1f = JS.glVertexAttrib1f
+        glVertexAttrib1fv = JS.glVertexAttrib1fv
+        glVertexAttrib2f = JS.glVertexAttrib2f
+        glVertexAttrib2fv = JS.glVertexAttrib2fv
+        glVertexAttrib3f = JS.glVertexAttrib3f
+        glVertexAttrib3fv = JS.glVertexAttrib3fv
+        glVertexAttrib4f = JS.glVertexAttrib4f
+        glVertexAttrib4fv = JS.glVertexAttrib4fv
+        glVertexAttribPointer = JS.glVertexAttribPointer
+        glViewport = JS.glViewport
+
+        gl_DEPTH_BUFFER_BIT = JS.gl_DEPTH_BUFFER_BIT
+        gl_STENCIL_BUFFER_BIT = JS.gl_STENCIL_BUFFER_BIT
+        gl_COLOR_BUFFER_BIT = JS.gl_COLOR_BUFFER_BIT
+        gl_POINTS = JS.gl_POINTS
+        gl_LINES = JS.gl_LINES
+        gl_LINE_LOOP = JS.gl_LINE_LOOP
+        gl_LINE_STRIP = JS.gl_LINE_STRIP
+        gl_TRIANGLES = JS.gl_TRIANGLES
+        gl_TRIANGLE_STRIP = JS.gl_TRIANGLE_STRIP
+        gl_TRIANGLE_FAN = JS.gl_TRIANGLE_FAN
+        gl_ZERO = JS.gl_ZERO
+        gl_ONE = JS.gl_ONE
+        gl_SRC_COLOR = JS.gl_SRC_COLOR
+        gl_ONE_MINUS_SRC_COLOR = JS.gl_ONE_MINUS_SRC_COLOR
+        gl_SRC_ALPHA = JS.gl_SRC_ALPHA
+        gl_ONE_MINUS_SRC_ALPHA = JS.gl_ONE_MINUS_SRC_ALPHA
+        gl_DST_ALPHA = JS.gl_DST_ALPHA
+        gl_ONE_MINUS_DST_ALPHA = JS.gl_ONE_MINUS_DST_ALPHA
+        gl_DST_COLOR = JS.gl_DST_COLOR
+        gl_ONE_MINUS_DST_COLOR = JS.gl_ONE_MINUS_DST_COLOR
+        gl_SRC_ALPHA_SATURATE = JS.gl_SRC_ALPHA_SATURATE
+        gl_FUNC_ADD = JS.gl_FUNC_ADD
+        gl_BLEND_EQUATION = JS.gl_BLEND_EQUATION
+        gl_BLEND_EQUATION_RGB = JS.gl_BLEND_EQUATION_RGB
+        gl_BLEND_EQUATION_ALPHA = JS.gl_BLEND_EQUATION_ALPHA
+        gl_FUNC_SUBTRACT = JS.gl_FUNC_SUBTRACT
+        gl_FUNC_REVERSE_SUBTRACT = JS.gl_FUNC_REVERSE_SUBTRACT
+        gl_BLEND_DST_RGB = JS.gl_BLEND_DST_RGB
+        gl_BLEND_SRC_RGB = JS.gl_BLEND_SRC_RGB
+        gl_BLEND_DST_ALPHA = JS.gl_BLEND_DST_ALPHA
+        gl_BLEND_SRC_ALPHA = JS.gl_BLEND_SRC_ALPHA
+        gl_CONSTANT_COLOR = JS.gl_CONSTANT_COLOR
+        gl_ONE_MINUS_CONSTANT_COLOR = JS.gl_ONE_MINUS_CONSTANT_COLOR
+        gl_CONSTANT_ALPHA = JS.gl_CONSTANT_ALPHA
+        gl_ONE_MINUS_CONSTANT_ALPHA = JS.gl_ONE_MINUS_CONSTANT_ALPHA
+        gl_BLEND_COLOR = JS.gl_BLEND_COLOR
+        gl_ARRAY_BUFFER = JS.gl_ARRAY_BUFFER
+        gl_ELEMENT_ARRAY_BUFFER = JS.gl_ELEMENT_ARRAY_BUFFER
+        gl_ARRAY_BUFFER_BINDING = JS.gl_ARRAY_BUFFER_BINDING
+        gl_ELEMENT_ARRAY_BUFFER_BINDING = JS.gl_ELEMENT_ARRAY_BUFFER_BINDING
+        gl_STREAM_DRAW = JS.gl_STREAM_DRAW
+        gl_STATIC_DRAW = JS.gl_STATIC_DRAW
+        gl_DYNAMIC_DRAW = JS.gl_DYNAMIC_DRAW
+        gl_BUFFER_SIZE = JS.gl_BUFFER_SIZE
+        gl_BUFFER_USAGE = JS.gl_BUFFER_USAGE
+        gl_CURRENT_VERTEX_ATTRIB = JS.gl_CURRENT_VERTEX_ATTRIB
+        gl_FRONT = JS.gl_FRONT
+        gl_BACK = JS.gl_BACK
+        gl_FRONT_AND_BACK = JS.gl_FRONT_AND_BACK
+        gl_CULL_FACE = JS.gl_CULL_FACE
+        gl_BLEND = JS.gl_BLEND
+        gl_DITHER = JS.gl_DITHER
+        gl_STENCIL_TEST = JS.gl_STENCIL_TEST
+        gl_DEPTH_TEST = JS.gl_DEPTH_TEST
+        gl_SCISSOR_TEST = JS.gl_SCISSOR_TEST
+        gl_POLYGON_OFFSET_FILL = JS.gl_POLYGON_OFFSET_FILL
+        gl_SAMPLE_ALPHA_TO_COVERAGE = JS.gl_SAMPLE_ALPHA_TO_COVERAGE
+        gl_SAMPLE_COVERAGE = JS.gl_SAMPLE_COVERAGE
+        gl_NO_ERROR = JS.gl_NO_ERROR
+        gl_INVALID_ENUM = JS.gl_INVALID_ENUM
+        gl_INVALID_VALUE = JS.gl_INVALID_VALUE
+        gl_INVALID_OPERATION = JS.gl_INVALID_OPERATION
+        gl_OUT_OF_MEMORY = JS.gl_OUT_OF_MEMORY
+        gl_CW = JS.gl_CW
+        gl_CCW = JS.gl_CCW
+        gl_LINE_WIDTH = JS.gl_LINE_WIDTH
+        gl_ALIASED_POINT_SIZE_RANGE = JS.gl_ALIASED_POINT_SIZE_RANGE
+        gl_ALIASED_LINE_WIDTH_RANGE = JS.gl_ALIASED_LINE_WIDTH_RANGE
+        gl_CULL_FACE_MODE = JS.gl_CULL_FACE_MODE
+        gl_FRONT_FACE = JS.gl_FRONT_FACE
+        gl_DEPTH_RANGE = JS.gl_DEPTH_RANGE
+        gl_DEPTH_WRITEMASK = JS.gl_DEPTH_WRITEMASK
+        gl_DEPTH_CLEAR_VALUE = JS.gl_DEPTH_CLEAR_VALUE
+        gl_DEPTH_FUNC = JS.gl_DEPTH_FUNC
+        gl_STENCIL_CLEAR_VALUE = JS.gl_STENCIL_CLEAR_VALUE
+        gl_STENCIL_FUNC = JS.gl_STENCIL_FUNC
+        gl_STENCIL_FAIL = JS.gl_STENCIL_FAIL
+        gl_STENCIL_PASS_DEPTH_FAIL = JS.gl_STENCIL_PASS_DEPTH_FAIL
+        gl_STENCIL_PASS_DEPTH_PASS = JS.gl_STENCIL_PASS_DEPTH_PASS
+        gl_STENCIL_REF = JS.gl_STENCIL_REF
+        gl_STENCIL_VALUE_MASK = JS.gl_STENCIL_VALUE_MASK
+        gl_STENCIL_WRITEMASK = JS.gl_STENCIL_WRITEMASK
+        gl_STENCIL_BACK_FUNC = JS.gl_STENCIL_BACK_FUNC
+        gl_STENCIL_BACK_FAIL = JS.gl_STENCIL_BACK_FAIL
+        gl_STENCIL_BACK_PASS_DEPTH_FAIL = JS.gl_STENCIL_BACK_PASS_DEPTH_FAIL
+        gl_STENCIL_BACK_PASS_DEPTH_PASS = JS.gl_STENCIL_BACK_PASS_DEPTH_PASS
+        gl_STENCIL_BACK_REF = JS.gl_STENCIL_BACK_REF
+        gl_STENCIL_BACK_VALUE_MASK = JS.gl_STENCIL_BACK_VALUE_MASK
+        gl_STENCIL_BACK_WRITEMASK = JS.gl_STENCIL_BACK_WRITEMASK
+        gl_VIEWPORT = JS.gl_VIEWPORT
+        gl_SCISSOR_BOX = JS.gl_SCISSOR_BOX
+        gl_COLOR_CLEAR_VALUE = JS.gl_COLOR_CLEAR_VALUE
+        gl_COLOR_WRITEMASK = JS.gl_COLOR_WRITEMASK
+        gl_UNPACK_ALIGNMENT = JS.gl_UNPACK_ALIGNMENT
+        gl_PACK_ALIGNMENT = JS.gl_PACK_ALIGNMENT
+        gl_MAX_TEXTURE_SIZE = JS.gl_MAX_TEXTURE_SIZE
+        gl_MAX_VIEWPORT_DIMS = JS.gl_MAX_VIEWPORT_DIMS
+        gl_SUBPIXEL_BITS = JS.gl_SUBPIXEL_BITS
+        gl_RED_BITS = JS.gl_RED_BITS
+        gl_GREEN_BITS = JS.gl_GREEN_BITS
+        gl_BLUE_BITS = JS.gl_BLUE_BITS
+        gl_ALPHA_BITS = JS.gl_ALPHA_BITS
+        gl_DEPTH_BITS = JS.gl_DEPTH_BITS
+        gl_STENCIL_BITS = JS.gl_STENCIL_BITS
+        gl_POLYGON_OFFSET_UNITS = JS.gl_POLYGON_OFFSET_UNITS
+        gl_POLYGON_OFFSET_FACTOR = JS.gl_POLYGON_OFFSET_FACTOR
+        gl_TEXTURE_BINDING_2D = JS.gl_TEXTURE_BINDING_2D
+        gl_SAMPLE_BUFFERS = JS.gl_SAMPLE_BUFFERS
+        gl_SAMPLES = JS.gl_SAMPLES
+        gl_SAMPLE_COVERAGE_VALUE = JS.gl_SAMPLE_COVERAGE_VALUE
+        gl_SAMPLE_COVERAGE_INVERT = JS.gl_SAMPLE_COVERAGE_INVERT
+        gl_COMPRESSED_TEXTURE_FORMATS = JS.gl_COMPRESSED_TEXTURE_FORMATS
+        gl_DONT_CARE = JS.gl_DONT_CARE
+        gl_FASTEST = JS.gl_FASTEST
+        gl_NICEST = JS.gl_NICEST
+        gl_GENERATE_MIPMAP_HINT = JS.gl_GENERATE_MIPMAP_HINT
+        gl_BYTE = JS.gl_BYTE
+        gl_UNSIGNED_BYTE = JS.gl_UNSIGNED_BYTE
+        gl_SHORT = JS.gl_SHORT
+        gl_UNSIGNED_SHORT = JS.gl_UNSIGNED_SHORT
+        gl_INT = JS.gl_INT
+        gl_UNSIGNED_INT = JS.gl_UNSIGNED_INT
+        gl_FLOAT = JS.gl_FLOAT
+        gl_DEPTH_COMPONENT = JS.gl_DEPTH_COMPONENT
+        gl_ALPHA = JS.gl_ALPHA
+        gl_RGB = JS.gl_RGB
+        gl_RGBA = JS.gl_RGBA
+        gl_LUMINANCE = JS.gl_LUMINANCE
+        gl_LUMINANCE_ALPHA = JS.gl_LUMINANCE_ALPHA
+        gl_UNSIGNED_SHORT_4_4_4_4 = JS.gl_UNSIGNED_SHORT_4_4_4_4
+        gl_UNSIGNED_SHORT_5_5_5_1 = JS.gl_UNSIGNED_SHORT_5_5_5_1
+        gl_UNSIGNED_SHORT_5_6_5 = JS.gl_UNSIGNED_SHORT_5_6_5
+        gl_FRAGMENT_SHADER = JS.gl_FRAGMENT_SHADER
+        gl_VERTEX_SHADER = JS.gl_VERTEX_SHADER
+        gl_MAX_VERTEX_ATTRIBS = JS.gl_MAX_VERTEX_ATTRIBS
+        gl_MAX_VERTEX_UNIFORM_VECTORS = JS.gl_MAX_VERTEX_UNIFORM_VECTORS
+        gl_MAX_VARYING_VECTORS = JS.gl_MAX_VARYING_VECTORS
+        gl_MAX_COMBINED_TEXTURE_IMAGE_UNITS = JS.gl_MAX_COMBINED_TEXTURE_IMAGE_UNITS
+        gl_MAX_VERTEX_TEXTURE_IMAGE_UNITS = JS.gl_MAX_VERTEX_TEXTURE_IMAGE_UNITS
+        gl_MAX_TEXTURE_IMAGE_UNITS = JS.gl_MAX_TEXTURE_IMAGE_UNITS
+        gl_MAX_FRAGMENT_UNIFORM_VECTORS = JS.gl_MAX_FRAGMENT_UNIFORM_VECTORS
+        gl_SHADER_TYPE = JS.gl_SHADER_TYPE
+        gl_DELETE_STATUS = JS.gl_DELETE_STATUS
+        gl_LINK_STATUS = JS.gl_LINK_STATUS
+        gl_VALIDATE_STATUS = JS.gl_VALIDATE_STATUS
+        gl_ATTACHED_SHADERS = JS.gl_ATTACHED_SHADERS
+        gl_ACTIVE_UNIFORMS = JS.gl_ACTIVE_UNIFORMS
+        gl_ACTIVE_ATTRIBUTES = JS.gl_ACTIVE_ATTRIBUTES
+        gl_SHADING_LANGUAGE_VERSION = JS.gl_SHADING_LANGUAGE_VERSION
+        gl_CURRENT_PROGRAM = JS.gl_CURRENT_PROGRAM
+        gl_NEVER = JS.gl_NEVER
+        gl_LESS = JS.gl_LESS
+        gl_EQUAL = JS.gl_EQUAL
+        gl_LEQUAL = JS.gl_LEQUAL
+        gl_GREATER = JS.gl_GREATER
+        gl_NOTEQUAL = JS.gl_NOTEQUAL
+        gl_GEQUAL = JS.gl_GEQUAL
+        gl_ALWAYS = JS.gl_ALWAYS
+        gl_KEEP = JS.gl_KEEP
+        gl_REPLACE = JS.gl_REPLACE
+        gl_INCR = JS.gl_INCR
+        gl_DECR = JS.gl_DECR
+        gl_INVERT = JS.gl_INVERT
+        gl_INCR_WRAP = JS.gl_INCR_WRAP
+        gl_DECR_WRAP = JS.gl_DECR_WRAP
+        gl_VENDOR = JS.gl_VENDOR
+        gl_RENDERER = JS.gl_RENDERER
+        gl_VERSION = JS.gl_VERSION
+        gl_NEAREST = JS.gl_NEAREST
+        gl_LINEAR = JS.gl_LINEAR
+        gl_NEAREST_MIPMAP_NEAREST = JS.gl_NEAREST_MIPMAP_NEAREST
+        gl_LINEAR_MIPMAP_NEAREST = JS.gl_LINEAR_MIPMAP_NEAREST
+        gl_NEAREST_MIPMAP_LINEAR = JS.gl_NEAREST_MIPMAP_LINEAR
+        gl_LINEAR_MIPMAP_LINEAR = JS.gl_LINEAR_MIPMAP_LINEAR
+        gl_TEXTURE_MAG_FILTER = JS.gl_TEXTURE_MAG_FILTER
+        gl_TEXTURE_MIN_FILTER = JS.gl_TEXTURE_MIN_FILTER
+        gl_TEXTURE_WRAP_S = JS.gl_TEXTURE_WRAP_S
+        gl_TEXTURE_WRAP_T = JS.gl_TEXTURE_WRAP_T
+        gl_TEXTURE_2D = JS.gl_TEXTURE_2D
+        gl_TEXTURE = JS.gl_TEXTURE
+        gl_TEXTURE_CUBE_MAP = JS.gl_TEXTURE_CUBE_MAP
+        gl_TEXTURE_BINDING_CUBE_MAP = JS.gl_TEXTURE_BINDING_CUBE_MAP
+        gl_TEXTURE_CUBE_MAP_POSITIVE_X = JS.gl_TEXTURE_CUBE_MAP_POSITIVE_X
+        gl_TEXTURE_CUBE_MAP_NEGATIVE_X = JS.gl_TEXTURE_CUBE_MAP_NEGATIVE_X
+        gl_TEXTURE_CUBE_MAP_POSITIVE_Y = JS.gl_TEXTURE_CUBE_MAP_POSITIVE_Y
+        gl_TEXTURE_CUBE_MAP_NEGATIVE_Y = JS.gl_TEXTURE_CUBE_MAP_NEGATIVE_Y
+        gl_TEXTURE_CUBE_MAP_POSITIVE_Z = JS.gl_TEXTURE_CUBE_MAP_POSITIVE_Z
+        gl_TEXTURE_CUBE_MAP_NEGATIVE_Z = JS.gl_TEXTURE_CUBE_MAP_NEGATIVE_Z
+        gl_MAX_CUBE_MAP_TEXTURE_SIZE = JS.gl_MAX_CUBE_MAP_TEXTURE_SIZE
+        gl_TEXTURE0 = JS.gl_TEXTURE0
+        gl_TEXTURE1 = JS.gl_TEXTURE1
+        gl_TEXTURE2 = JS.gl_TEXTURE2
+        gl_TEXTURE3 = JS.gl_TEXTURE3
+        gl_TEXTURE4 = JS.gl_TEXTURE4
+        gl_TEXTURE5 = JS.gl_TEXTURE5
+        gl_TEXTURE6 = JS.gl_TEXTURE6
+        gl_TEXTURE7 = JS.gl_TEXTURE7
+        gl_TEXTURE8 = JS.gl_TEXTURE8
+        gl_TEXTURE9 = JS.gl_TEXTURE9
+        gl_TEXTURE10 = JS.gl_TEXTURE10
+        gl_TEXTURE11 = JS.gl_TEXTURE11
+        gl_TEXTURE12 = JS.gl_TEXTURE12
+        gl_TEXTURE13 = JS.gl_TEXTURE13
+        gl_TEXTURE14 = JS.gl_TEXTURE14
+        gl_TEXTURE15 = JS.gl_TEXTURE15
+        gl_TEXTURE16 = JS.gl_TEXTURE16
+        gl_TEXTURE17 = JS.gl_TEXTURE17
+        gl_TEXTURE18 = JS.gl_TEXTURE18
+        gl_TEXTURE19 = JS.gl_TEXTURE19
+        gl_TEXTURE20 = JS.gl_TEXTURE20
+        gl_TEXTURE21 = JS.gl_TEXTURE21
+        gl_TEXTURE22 = JS.gl_TEXTURE22
+        gl_TEXTURE23 = JS.gl_TEXTURE23
+        gl_TEXTURE24 = JS.gl_TEXTURE24
+        gl_TEXTURE25 = JS.gl_TEXTURE25
+        gl_TEXTURE26 = JS.gl_TEXTURE26
+        gl_TEXTURE27 = JS.gl_TEXTURE27
+        gl_TEXTURE28 = JS.gl_TEXTURE28
+        gl_TEXTURE29 = JS.gl_TEXTURE29
+        gl_TEXTURE30 = JS.gl_TEXTURE30
+        gl_TEXTURE31 = JS.gl_TEXTURE31
+        gl_ACTIVE_TEXTURE = JS.gl_ACTIVE_TEXTURE
+        gl_REPEAT = JS.gl_REPEAT
+        gl_CLAMP_TO_EDGE = JS.gl_CLAMP_TO_EDGE
+        gl_MIRRORED_REPEAT = JS.gl_MIRRORED_REPEAT
+        gl_FLOAT_VEC2 = JS.gl_FLOAT_VEC2
+        gl_FLOAT_VEC3 = JS.gl_FLOAT_VEC3
+        gl_FLOAT_VEC4 = JS.gl_FLOAT_VEC4
+        gl_INT_VEC2 = JS.gl_INT_VEC2
+        gl_INT_VEC3 = JS.gl_INT_VEC3
+        gl_INT_VEC4 = JS.gl_INT_VEC4
+        gl_BOOL = JS.gl_BOOL
+        gl_BOOL_VEC2 = JS.gl_BOOL_VEC2
+        gl_BOOL_VEC3 = JS.gl_BOOL_VEC3
+        gl_BOOL_VEC4 = JS.gl_BOOL_VEC4
+        gl_FLOAT_MAT2 = JS.gl_FLOAT_MAT2
+        gl_FLOAT_MAT3 = JS.gl_FLOAT_MAT3
+        gl_FLOAT_MAT4 = JS.gl_FLOAT_MAT4
+        gl_SAMPLER_2D = JS.gl_SAMPLER_2D
+        gl_SAMPLER_CUBE = JS.gl_SAMPLER_CUBE
+        gl_VERTEX_ATTRIB_ARRAY_ENABLED = JS.gl_VERTEX_ATTRIB_ARRAY_ENABLED
+        gl_VERTEX_ATTRIB_ARRAY_SIZE = JS.gl_VERTEX_ATTRIB_ARRAY_SIZE
+        gl_VERTEX_ATTRIB_ARRAY_STRIDE = JS.gl_VERTEX_ATTRIB_ARRAY_STRIDE
+        gl_VERTEX_ATTRIB_ARRAY_TYPE = JS.gl_VERTEX_ATTRIB_ARRAY_TYPE
+        gl_VERTEX_ATTRIB_ARRAY_NORMALIZED = JS.gl_VERTEX_ATTRIB_ARRAY_NORMALIZED
+        gl_VERTEX_ATTRIB_ARRAY_POINTER = JS.gl_VERTEX_ATTRIB_ARRAY_POINTER
+        gl_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = JS.gl_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
+        gl_COMPILE_STATUS = JS.gl_COMPILE_STATUS
+        gl_LOW_FLOAT = JS.gl_LOW_FLOAT
+        gl_MEDIUM_FLOAT = JS.gl_MEDIUM_FLOAT
+        gl_HIGH_FLOAT = JS.gl_HIGH_FLOAT
+        gl_LOW_INT = JS.gl_LOW_INT
+        gl_MEDIUM_INT = JS.gl_MEDIUM_INT
+        gl_HIGH_INT = JS.gl_HIGH_INT
+        gl_FRAMEBUFFER = JS.gl_FRAMEBUFFER
+        gl_RENDERBUFFER = JS.gl_RENDERBUFFER
+        gl_RGBA4 = JS.gl_RGBA4
+        gl_RGB5_A1 = JS.gl_RGB5_A1
+        gl_RGB565 = JS.gl_RGB565
+        gl_DEPTH_COMPONENT16 = JS.gl_DEPTH_COMPONENT16
+        gl_STENCIL_INDEX8 = JS.gl_STENCIL_INDEX8
+        gl_RENDERBUFFER_WIDTH = JS.gl_RENDERBUFFER_WIDTH
+        gl_RENDERBUFFER_HEIGHT = JS.gl_RENDERBUFFER_HEIGHT
+        gl_RENDERBUFFER_INTERNAL_FORMAT = JS.gl_RENDERBUFFER_INTERNAL_FORMAT
+        gl_RENDERBUFFER_RED_SIZE = JS.gl_RENDERBUFFER_RED_SIZE
+        gl_RENDERBUFFER_GREEN_SIZE = JS.gl_RENDERBUFFER_GREEN_SIZE
+        gl_RENDERBUFFER_BLUE_SIZE = JS.gl_RENDERBUFFER_BLUE_SIZE
+        gl_RENDERBUFFER_ALPHA_SIZE = JS.gl_RENDERBUFFER_ALPHA_SIZE
+        gl_RENDERBUFFER_DEPTH_SIZE = JS.gl_RENDERBUFFER_DEPTH_SIZE
+        gl_RENDERBUFFER_STENCIL_SIZE = JS.gl_RENDERBUFFER_STENCIL_SIZE
+        gl_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = JS.gl_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
+        gl_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = JS.gl_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
+        gl_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = JS.gl_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL
+        gl_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = JS.gl_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE
+        gl_COLOR_ATTACHMENT0 = JS.gl_COLOR_ATTACHMENT0
+        gl_DEPTH_ATTACHMENT = JS.gl_DEPTH_ATTACHMENT
+        gl_STENCIL_ATTACHMENT = JS.gl_STENCIL_ATTACHMENT
+        gl_NONE = JS.gl_NONE
+        gl_FRAMEBUFFER_COMPLETE = JS.gl_FRAMEBUFFER_COMPLETE
+        gl_FRAMEBUFFER_INCOMPLETE_ATTACHMENT = JS.gl_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
+        gl_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = JS.gl_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
+        gl_FRAMEBUFFER_INCOMPLETE_DIMENSIONS = JS.gl_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
+        gl_FRAMEBUFFER_UNSUPPORTED = JS.gl_FRAMEBUFFER_UNSUPPORTED
+        gl_FRAMEBUFFER_BINDING = JS.gl_FRAMEBUFFER_BINDING
+        gl_RENDERBUFFER_BINDING = JS.gl_RENDERBUFFER_BINDING
+        gl_MAX_RENDERBUFFER_SIZE = JS.gl_MAX_RENDERBUFFER_SIZE
+        gl_INVALID_FRAMEBUFFER_OPERATION = JS.gl_INVALID_FRAMEBUFFER_OPERATION
diff --git a/FWGL/Backend/JavaScript/Event.hs b/FWGL/Backend/JavaScript/Event.hs
new file mode 100644
--- /dev/null
+++ b/FWGL/Backend/JavaScript/Event.hs
@@ -0,0 +1,200 @@
+-- TODO: rewrite everything
+
+module FWGL.Backend.JavaScript.Event (
+        InputEvent(..),
+        Source,
+        source,
+        addEvent,
+        addEvents,
+        events,
+        clear
+) where
+
+import Control.Applicative
+import Data.Char (toLower, toUpper)
+import qualified Data.Hashable as H
+import qualified Data.HashMap.Strict as H
+import Data.IORef
+
+import GHCJS.Foreign
+import GHCJS.Marshal
+import GHCJS.Types
+
+import FWGL.Input
+
+type Event = InputEvent
+
+data Source = Source {
+        element :: JSRef (),
+        eventMap :: IORef (H.HashMap Event [EventData])
+}
+
+source :: [Event] -> JSRef a -> IO Source
+source es j = do
+        s <- Source (castRef j) <$> newIORef H.empty
+        addEvents es s
+        return s
+
+events :: Source -> IO (H.HashMap Event [EventData])
+events (Source _ c) = readIORef c
+
+clear :: Source -> IO (H.HashMap Event [EventData])
+clear (Source _ c) = atomicModifyIORef' c $ \m -> (H.empty, m)
+
+addEvents :: [Event] -> Source -> IO ()
+addEvents es s = mapM_ (flip addEvent s) es
+
+addEvent :: Event -> Source -> IO ()
+addEvent e (Source j c) = asyncCallback1 NeverRetain handler >>=
+                          addHandler j (toJSString $ eventName e)
+        where 
+                prop p d =  getProp p d >>= fromJSRef
+                handler d = do
+                        eventData <- EventData
+                                        <$> (do w <- prop "clientWidth" j
+                                                h <- prop "clientHeight" j
+                                                return $ (,) <$> w <*> h)
+                                        <*> (do x <- prop "clientX" d
+                                                y <- prop "clientY" d
+                                                return $ (,) <$> x <*> y)
+                                        <*> ((getButton <$>) <$> prop "button" d)
+                                        <*> ((getKey <$>) <$> prop "keyCode" d)
+                        modifyIORef c $ H.insertWith (flip (++)) e [ eventData ]
+
+eventName :: Event -> String
+-- eventName (Other s) = s
+-- eventName DoubleClick = "dblclick"
+eventName s = map toLower . show $ s
+
+getButton :: Int -> MouseButton
+getButton 0 = MouseLeft
+getButton 1 = MouseMiddle
+getButton 2 = MouseRight
+
+foreign import javascript unsafe "$1.addEventListener($2, $3)"
+        addHandler :: JSRef a -> JSString -> JSFun (JSRef b -> IO ()) -> IO ()
+
+getKey :: Int -> Key
+getKey 65 = KeyA
+getKey 66 = KeyB
+getKey 67 = KeyC
+getKey 68 = KeyD
+getKey 69 = KeyE
+getKey 70 = KeyF
+getKey 71 = KeyG
+getKey 72 = KeyH
+getKey 73 = KeyI
+getKey 74 = KeyJ
+getKey 75 = KeyK
+getKey 76 = KeyL
+getKey 77 = KeyM
+getKey 78 = KeyN
+getKey 79 = KeyO
+getKey 80 = KeyP
+getKey 81 = KeyQ
+getKey 82 = KeyR
+getKey 83 = KeyS
+getKey 84 = KeyT
+getKey 85 = KeyU
+getKey 86 = KeyV
+getKey 87 = KeyW
+getKey 88 = KeyX
+getKey 89 = KeyY
+getKey 90 = KeyZ
+getKey 97 = KeyA
+getKey 98 = KeyB
+getKey 99 = KeyC
+getKey 100 = KeyD
+getKey 101 = KeyE
+getKey 102 = KeyF
+getKey 103 = KeyG
+getKey 104 = KeyH
+getKey 105 = KeyI
+getKey 106 = KeyJ
+getKey 107 = KeyK
+getKey 108 = KeyL
+getKey 109 = KeyM
+getKey 110 = KeyN
+getKey 111 = KeyO
+getKey 112 = KeyP
+getKey 113 = KeyQ
+getKey 114 = KeyR
+getKey 115 = KeyS
+getKey 116 = KeyT
+getKey 117 = KeyU
+getKey 118 = KeyV
+getKey 119 = KeyW
+getKey 120 = KeyX
+getKey 121 = KeyY
+getKey 122 = KeyZ
+getKey 48 = Key0
+getKey 49 = Key1
+getKey 50 = Key2
+getKey 51 = Key3
+getKey 52 = Key4
+getKey 53 = Key5
+getKey 54 = Key6
+getKey 55 = Key7
+getKey 56 = Key8
+getKey 57 = Key9
+getKey 32 = KeySpace
+getKey 13 = KeyEnter
+getKey 9 = KeyTab
+getKey 27 = KeyEsc
+getKey 8 = KeyBackspace
+getKey 16 = KeyShift
+getKey 17 = KeyControl
+getKey 18 = KeyAlt
+getKey 20 = KeyCapsLock
+getKey 144 = KeyNumLock
+getKey 37 = KeyArrowLeft
+getKey 38 = KeyArrowUp
+getKey 39 = KeyArrowRight
+getKey 40 = KeyArrowDown
+getKey 45 = KeyIns
+getKey 46 = KeyDel
+getKey 36 = KeyHome
+getKey 35 = KeyEnd
+getKey 33 = KeyPgUp
+getKey 34 = KeyPgDown
+getKey 112 = KeyF1
+getKey 113 = KeyF2
+getKey 114 = KeyF3
+getKey 115 = KeyF4
+getKey 116 = KeyF5
+getKey 117 = KeyF6
+getKey 118 = KeyF7
+getKey 119 = KeyF8
+getKey 120 = KeyF9
+getKey 121 = KeyF10
+getKey 122 = KeyF11
+getKey 123 = KeyF12
+getKey 46 = KeyPadDel
+getKey 45 = KeyPadIns
+getKey 35 = KeyPadEnd
+getKey 40 = KeyPadDown
+getKey 34 = KeyPadPgDown
+getKey 37 = KeyPadLeft
+getKey 39 = KeyPadRight
+getKey 36 = KeyPadHome
+getKey 38 = KeyPadUp
+getKey 33 = KeyPadPgUp
+getKey 107 = KeyPadAdd
+getKey 109 = KeyPadSub
+getKey 106 = KeyPadMul
+getKey 111 = KeyPadDiv
+getKey 13 = KeyPadEnter
+getKey 46 = KeyPadDot
+getKey 48 = KeyPad0
+getKey 49 = KeyPad1
+getKey 50 = KeyPad2
+getKey 51 = KeyPad3
+getKey 52 = KeyPad4
+getKey 53 = KeyPad5
+getKey 54 = KeyPad6
+getKey 55 = KeyPad7
+getKey 56 = KeyPad8
+getKey 57 = KeyPad9
+getKey _ = KeyUnknown
+-- TODO: letters, numbers
+-- TODO: fix overlapping patterns
diff --git a/FWGL/Backend/JavaScript/WebGL.hs b/FWGL/Backend/JavaScript/WebGL.hs
new file mode 100644
--- /dev/null
+++ b/FWGL/Backend/JavaScript/WebGL.hs
@@ -0,0 +1,5 @@
+module FWGL.Backend.JavaScript.WebGL (module W) where
+
+import FWGL.Backend.JavaScript.WebGL.Const as W
+import FWGL.Backend.JavaScript.WebGL.Raw as W
+import FWGL.Backend.JavaScript.WebGL.Types as W
diff --git a/FWGL/Backend/JavaScript/WebGL/Const.hs b/FWGL/Backend/JavaScript/WebGL/Const.hs
new file mode 100644
--- /dev/null
+++ b/FWGL/Backend/JavaScript/WebGL/Const.hs
@@ -0,0 +1,886 @@
+module FWGL.Backend.JavaScript.WebGL.Const where
+
+gl_DEPTH_BUFFER_BIT :: Num a => a
+gl_DEPTH_BUFFER_BIT = 0x00000100
+
+gl_STENCIL_BUFFER_BIT :: Num a => a
+gl_STENCIL_BUFFER_BIT = 0x00000400
+
+gl_COLOR_BUFFER_BIT :: Num a => a
+gl_COLOR_BUFFER_BIT = 0x00004000
+
+gl_POINTS :: Num a => a
+gl_POINTS = 0x0000
+
+gl_LINES :: Num a => a
+gl_LINES = 0x0001
+
+gl_LINE_LOOP :: Num a => a
+gl_LINE_LOOP = 0x0002
+
+gl_LINE_STRIP :: Num a => a
+gl_LINE_STRIP = 0x0003
+
+gl_TRIANGLES :: Num a => a
+gl_TRIANGLES = 0x0004
+
+gl_TRIANGLE_STRIP :: Num a => a
+gl_TRIANGLE_STRIP = 0x0005
+
+gl_TRIANGLE_FAN :: Num a => a
+gl_TRIANGLE_FAN = 0x0006
+
+gl_ZERO :: Num a => a
+gl_ZERO = 0
+
+gl_ONE :: Num a => a
+gl_ONE = 1
+
+gl_SRC_COLOR :: Num a => a
+gl_SRC_COLOR = 0x0300
+
+gl_ONE_MINUS_SRC_COLOR :: Num a => a
+gl_ONE_MINUS_SRC_COLOR = 0x0301
+
+gl_SRC_ALPHA :: Num a => a
+gl_SRC_ALPHA = 0x0302
+
+gl_ONE_MINUS_SRC_ALPHA :: Num a => a
+gl_ONE_MINUS_SRC_ALPHA = 0x0303
+
+gl_DST_ALPHA :: Num a => a
+gl_DST_ALPHA = 0x0304
+
+gl_ONE_MINUS_DST_ALPHA :: Num a => a
+gl_ONE_MINUS_DST_ALPHA = 0x0305
+
+gl_DST_COLOR :: Num a => a
+gl_DST_COLOR = 0x0306
+
+gl_ONE_MINUS_DST_COLOR :: Num a => a
+gl_ONE_MINUS_DST_COLOR = 0x0307
+
+gl_SRC_ALPHA_SATURATE :: Num a => a
+gl_SRC_ALPHA_SATURATE = 0x0308
+
+gl_FUNC_ADD :: Num a => a
+gl_FUNC_ADD = 0x8006
+
+gl_BLEND_EQUATION :: Num a => a
+gl_BLEND_EQUATION = 0x8009
+
+gl_BLEND_EQUATION_RGB :: Num a => a
+gl_BLEND_EQUATION_RGB = 0x8009   
+
+gl_BLEND_EQUATION_ALPHA :: Num a => a
+gl_BLEND_EQUATION_ALPHA = 0x883D
+
+gl_FUNC_SUBTRACT :: Num a => a
+gl_FUNC_SUBTRACT = 0x800A
+
+gl_FUNC_REVERSE_SUBTRACT :: Num a => a
+gl_FUNC_REVERSE_SUBTRACT = 0x800B
+
+gl_BLEND_DST_RGB :: Num a => a
+gl_BLEND_DST_RGB = 0x80C8
+
+gl_BLEND_SRC_RGB :: Num a => a
+gl_BLEND_SRC_RGB = 0x80C9
+
+gl_BLEND_DST_ALPHA :: Num a => a
+gl_BLEND_DST_ALPHA = 0x80CA
+
+gl_BLEND_SRC_ALPHA :: Num a => a
+gl_BLEND_SRC_ALPHA = 0x80CB
+
+gl_CONSTANT_COLOR :: Num a => a
+gl_CONSTANT_COLOR = 0x8001
+
+gl_ONE_MINUS_CONSTANT_COLOR :: Num a => a
+gl_ONE_MINUS_CONSTANT_COLOR = 0x8002
+
+gl_CONSTANT_ALPHA :: Num a => a
+gl_CONSTANT_ALPHA = 0x8003
+
+gl_ONE_MINUS_CONSTANT_ALPHA :: Num a => a
+gl_ONE_MINUS_CONSTANT_ALPHA = 0x8004
+
+gl_BLEND_COLOR :: Num a => a
+gl_BLEND_COLOR = 0x8005
+
+gl_ARRAY_BUFFER :: Num a => a
+gl_ARRAY_BUFFER = 0x8892
+
+gl_ELEMENT_ARRAY_BUFFER :: Num a => a
+gl_ELEMENT_ARRAY_BUFFER = 0x8893
+
+gl_ARRAY_BUFFER_BINDING :: Num a => a
+gl_ARRAY_BUFFER_BINDING = 0x8894
+
+gl_ELEMENT_ARRAY_BUFFER_BINDING :: Num a => a
+gl_ELEMENT_ARRAY_BUFFER_BINDING = 0x8895
+
+gl_STREAM_DRAW :: Num a => a
+gl_STREAM_DRAW = 0x88E0
+
+gl_STATIC_DRAW :: Num a => a
+gl_STATIC_DRAW = 0x88E4
+
+gl_DYNAMIC_DRAW :: Num a => a
+gl_DYNAMIC_DRAW = 0x88E8
+
+gl_BUFFER_SIZE :: Num a => a
+gl_BUFFER_SIZE = 0x8764
+
+gl_BUFFER_USAGE :: Num a => a
+gl_BUFFER_USAGE = 0x8765
+
+gl_CURRENT_VERTEX_ATTRIB :: Num a => a
+gl_CURRENT_VERTEX_ATTRIB = 0x8626
+
+gl_FRONT :: Num a => a
+gl_FRONT = 0x0404
+
+gl_BACK :: Num a => a
+gl_BACK = 0x0405
+
+gl_FRONT_AND_BACK :: Num a => a
+gl_FRONT_AND_BACK = 0x0408
+
+gl_CULL_FACE :: Num a => a
+gl_CULL_FACE = 0x0B44
+
+gl_BLEND :: Num a => a
+gl_BLEND = 0x0BE2
+
+gl_DITHER :: Num a => a
+gl_DITHER = 0x0BD0
+
+gl_STENCIL_TEST :: Num a => a
+gl_STENCIL_TEST = 0x0B90
+
+gl_DEPTH_TEST :: Num a => a
+gl_DEPTH_TEST = 0x0B71
+
+gl_SCISSOR_TEST :: Num a => a
+gl_SCISSOR_TEST = 0x0C11
+
+gl_POLYGON_OFFSET_FILL :: Num a => a
+gl_POLYGON_OFFSET_FILL = 0x8037
+
+gl_SAMPLE_ALPHA_TO_COVERAGE :: Num a => a
+gl_SAMPLE_ALPHA_TO_COVERAGE = 0x809E
+
+gl_SAMPLE_COVERAGE :: Num a => a
+gl_SAMPLE_COVERAGE = 0x80A0
+
+gl_NO_ERROR :: Num a => a
+gl_NO_ERROR = 0
+
+gl_INVALID_ENUM :: Num a => a
+gl_INVALID_ENUM = 0x0500
+
+gl_INVALID_VALUE :: Num a => a
+gl_INVALID_VALUE = 0x0501
+
+gl_INVALID_OPERATION :: Num a => a
+gl_INVALID_OPERATION = 0x0502
+
+gl_OUT_OF_MEMORY :: Num a => a
+gl_OUT_OF_MEMORY = 0x0505
+
+gl_CW :: Num a => a
+gl_CW = 0x0900
+
+gl_CCW :: Num a => a
+gl_CCW = 0x0901
+
+gl_LINE_WIDTH :: Num a => a
+gl_LINE_WIDTH = 0x0B21
+
+gl_ALIASED_POINT_SIZE_RANGE :: Num a => a
+gl_ALIASED_POINT_SIZE_RANGE = 0x846D
+
+gl_ALIASED_LINE_WIDTH_RANGE :: Num a => a
+gl_ALIASED_LINE_WIDTH_RANGE = 0x846E
+
+gl_CULL_FACE_MODE :: Num a => a
+gl_CULL_FACE_MODE = 0x0B45
+
+gl_FRONT_FACE :: Num a => a
+gl_FRONT_FACE = 0x0B46
+
+gl_DEPTH_RANGE :: Num a => a
+gl_DEPTH_RANGE = 0x0B70
+
+gl_DEPTH_WRITEMASK :: Num a => a
+gl_DEPTH_WRITEMASK = 0x0B72
+
+gl_DEPTH_CLEAR_VALUE :: Num a => a
+gl_DEPTH_CLEAR_VALUE = 0x0B73
+
+gl_DEPTH_FUNC :: Num a => a
+gl_DEPTH_FUNC = 0x0B74
+
+gl_STENCIL_CLEAR_VALUE :: Num a => a
+gl_STENCIL_CLEAR_VALUE = 0x0B91
+
+gl_STENCIL_FUNC :: Num a => a
+gl_STENCIL_FUNC = 0x0B92
+
+gl_STENCIL_FAIL :: Num a => a
+gl_STENCIL_FAIL = 0x0B94
+
+gl_STENCIL_PASS_DEPTH_FAIL :: Num a => a
+gl_STENCIL_PASS_DEPTH_FAIL = 0x0B95
+
+gl_STENCIL_PASS_DEPTH_PASS :: Num a => a
+gl_STENCIL_PASS_DEPTH_PASS = 0x0B96
+
+gl_STENCIL_REF :: Num a => a
+gl_STENCIL_REF = 0x0B97
+
+gl_STENCIL_VALUE_MASK :: Num a => a
+gl_STENCIL_VALUE_MASK = 0x0B93
+
+gl_STENCIL_WRITEMASK :: Num a => a
+gl_STENCIL_WRITEMASK = 0x0B98
+
+gl_STENCIL_BACK_FUNC :: Num a => a
+gl_STENCIL_BACK_FUNC = 0x8800
+
+gl_STENCIL_BACK_FAIL :: Num a => a
+gl_STENCIL_BACK_FAIL = 0x8801
+
+gl_STENCIL_BACK_PASS_DEPTH_FAIL :: Num a => a
+gl_STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802
+
+gl_STENCIL_BACK_PASS_DEPTH_PASS :: Num a => a
+gl_STENCIL_BACK_PASS_DEPTH_PASS = 0x8803
+
+gl_STENCIL_BACK_REF :: Num a => a
+gl_STENCIL_BACK_REF = 0x8CA3
+
+gl_STENCIL_BACK_VALUE_MASK :: Num a => a
+gl_STENCIL_BACK_VALUE_MASK = 0x8CA4
+
+gl_STENCIL_BACK_WRITEMASK :: Num a => a
+gl_STENCIL_BACK_WRITEMASK = 0x8CA5
+
+gl_VIEWPORT :: Num a => a
+gl_VIEWPORT = 0x0BA2
+
+gl_SCISSOR_BOX :: Num a => a
+gl_SCISSOR_BOX = 0x0C10
+
+gl_COLOR_CLEAR_VALUE :: Num a => a
+gl_COLOR_CLEAR_VALUE = 0x0C22
+
+gl_COLOR_WRITEMASK :: Num a => a
+gl_COLOR_WRITEMASK = 0x0C23
+
+gl_UNPACK_ALIGNMENT :: Num a => a
+gl_UNPACK_ALIGNMENT = 0x0CF5
+
+gl_PACK_ALIGNMENT :: Num a => a
+gl_PACK_ALIGNMENT = 0x0D05
+
+gl_MAX_TEXTURE_SIZE :: Num a => a
+gl_MAX_TEXTURE_SIZE = 0x0D33
+
+gl_MAX_VIEWPORT_DIMS :: Num a => a
+gl_MAX_VIEWPORT_DIMS = 0x0D3A
+
+gl_SUBPIXEL_BITS :: Num a => a
+gl_SUBPIXEL_BITS = 0x0D50
+
+gl_RED_BITS :: Num a => a
+gl_RED_BITS = 0x0D52
+
+gl_GREEN_BITS :: Num a => a
+gl_GREEN_BITS = 0x0D53
+
+gl_BLUE_BITS :: Num a => a
+gl_BLUE_BITS = 0x0D54
+
+gl_ALPHA_BITS :: Num a => a
+gl_ALPHA_BITS = 0x0D55
+
+gl_DEPTH_BITS :: Num a => a
+gl_DEPTH_BITS = 0x0D56
+
+gl_STENCIL_BITS :: Num a => a
+gl_STENCIL_BITS = 0x0D57
+
+gl_POLYGON_OFFSET_UNITS :: Num a => a
+gl_POLYGON_OFFSET_UNITS = 0x2A00
+
+gl_POLYGON_OFFSET_FACTOR :: Num a => a
+gl_POLYGON_OFFSET_FACTOR = 0x8038
+
+gl_TEXTURE_BINDING_2D :: Num a => a
+gl_TEXTURE_BINDING_2D = 0x8069
+
+gl_SAMPLE_BUFFERS :: Num a => a
+gl_SAMPLE_BUFFERS = 0x80A8
+
+gl_SAMPLES :: Num a => a
+gl_SAMPLES = 0x80A9
+
+gl_SAMPLE_COVERAGE_VALUE :: Num a => a
+gl_SAMPLE_COVERAGE_VALUE = 0x80AA
+
+gl_SAMPLE_COVERAGE_INVERT :: Num a => a
+gl_SAMPLE_COVERAGE_INVERT = 0x80AB
+
+gl_COMPRESSED_TEXTURE_FORMATS :: Num a => a
+gl_COMPRESSED_TEXTURE_FORMATS = 0x86A3
+
+gl_DONT_CARE :: Num a => a
+gl_DONT_CARE = 0x1100
+
+gl_FASTEST :: Num a => a
+gl_FASTEST = 0x1101
+
+gl_NICEST :: Num a => a
+gl_NICEST = 0x1102
+
+gl_GENERATE_MIPMAP_HINT :: Num a => a
+gl_GENERATE_MIPMAP_HINT = 0x8192
+
+gl_BYTE :: Num a => a
+gl_BYTE = 0x1400
+
+gl_UNSIGNED_BYTE :: Num a => a
+gl_UNSIGNED_BYTE = 0x1401
+
+gl_SHORT :: Num a => a
+gl_SHORT = 0x1402
+
+gl_UNSIGNED_SHORT :: Num a => a
+gl_UNSIGNED_SHORT = 0x1403
+
+gl_INT :: Num a => a
+gl_INT = 0x1404
+
+gl_UNSIGNED_INT :: Num a => a
+gl_UNSIGNED_INT = 0x1405
+
+gl_FLOAT :: Num a => a
+gl_FLOAT = 0x1406
+
+gl_DEPTH_COMPONENT :: Num a => a
+gl_DEPTH_COMPONENT = 0x1902
+
+gl_ALPHA :: Num a => a
+gl_ALPHA = 0x1906
+
+gl_RGB :: Num a => a
+gl_RGB = 0x1907
+
+gl_RGBA :: Num a => a
+gl_RGBA = 0x1908
+
+gl_LUMINANCE :: Num a => a
+gl_LUMINANCE = 0x1909
+
+gl_LUMINANCE_ALPHA :: Num a => a
+gl_LUMINANCE_ALPHA = 0x190A
+
+gl_UNSIGNED_SHORT_4_4_4_4 :: Num a => a
+gl_UNSIGNED_SHORT_4_4_4_4 = 0x8033
+
+gl_UNSIGNED_SHORT_5_5_5_1 :: Num a => a
+gl_UNSIGNED_SHORT_5_5_5_1 = 0x8034
+
+gl_UNSIGNED_SHORT_5_6_5 :: Num a => a
+gl_UNSIGNED_SHORT_5_6_5 = 0x8363
+
+gl_FRAGMENT_SHADER :: Num a => a
+gl_FRAGMENT_SHADER = 0x8B30
+
+gl_VERTEX_SHADER :: Num a => a
+gl_VERTEX_SHADER = 0x8B31
+
+gl_MAX_VERTEX_ATTRIBS :: Num a => a
+gl_MAX_VERTEX_ATTRIBS = 0x8869
+
+gl_MAX_VERTEX_UNIFORM_VECTORS :: Num a => a
+gl_MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB
+
+gl_MAX_VARYING_VECTORS :: Num a => a
+gl_MAX_VARYING_VECTORS = 0x8DFC
+
+gl_MAX_COMBINED_TEXTURE_IMAGE_UNITS :: Num a => a
+gl_MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D
+
+gl_MAX_VERTEX_TEXTURE_IMAGE_UNITS :: Num a => a
+gl_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C
+
+gl_MAX_TEXTURE_IMAGE_UNITS :: Num a => a
+gl_MAX_TEXTURE_IMAGE_UNITS = 0x8872
+
+gl_MAX_FRAGMENT_UNIFORM_VECTORS :: Num a => a
+gl_MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD
+
+gl_SHADER_TYPE :: Num a => a
+gl_SHADER_TYPE = 0x8B4F
+
+gl_DELETE_STATUS :: Num a => a
+gl_DELETE_STATUS = 0x8B80
+
+gl_LINK_STATUS :: Num a => a
+gl_LINK_STATUS = 0x8B82
+
+gl_VALIDATE_STATUS :: Num a => a
+gl_VALIDATE_STATUS = 0x8B83
+
+gl_ATTACHED_SHADERS :: Num a => a
+gl_ATTACHED_SHADERS = 0x8B85
+
+gl_ACTIVE_UNIFORMS :: Num a => a
+gl_ACTIVE_UNIFORMS = 0x8B86
+
+gl_ACTIVE_ATTRIBUTES :: Num a => a
+gl_ACTIVE_ATTRIBUTES = 0x8B89
+
+gl_SHADING_LANGUAGE_VERSION :: Num a => a
+gl_SHADING_LANGUAGE_VERSION = 0x8B8C
+
+gl_CURRENT_PROGRAM :: Num a => a
+gl_CURRENT_PROGRAM = 0x8B8D
+
+gl_NEVER :: Num a => a
+gl_NEVER = 0x0200
+
+gl_LESS :: Num a => a
+gl_LESS = 0x0201
+
+gl_EQUAL :: Num a => a
+gl_EQUAL = 0x0202
+
+gl_LEQUAL :: Num a => a
+gl_LEQUAL = 0x0203
+
+gl_GREATER :: Num a => a
+gl_GREATER = 0x0204
+
+gl_NOTEQUAL :: Num a => a
+gl_NOTEQUAL = 0x0205
+
+gl_GEQUAL :: Num a => a
+gl_GEQUAL = 0x0206
+
+gl_ALWAYS :: Num a => a
+gl_ALWAYS = 0x0207
+
+gl_KEEP :: Num a => a
+gl_KEEP = 0x1E00
+
+gl_REPLACE :: Num a => a
+gl_REPLACE = 0x1E01
+
+gl_INCR :: Num a => a
+gl_INCR = 0x1E02
+
+gl_DECR :: Num a => a
+gl_DECR = 0x1E03
+
+gl_INVERT :: Num a => a
+gl_INVERT = 0x150A
+
+gl_INCR_WRAP :: Num a => a
+gl_INCR_WRAP = 0x8507
+
+gl_DECR_WRAP :: Num a => a
+gl_DECR_WRAP = 0x8508
+
+gl_VENDOR :: Num a => a
+gl_VENDOR = 0x1F00
+
+gl_RENDERER :: Num a => a
+gl_RENDERER = 0x1F01
+
+gl_VERSION :: Num a => a
+gl_VERSION = 0x1F02
+
+gl_NEAREST :: Num a => a
+gl_NEAREST = 0x2600
+
+gl_LINEAR :: Num a => a
+gl_LINEAR = 0x2601
+
+gl_NEAREST_MIPMAP_NEAREST :: Num a => a
+gl_NEAREST_MIPMAP_NEAREST = 0x2700
+
+gl_LINEAR_MIPMAP_NEAREST :: Num a => a
+gl_LINEAR_MIPMAP_NEAREST = 0x2701
+
+gl_NEAREST_MIPMAP_LINEAR :: Num a => a
+gl_NEAREST_MIPMAP_LINEAR = 0x2702
+
+gl_LINEAR_MIPMAP_LINEAR :: Num a => a
+gl_LINEAR_MIPMAP_LINEAR = 0x2703
+
+gl_TEXTURE_MAG_FILTER :: Num a => a
+gl_TEXTURE_MAG_FILTER = 0x2800
+
+gl_TEXTURE_MIN_FILTER :: Num a => a
+gl_TEXTURE_MIN_FILTER = 0x2801
+
+gl_TEXTURE_WRAP_S :: Num a => a
+gl_TEXTURE_WRAP_S = 0x2802
+
+gl_TEXTURE_WRAP_T :: Num a => a
+gl_TEXTURE_WRAP_T = 0x2803
+
+gl_TEXTURE_2D :: Num a => a
+gl_TEXTURE_2D = 0x0DE1
+
+gl_TEXTURE :: Num a => a
+gl_TEXTURE = 0x1702
+
+gl_TEXTURE_CUBE_MAP :: Num a => a
+gl_TEXTURE_CUBE_MAP = 0x8513
+
+gl_TEXTURE_BINDING_CUBE_MAP :: Num a => a
+gl_TEXTURE_BINDING_CUBE_MAP = 0x8514
+
+gl_TEXTURE_CUBE_MAP_POSITIVE_X :: Num a => a
+gl_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515
+
+gl_TEXTURE_CUBE_MAP_NEGATIVE_X :: Num a => a
+gl_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516
+
+gl_TEXTURE_CUBE_MAP_POSITIVE_Y :: Num a => a
+gl_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517
+
+gl_TEXTURE_CUBE_MAP_NEGATIVE_Y :: Num a => a
+gl_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518
+
+gl_TEXTURE_CUBE_MAP_POSITIVE_Z :: Num a => a
+gl_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519
+
+gl_TEXTURE_CUBE_MAP_NEGATIVE_Z :: Num a => a
+gl_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A
+
+gl_MAX_CUBE_MAP_TEXTURE_SIZE :: Num a => a
+gl_MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C
+
+gl_TEXTURE0 :: Num a => a
+gl_TEXTURE0 = 0x84C0
+
+gl_TEXTURE1 :: Num a => a
+gl_TEXTURE1 = 0x84C1
+
+gl_TEXTURE2 :: Num a => a
+gl_TEXTURE2 = 0x84C2
+
+gl_TEXTURE3 :: Num a => a
+gl_TEXTURE3 = 0x84C3
+
+gl_TEXTURE4 :: Num a => a
+gl_TEXTURE4 = 0x84C4
+
+gl_TEXTURE5 :: Num a => a
+gl_TEXTURE5 = 0x84C5
+
+gl_TEXTURE6 :: Num a => a
+gl_TEXTURE6 = 0x84C6
+
+gl_TEXTURE7 :: Num a => a
+gl_TEXTURE7 = 0x84C7
+
+gl_TEXTURE8 :: Num a => a
+gl_TEXTURE8 = 0x84C8
+
+gl_TEXTURE9 :: Num a => a
+gl_TEXTURE9 = 0x84C9
+
+gl_TEXTURE10 :: Num a => a
+gl_TEXTURE10 = 0x84CA
+
+gl_TEXTURE11 :: Num a => a
+gl_TEXTURE11 = 0x84CB
+
+gl_TEXTURE12 :: Num a => a
+gl_TEXTURE12 = 0x84CC
+
+gl_TEXTURE13 :: Num a => a
+gl_TEXTURE13 = 0x84CD
+
+gl_TEXTURE14 :: Num a => a
+gl_TEXTURE14 = 0x84CE
+
+gl_TEXTURE15 :: Num a => a
+gl_TEXTURE15 = 0x84CF
+
+gl_TEXTURE16 :: Num a => a
+gl_TEXTURE16 = 0x84D0
+
+gl_TEXTURE17 :: Num a => a
+gl_TEXTURE17 = 0x84D1
+
+gl_TEXTURE18 :: Num a => a
+gl_TEXTURE18 = 0x84D2
+
+gl_TEXTURE19 :: Num a => a
+gl_TEXTURE19 = 0x84D3
+
+gl_TEXTURE20 :: Num a => a
+gl_TEXTURE20 = 0x84D4
+
+gl_TEXTURE21 :: Num a => a
+gl_TEXTURE21 = 0x84D5
+
+gl_TEXTURE22 :: Num a => a
+gl_TEXTURE22 = 0x84D6
+
+gl_TEXTURE23 :: Num a => a
+gl_TEXTURE23 = 0x84D7
+
+gl_TEXTURE24 :: Num a => a
+gl_TEXTURE24 = 0x84D8
+
+gl_TEXTURE25 :: Num a => a
+gl_TEXTURE25 = 0x84D9
+
+gl_TEXTURE26 :: Num a => a
+gl_TEXTURE26 = 0x84DA
+
+gl_TEXTURE27 :: Num a => a
+gl_TEXTURE27 = 0x84DB
+
+gl_TEXTURE28 :: Num a => a
+gl_TEXTURE28 = 0x84DC
+
+gl_TEXTURE29 :: Num a => a
+gl_TEXTURE29 = 0x84DD
+
+gl_TEXTURE30 :: Num a => a
+gl_TEXTURE30 = 0x84DE
+
+gl_TEXTURE31 :: Num a => a
+gl_TEXTURE31 = 0x84DF
+
+gl_ACTIVE_TEXTURE :: Num a => a
+gl_ACTIVE_TEXTURE = 0x84E0
+
+gl_REPEAT :: Num a => a
+gl_REPEAT = 0x2901
+
+gl_CLAMP_TO_EDGE :: Num a => a
+gl_CLAMP_TO_EDGE = 0x812F
+
+gl_MIRRORED_REPEAT :: Num a => a
+gl_MIRRORED_REPEAT = 0x8370
+
+gl_FLOAT_VEC2 :: Num a => a
+gl_FLOAT_VEC2 = 0x8B50
+
+gl_FLOAT_VEC3 :: Num a => a
+gl_FLOAT_VEC3 = 0x8B51
+
+gl_FLOAT_VEC4 :: Num a => a
+gl_FLOAT_VEC4 = 0x8B52
+
+gl_INT_VEC2 :: Num a => a
+gl_INT_VEC2 = 0x8B53
+
+gl_INT_VEC3 :: Num a => a
+gl_INT_VEC3 = 0x8B54
+
+gl_INT_VEC4 :: Num a => a
+gl_INT_VEC4 = 0x8B55
+
+gl_BOOL :: Num a => a
+gl_BOOL = 0x8B56
+
+gl_BOOL_VEC2 :: Num a => a
+gl_BOOL_VEC2 = 0x8B57
+
+gl_BOOL_VEC3 :: Num a => a
+gl_BOOL_VEC3 = 0x8B58
+
+gl_BOOL_VEC4 :: Num a => a
+gl_BOOL_VEC4 = 0x8B59
+
+gl_FLOAT_MAT2 :: Num a => a
+gl_FLOAT_MAT2 = 0x8B5A
+
+gl_FLOAT_MAT3 :: Num a => a
+gl_FLOAT_MAT3 = 0x8B5B
+
+gl_FLOAT_MAT4 :: Num a => a
+gl_FLOAT_MAT4 = 0x8B5C
+
+gl_SAMPLER_2D :: Num a => a
+gl_SAMPLER_2D = 0x8B5E
+
+gl_SAMPLER_CUBE :: Num a => a
+gl_SAMPLER_CUBE = 0x8B60
+
+gl_VERTEX_ATTRIB_ARRAY_ENABLED :: Num a => a
+gl_VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622
+
+gl_VERTEX_ATTRIB_ARRAY_SIZE :: Num a => a
+gl_VERTEX_ATTRIB_ARRAY_SIZE = 0x8623
+
+gl_VERTEX_ATTRIB_ARRAY_STRIDE :: Num a => a
+gl_VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624
+
+gl_VERTEX_ATTRIB_ARRAY_TYPE :: Num a => a
+gl_VERTEX_ATTRIB_ARRAY_TYPE = 0x8625
+
+gl_VERTEX_ATTRIB_ARRAY_NORMALIZED :: Num a => a
+gl_VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A
+
+gl_VERTEX_ATTRIB_ARRAY_POINTER :: Num a => a
+gl_VERTEX_ATTRIB_ARRAY_POINTER = 0x8645
+
+gl_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING :: Num a => a
+gl_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F
+
+gl_COMPILE_STATUS :: Num a => a
+gl_COMPILE_STATUS = 0x8B81
+
+gl_LOW_FLOAT :: Num a => a
+gl_LOW_FLOAT = 0x8DF0
+
+gl_MEDIUM_FLOAT :: Num a => a
+gl_MEDIUM_FLOAT = 0x8DF1
+
+gl_HIGH_FLOAT :: Num a => a
+gl_HIGH_FLOAT = 0x8DF2
+
+gl_LOW_INT :: Num a => a
+gl_LOW_INT = 0x8DF3
+
+gl_MEDIUM_INT :: Num a => a
+gl_MEDIUM_INT = 0x8DF4
+
+gl_HIGH_INT :: Num a => a
+gl_HIGH_INT = 0x8DF5
+
+gl_FRAMEBUFFER :: Num a => a
+gl_FRAMEBUFFER = 0x8D40
+
+gl_RENDERBUFFER :: Num a => a
+gl_RENDERBUFFER = 0x8D41
+
+gl_RGBA4 :: Num a => a
+gl_RGBA4 = 0x8056
+
+gl_RGB5_A1 :: Num a => a
+gl_RGB5_A1 = 0x8057
+
+gl_RGB565 :: Num a => a
+gl_RGB565 = 0x8D62
+
+gl_DEPTH_COMPONENT16 :: Num a => a
+gl_DEPTH_COMPONENT16 = 0x81A5
+
+gl_STENCIL_INDEX :: Num a => a
+gl_STENCIL_INDEX = 0x1901
+
+gl_STENCIL_INDEX8 :: Num a => a
+gl_STENCIL_INDEX8 = 0x8D48
+
+gl_DEPTH_STENCIL :: Num a => a
+gl_DEPTH_STENCIL = 0x84F9
+
+gl_RENDERBUFFER_WIDTH :: Num a => a
+gl_RENDERBUFFER_WIDTH = 0x8D42
+
+gl_RENDERBUFFER_HEIGHT :: Num a => a
+gl_RENDERBUFFER_HEIGHT = 0x8D43
+
+gl_RENDERBUFFER_INTERNAL_FORMAT :: Num a => a
+gl_RENDERBUFFER_INTERNAL_FORMAT = 0x8D44
+
+gl_RENDERBUFFER_RED_SIZE :: Num a => a
+gl_RENDERBUFFER_RED_SIZE = 0x8D50
+
+gl_RENDERBUFFER_GREEN_SIZE :: Num a => a
+gl_RENDERBUFFER_GREEN_SIZE = 0x8D51
+
+gl_RENDERBUFFER_BLUE_SIZE :: Num a => a
+gl_RENDERBUFFER_BLUE_SIZE = 0x8D52
+
+gl_RENDERBUFFER_ALPHA_SIZE :: Num a => a
+gl_RENDERBUFFER_ALPHA_SIZE = 0x8D53
+
+gl_RENDERBUFFER_DEPTH_SIZE :: Num a => a
+gl_RENDERBUFFER_DEPTH_SIZE = 0x8D54
+
+gl_RENDERBUFFER_STENCIL_SIZE :: Num a => a
+gl_RENDERBUFFER_STENCIL_SIZE = 0x8D55
+
+gl_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE :: Num a => a
+gl_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0
+
+gl_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME :: Num a => a
+gl_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1
+
+gl_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL :: Num a => a
+gl_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2
+
+gl_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE :: Num a => a
+gl_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3
+
+gl_COLOR_ATTACHMENT0 :: Num a => a
+gl_COLOR_ATTACHMENT0 = 0x8CE0
+
+gl_DEPTH_ATTACHMENT :: Num a => a
+gl_DEPTH_ATTACHMENT = 0x8D00
+
+gl_STENCIL_ATTACHMENT :: Num a => a
+gl_STENCIL_ATTACHMENT = 0x8D20
+
+gl_DEPTH_STENCIL_ATTACHMENT :: Num a => a
+gl_DEPTH_STENCIL_ATTACHMENT = 0x821A
+
+gl_NONE :: Num a => a
+gl_NONE = 0
+
+gl_FRAMEBUFFER_COMPLETE :: Num a => a
+gl_FRAMEBUFFER_COMPLETE = 0x8CD5
+
+gl_FRAMEBUFFER_INCOMPLETE_ATTACHMENT :: Num a => a
+gl_FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6
+
+gl_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT :: Num a => a
+gl_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7
+
+gl_FRAMEBUFFER_INCOMPLETE_DIMENSIONS :: Num a => a
+gl_FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9
+
+gl_FRAMEBUFFER_UNSUPPORTED :: Num a => a
+gl_FRAMEBUFFER_UNSUPPORTED = 0x8CDD
+
+gl_FRAMEBUFFER_BINDING :: Num a => a
+gl_FRAMEBUFFER_BINDING = 0x8CA6
+
+gl_RENDERBUFFER_BINDING :: Num a => a
+gl_RENDERBUFFER_BINDING = 0x8CA7
+
+gl_MAX_RENDERBUFFER_SIZE :: Num a => a
+gl_MAX_RENDERBUFFER_SIZE = 0x84E8
+
+gl_INVALID_FRAMEBUFFER_OPERATION :: Num a => a
+gl_INVALID_FRAMEBUFFER_OPERATION = 0x0506
+
+gl_UNPACK_FLIP_Y_WEBGL :: Num a => a
+gl_UNPACK_FLIP_Y_WEBGL = 0x9240
+
+gl_UNPACK_PREMULTIPLY_ALPHA_WEBGL :: Num a => a
+gl_UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241
+
+gl_CONTEXT_LOST_WEBGL :: Num a => a
+gl_CONTEXT_LOST_WEBGL = 0x9242
+
+gl_UNPACK_COLORSPACE_CONVERSION_WEBGL :: Num a => a
+gl_UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243
+
+gl_BROWSER_DEFAULT_WEBGL :: Num a => a
+gl_BROWSER_DEFAULT_WEBGL = 0x9244
diff --git a/FWGL/Backend/JavaScript/WebGL/Raw.hs b/FWGL/Backend/JavaScript/WebGL/Raw.hs
new file mode 100644
--- /dev/null
+++ b/FWGL/Backend/JavaScript/WebGL/Raw.hs
@@ -0,0 +1,514 @@
+module FWGL.Backend.JavaScript.WebGL.Raw where
+
+import Data.Int
+import Data.Word
+
+import GHCJS.Types
+
+import FWGL.Backend.JavaScript.WebGL.Types
+
+foreign import javascript unsafe "$1.activeTexture($2)"
+        glActiveTexture :: Ctx -> Word -> IO ()
+
+foreign import javascript unsafe "$1.attachShader($2, $3)"
+        glAttachShader :: Ctx -> Program -> Shader -> IO ()
+
+foreign import javascript unsafe "$1.bindAttribLocation($2, $3, $4)"
+        glBindAttribLocation :: Ctx -> Program -> Word -> JSString -> IO ()
+
+foreign import javascript unsafe "$1.bindBuffer($2, $3)"
+        glBindBuffer :: Ctx -> Word -> Buffer -> IO ()
+
+foreign import javascript unsafe "$1.bindFramebuffer($2, $3)"
+        glBindFramebuffer :: Ctx -> Word -> FrameBuffer -> IO ()
+
+foreign import javascript unsafe "$1.bindRenderbuffer($2, $3)"
+        glBindRenderbuffer :: Ctx -> Word -> RenderBuffer -> IO ()
+
+foreign import javascript unsafe "$1.bindTexture($2, $3)"
+        glBindTexture :: Ctx -> Word -> Texture -> IO ()
+
+foreign import javascript unsafe "$1.blendColor($2, $3, $4, $5)"
+        glBlendColor :: Ctx -> Float -> Float -> Float -> Float -> IO ()
+
+foreign import javascript unsafe "$1.blendEquation($2)"
+        glBlendEquation :: Ctx -> Word -> IO ()
+
+foreign import javascript unsafe "$1.blendEquationSeparate($2, $3)"
+        glBlendEquationSeparate :: Ctx -> Word -> Word -> IO ()
+
+foreign import javascript unsafe "$1.blendFunc($2, $3)"
+        glBlendFunc :: Ctx -> Word -> Word -> IO ()
+
+foreign import javascript unsafe "$1.blendFuncSeparate($2, $3, $4, $5)"
+        glBlendFuncSeparate :: Ctx -> Word -> Word -> Word -> Word -> IO ()
+
+{-
+foreign import javascript unsafe "$1.bufferData($2, $3, $4)"
+        glBufferData :: Ctx -> Word -> Word -> Word -> IO ()
+-}
+
+foreign import javascript unsafe "$1.bufferData($2, $3, $4)"
+        glBufferData :: Ctx -> Word -> ArrayBufferView -> Word -> IO ()
+
+{-
+foreign import javascript unsafe "$1.bufferData($2, $3, $4)"
+        glBufferData :: Ctx -> Word -> ArrayBuffer -> Word -> IO ()
+-}
+
+foreign import javascript unsafe "$1.bufferSubData($2, $3, $4)"
+        glBufferSubData :: Ctx -> Word -> Word -> ArrayBufferView -> IO ()
+
+{-
+foreign import javascript unsafe "$1.bufferSubData($2, $3, $4)"
+        glBufferSubData :: Ctx -> Word -> Word -> ArrayBuffer -> IO ()
+-}
+
+foreign import javascript unsafe "$1.checkFramebufferStatus($2)"
+        glCheckFramebufferStatus :: Ctx -> Word -> IO Word
+
+foreign import javascript unsafe "$1.clear($2)"
+        glClear :: Ctx -> Word -> IO ()
+
+foreign import javascript unsafe "$1.clearColor($2, $3, $4, $5)"
+        glClearColor :: Ctx -> Float -> Float -> Float -> Float -> IO ()
+
+foreign import javascript unsafe "$1.clearDepth($2)"
+        glClearDepth :: Ctx -> Float -> IO ()
+
+foreign import javascript unsafe "$1.clearStencil($2)"
+        glClearStencil :: Ctx -> Int -> IO ()
+
+foreign import javascript unsafe "$1.colorMask($2, $3, $4, $5)"
+        glColorMask :: Ctx -> Bool -> Bool -> Bool -> Bool -> IO ()
+
+foreign import javascript unsafe "$1.compileShader($2)"
+        glCompileShader :: Ctx -> Shader -> IO ()
+
+foreign import javascript unsafe "$1.compressedTexImage2D($2, $3, $4, $5, $6, $7, $8)"
+        glCompressedTexImage2D :: Ctx -> Word -> Int -> Word -> Int -> Int -> Int -> ArrayBufferView -> IO ()
+
+foreign import javascript unsafe "$1.compressedTexSubImage2D($2, $3, $4, $5, $6, $7, $8, $9)"
+        glCompressedTexSubImage2D :: Ctx -> Word -> Int -> Int -> Int -> Int -> Int -> Word -> ArrayBufferView -> IO ()
+
+foreign import javascript unsafe "$1.copyTexImage2D($2, $3, $4, $5, $6, $7, $8, $9)"
+        glCopyTexImage2D :: Ctx -> Word -> Int -> Word -> Int -> Int -> Int -> Int -> Int -> IO ()
+
+foreign import javascript unsafe "$1.copyTexSubImage2D($2, $3, $4, $5, $6, $7, $8, $9)"
+        glCopyTexSubImage2D :: Ctx -> Word -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()
+
+foreign import javascript unsafe "$1.createBuffer()"
+        glCreateBuffer :: Ctx -> IO Buffer
+
+foreign import javascript unsafe "$1.createFramebuffer()"
+        glCreateFramebuffer :: Ctx -> IO FrameBuffer
+
+foreign import javascript unsafe "$1.createProgram()"
+        glCreateProgram :: Ctx -> IO Program
+
+foreign import javascript unsafe "$1.createRenderbuffer()"
+        glCreateRenderbuffer :: Ctx -> IO RenderBuffer
+
+foreign import javascript unsafe "$1.createShader($2)"
+        glCreateShader :: Ctx -> Word -> IO Shader
+
+foreign import javascript unsafe "$1.createTexture()"
+        glCreateTexture :: Ctx -> IO Texture
+
+foreign import javascript unsafe "$1.cullFace($2)"
+        glCullFace :: Ctx -> Word -> IO ()
+
+foreign import javascript unsafe "$1.deleteBuffer($2)"
+        glDeleteBuffer :: Ctx -> Buffer -> IO ()
+
+foreign import javascript unsafe "$1.deleteFramebuffer($2)"
+        glDeleteFramebuffer :: Ctx -> FrameBuffer -> IO ()
+
+foreign import javascript unsafe "$1.deleteProgram($2)"
+        glDeleteProgram :: Ctx -> Program -> IO ()
+
+foreign import javascript unsafe "$1.deleteRenderbuffer($2)"
+        glDeleteRenderbuffer :: Ctx -> RenderBuffer -> IO ()
+
+foreign import javascript unsafe "$1.deleteShader($2)"
+        glDeleteShader :: Ctx -> Shader -> IO ()
+
+foreign import javascript unsafe "$1.deleteTexture($2)"
+        glDeleteTexture :: Ctx -> Texture -> IO ()
+
+foreign import javascript unsafe "$1.depthFunc($2)"
+        glDepthFunc :: Ctx -> Word -> IO ()
+
+foreign import javascript unsafe "$1.depthMask($2)"
+        glDepthMask :: Ctx -> Bool -> IO ()
+
+foreign import javascript unsafe "$1.depthRange($2, $3)"
+        glDepthRange :: Ctx -> Float -> Float -> IO ()
+
+foreign import javascript unsafe "$1.detachShader($2, $3)"
+        glDetachShader :: Ctx -> Program -> Shader -> IO ()
+
+foreign import javascript unsafe "$1.disable($2)"
+        glDisable :: Ctx -> Word -> IO ()
+
+foreign import javascript unsafe "$1.disableVertexAttribArray($2)"
+        glDisableVertexAttribArray :: Ctx -> Word -> IO ()
+
+foreign import javascript unsafe "$1.drawArrays($2, $3, $4)"
+        glDrawArrays :: Ctx -> Word -> Int -> Int -> IO ()
+
+foreign import javascript unsafe "$1.drawElements($2, $3, $4, $5)"
+        glDrawElements :: Ctx -> Word -> Int -> Word -> Word -> IO ()
+
+foreign import javascript unsafe "$1.enable($2)"
+        glEnable :: Ctx -> Word -> IO ()
+
+foreign import javascript unsafe "$1.enableVertexAttribArray($2)"
+        glEnableVertexAttribArray :: Ctx -> Word -> IO ()
+
+foreign import javascript unsafe "$1.finish()"
+        glFinish :: Ctx -> IO ()
+
+foreign import javascript unsafe "$1.flush()"
+        glFlush :: Ctx -> IO ()
+
+foreign import javascript unsafe "$1.framebufferRenderbuffer($2, $3, $4, $5)"
+        glFramebufferRenderbuffer :: Ctx -> Word -> Word -> Word -> RenderBuffer -> IO ()
+
+foreign import javascript unsafe "$1.framebufferTexture2D($2, $3, $4, $5, $6)"
+        glFramebufferTexture2D :: Ctx -> Word -> Word -> Word -> Texture -> Int -> IO ()
+
+foreign import javascript unsafe "$1.frontFace($2)"
+        glFrontFace :: Ctx -> Word -> IO ()
+
+foreign import javascript unsafe "$1.generateMipmap($2)"
+        glGenerateMipmap :: Ctx -> Word -> IO ()
+
+foreign import javascript unsafe "$1.getActiveAttrib($2, $3)"
+        glGetActiveAttrib :: Ctx -> Program -> Word -> IO ActiveInfo
+
+foreign import javascript unsafe "$1.getActiveUniform($2, $3)"
+        glGetActiveUniform :: Ctx -> Program -> Word -> IO ActiveInfo
+
+{-
+foreign import javascript unsafe "$1.getAttachedShaders($2)"
+        glGetAttachedShaders :: Ctx -> Program -> IO (Sequence Shader)
+-}
+
+foreign import javascript unsafe "$1.getAttribLocation($2, $3)"
+        glGetAttribLocation :: Ctx -> Program -> JSString -> IO Int
+
+foreign import javascript unsafe "$1.getBufferParameter($2, $3)"
+        glGetBufferParameter :: Ctx -> Word -> Word -> IO (JSRef a)
+
+foreign import javascript unsafe "$1.getParameter($2)"
+        glGetParameter :: Ctx -> Word -> IO (JSRef a)
+
+foreign import javascript unsafe "$1.getError()"
+        glGetError :: Ctx -> IO Word
+
+foreign import javascript unsafe "$1.getFramebufferAttachmentParameter($2, $3)"
+        glGetFramebufferAttachmentParameter :: Ctx -> Word -> Word -> IO Word
+
+foreign import javascript unsafe "$1.getProgramInfoLog($2)"
+        glGetProgramInfoLog :: Ctx -> Program -> IO JSString
+
+foreign import javascript unsafe "$1.getRenderbufferParameter($2, $3)"
+        glGetRenderbufferParameter :: Ctx -> Word -> Word -> IO (JSRef a)
+
+foreign import javascript unsafe "$1.getShaderParameter($2, $3)"
+        glGetShaderParameter :: Ctx -> Shader -> Word -> IO (JSRef a)
+
+foreign import javascript unsafe "$1.getShaderPrecisionFormat($2, $3)"
+        glGetShaderPrecisionFormat :: Ctx -> Word -> Word -> IO ShaderPrecisionFormat
+
+foreign import javascript unsafe "$1.getShaderInfoLog($2)"
+        glGetShaderInfoLog :: Ctx -> Shader -> IO JSString
+
+foreign import javascript unsafe "$1.getShaderSource($2)"
+        glGetShaderSource :: Ctx -> Shader -> IO JSString
+
+foreign import javascript unsafe "$1.getTexParameter($2, $3)"
+        glGetTexParameter :: Ctx -> Word -> Word -> IO (JSRef a)
+
+foreign import javascript unsafe "$1.getUniform($2, $3)"
+        glGetUniform :: Ctx -> Program -> UniformLocation -> IO (JSRef a)
+
+foreign import javascript unsafe "$1.getUniformLocation($2, $3)"
+        glGetUniformLocation :: Ctx -> Program -> JSString -> IO UniformLocation
+
+foreign import javascript unsafe "$1.getVertexAttrib($2, $3)"
+        glGetVertexAttrib :: Ctx -> Word -> Word -> IO (JSRef a)
+
+foreign import javascript unsafe "$1.getVertexAttribOffset($2, $3)"
+        glGetVertexAttribOffset :: Ctx -> Word -> Word -> IO Word
+
+foreign import javascript unsafe "$1.hint($2, $3)"
+        glHint :: Ctx -> Word -> Word -> IO ()
+
+foreign import javascript unsafe "$1.isBuffer($2)"
+        glIsBuffer :: Ctx -> Buffer -> IO Bool
+
+foreign import javascript unsafe "$1.isEnabled($2)"
+        glIsEnabled :: Ctx -> Word -> IO Bool
+
+foreign import javascript unsafe "$1.isFramebuffer($2)"
+        glIsFramebuffer :: Ctx -> FrameBuffer -> IO Bool
+
+foreign import javascript unsafe "$1.isProgram($2)"
+        glIsProgram :: Ctx -> Program -> IO Bool
+
+foreign import javascript unsafe "$1.isRenderbuffer($2)"
+        glIsRenderbuffer :: Ctx -> RenderBuffer -> IO Bool
+
+foreign import javascript unsafe "$1.isShader($2)"
+        glIsShader :: Ctx -> Shader -> IO Bool
+
+foreign import javascript unsafe "$1.isTexture($2)"
+        glIsTexture :: Ctx -> Texture -> IO Bool
+
+foreign import javascript unsafe "$1.lineWidth($2)"
+        glLineWidth :: Ctx -> Float -> IO ()
+
+foreign import javascript unsafe "$1.linkProgram($2)"
+        glLinkProgram :: Ctx -> Program -> IO ()
+
+foreign import javascript unsafe "$1.pixelStorei($2, $3)"
+        glPixelStorei :: Ctx -> Word -> Int -> IO ()
+
+foreign import javascript unsafe "$1.polygonOffset($2, $3)"
+        glPolygonOffset :: Ctx -> Float -> Float -> IO ()
+
+foreign import javascript unsafe "$1.readPixels($2, $3, $4, $5, $6, $7, $8)"
+        glReadPixels :: Ctx -> Int -> Int -> Int -> Int -> Word -> Word -> ArrayBufferView -> IO ()
+
+foreign import javascript unsafe "$1.renderbufferStorage($2, $3, $4, $5)"
+        glRenderbufferStorage :: Ctx -> Word -> Word -> Int -> Int -> IO ()
+
+foreign import javascript unsafe "$1.sampleCoverage($2, $3)"
+        glSampleCoverage :: Ctx -> Float -> Bool -> IO ()
+
+foreign import javascript unsafe "$1.scissor($2, $3, $4, $5)"
+        glScissor :: Ctx -> Int -> Int -> Int -> Int -> IO ()
+
+foreign import javascript unsafe "$1.shaderSource($2, $3)"
+        glShaderSource :: Ctx -> Shader -> JSString -> IO ()
+
+foreign import javascript unsafe "$1.stencilFunc($2, $3, $4)"
+        glStencilFunc :: Ctx -> Word -> Int -> Word -> IO ()
+
+foreign import javascript unsafe "$1.stencilFuncSeparate($2, $3, $4, $5)"
+        glStencilFuncSeparate :: Ctx -> Word -> Word -> Int -> Word -> IO ()
+
+foreign import javascript unsafe "$1.stencilMask($2)"
+        glStencilMask :: Ctx -> Word -> IO ()
+
+foreign import javascript unsafe "$1.stencilMaskSeparate($2, $3)"
+        glStencilMaskSeparate :: Ctx -> Word -> Word -> IO ()
+
+foreign import javascript unsafe "$1.stencilOp($2, $3, $4)"
+        glStencilOp :: Ctx -> Word -> Word -> Word -> IO ()
+
+foreign import javascript unsafe "$1.stencilOpSeparate($2, $3, $4, $5)"
+        glStencilOpSeparate :: Ctx -> Word -> Word -> Word -> Word -> IO ()
+
+foreign import javascript unsafe "$1.texImage2D($2, $3, $4, $5, $6, $7, $8, $9, $10)"
+        glTexImage2DBuffer :: Ctx -> Word -> Int -> Int -> Int -> Int -> Int -> Word -> Word -> ArrayBufferView -> IO ()
+
+foreign import javascript unsafe "$1.texImage2D($2, $3, $4, $5, $6, $7)"
+        glTexImage2DElement :: Ctx -> Word -> Int -> Int -> Word -> Word -> Image -> IO ()
+
+{-
+foreign import javascript unsafe "$1.texImage2D()"
+        glTexImage2D :: Ctx -> Word -> Int -> Word -> Word -> Word -> CanvasElement -> Void 
+
+foreign import javascript unsafe "$1.texImage2D()"
+        glTexImage2D :: Ctx -> Word -> Int -> Word -> Word -> Word -> VideoElement -> Void 
+-}
+
+foreign import javascript unsafe "$1.texParameterf($2, $3, $4)"
+        glTexParameterf :: Ctx -> Word -> Word -> Float -> IO ()
+
+foreign import javascript unsafe "$1.texParameteri($2, $3, $4)"
+        glTexParameteri :: Ctx -> Word -> Word -> Int -> IO ()
+
+foreign import javascript unsafe "$1.texSubImage2D($2, $3, $4, $5, $6, $7, $8, $9, $10)"
+        glTexSubImage2D :: Ctx -> Word -> Int -> Int -> Int -> Int -> Int -> Word -> Word -> ArrayBufferView -> IO ()
+
+{-
+
+foreign import javascript unsafe "$1.texSubImage2D()"
+        glTexSubImage2D :: Ctx -> Word -> Int -> Int -> Int -> Word -> Word -> CanvasElement -> Void 
+
+foreign import javascript unsafe "$1.texSubImage2D()"
+        glTexSubImage2D :: Ctx -> Word -> Int -> Int -> Int -> Word -> Word -> VideoElement -> Void 
+
+-}
+
+foreign import javascript unsafe "$1.uniform1f($2, $3)"
+        glUniform1f :: Ctx -> UniformLocation -> Float -> IO ()
+
+foreign import javascript unsafe "$1.uniform1fv($2, $3)"
+        glUniform1fv :: Ctx -> UniformLocation -> Float32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.uniform1fv($2 Sequence Float ->)"
+        glUniform1fv :: Ctx -> UniformLocation -> Sequence Float -> IO ()
+-}
+
+foreign import javascript unsafe "$1.uniform1i($2, $3)"
+        glUniform1i :: Ctx -> UniformLocation -> Int -> IO ()
+
+foreign import javascript unsafe "$1.uniform1iv($2, $3)"
+        glUniform1iv :: Ctx -> UniformLocation -> Int32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.uniform1iv($2 Sequence Int ->)"
+        glUniform1iv :: Ctx -> UniformLocation -> Sequence Int -> IO ()
+-}
+
+foreign import javascript unsafe "$1.uniform2f($2, $3, $4)"
+        glUniform2f :: Ctx -> UniformLocation -> Float -> Float -> IO ()
+
+foreign import javascript unsafe "$1.uniform2fv($2, $3)"
+        glUniform2fv :: Ctx -> UniformLocation -> Float32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.uniform2fv($2 Sequence Float ->)"
+        glUniform2fv :: Ctx -> UniformLocation -> Sequence Float -> IO ()
+-}
+
+foreign import javascript unsafe "$1.uniform2i($2, $3, $4)"
+        glUniform2i :: Ctx -> UniformLocation -> Int -> Int -> IO ()
+
+foreign import javascript unsafe "$1.uniform2iv($2, $3)"
+        glUniform2iv :: Ctx -> UniformLocation -> Int32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.uniform2iv($2 Sequence Int ->)"
+        glUniform2iv :: Ctx -> UniformLocation -> Sequence Int -> IO ()
+-}
+
+foreign import javascript unsafe "$1.uniform3f($2, $3, $4, $5)"
+        glUniform3f :: Ctx -> UniformLocation -> Float -> Float -> Float -> IO ()
+
+foreign import javascript unsafe "$1.uniform3fv($2, $3)"
+        glUniform3fv :: Ctx -> UniformLocation -> Float32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.uniform3fv($2 Sequence Float ->)"
+        glUniform3fv :: Ctx -> UniformLocation -> Sequence Float -> IO ()
+-}
+
+foreign import javascript unsafe "$1.uniform3i($2, $3, $4, $5)"
+        glUniform3i :: Ctx -> UniformLocation -> Int -> Int -> Int -> IO ()
+
+foreign import javascript unsafe "$1.uniform3iv($2, $3)"
+        glUniform3iv :: Ctx -> UniformLocation -> Int32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.uniform3iv($2 Sequence Int ->)"
+        glUniform3iv :: Ctx -> UniformLocation -> Sequence Int -> IO ()
+-}
+
+foreign import javascript unsafe "$1.uniform4f($2, $3, $4, $5, $6)"
+        glUniform4f :: Ctx -> UniformLocation -> Float -> Float -> Float -> Float -> IO ()
+
+foreign import javascript unsafe "$1.uniform4fv($2, $3)"
+        glUniform4fv :: Ctx -> UniformLocation -> Float32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.uniform4fv($2 Sequence Float ->)"
+        glUniform4fv :: Ctx -> UniformLocation -> Sequence Float -> IO ()
+-}
+
+foreign import javascript unsafe "$1.uniform4i($2, $3, $4, $5, $6)"
+        glUniform4i :: Ctx -> UniformLocation -> Int -> Int -> Int -> Int -> IO ()
+
+foreign import javascript unsafe "$1.uniform4iv($2, $3)"
+        glUniform4iv :: Ctx -> UniformLocation -> Int32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.uniform4iv($2 Sequence Int ->)"
+        glUniform4iv :: Ctx -> UniformLocation -> Sequence Int -> IO ()
+-}
+
+foreign import javascript unsafe "$1.uniformMatrix2fv($2, $3, $4)"
+        glUniformMatrix2fv :: Ctx -> UniformLocation -> Bool -> Float32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.uniformMatrix2fv($2, $3 Sequence Float ->)"
+        glUniformMatrix2fv :: Ctx -> UniformLocation -> Bool -> Sequence Float -> IO ()
+-}
+
+foreign import javascript unsafe "$1.uniformMatrix3fv($2, $3, $4)"
+        glUniformMatrix3fv :: Ctx -> UniformLocation -> Bool -> Float32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.uniformMatrix3fv($2, $3 Sequence Float ->)"
+        glUniformMatrix3fv :: Ctx -> UniformLocation -> Bool -> Sequence Float -> IO ()
+-}
+
+foreign import javascript unsafe "$1.uniformMatrix4fv($2, $3, $4)"
+        glUniformMatrix4fv :: Ctx -> UniformLocation -> Bool -> Float32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.uniformMatrix4fv($2, $3 Sequence Float ->)"
+        glUniformMatrix4fv :: Ctx -> UniformLocation -> Bool -> Sequence Float -> IO ()
+-}
+
+foreign import javascript unsafe "$1.useProgram($2)"
+        glUseProgram :: Ctx -> Program -> IO ()
+
+foreign import javascript unsafe "$1.validateProgram($2)"
+        glValidateProgram :: Ctx -> Program -> IO ()
+
+foreign import javascript unsafe "$1.vertexAttrib1f($2, $3)"
+        glVertexAttrib1f :: Ctx -> Word -> Float -> IO ()
+
+foreign import javascript unsafe "$1.vertexAttrib1fv($2, $3)"
+        glVertexAttrib1fv :: Ctx -> Word -> Float32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.vertexAttrib1fv($2 Sequence Float ->)"
+        glVertexAttrib1fv :: Ctx -> Word -> Sequence Float -> IO ()
+-}
+
+foreign import javascript unsafe "$1.vertexAttrib2f($2, $3, $4)"
+        glVertexAttrib2f :: Ctx -> Word -> Float -> Float -> IO ()
+
+foreign import javascript unsafe "$1.vertexAttrib2fv($2, $3)"
+        glVertexAttrib2fv :: Ctx -> Word -> Float32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.vertexAttrib2fv($2 Sequence Float ->)"
+        glVertexAttrib2fv :: Ctx -> Word -> Sequence Float -> IO ()
+-}
+
+foreign import javascript unsafe "$1.vertexAttrib3f($2, $3, $4, $5)"
+        glVertexAttrib3f :: Ctx -> Word -> Float -> Float -> Float -> IO ()
+
+foreign import javascript unsafe "$1.vertexAttrib3fv($2, $3)"
+        glVertexAttrib3fv :: Ctx -> Word -> Float32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.vertexAttrib3fv($2 Sequence Float ->)"
+        glVertexAttrib3fv :: Ctx -> Word -> Sequence Float -> IO ()
+-}
+
+foreign import javascript unsafe "$1.vertexAttrib4f($2, $3, $4, $5, $6)"
+        glVertexAttrib4f :: Ctx -> Word -> Float -> Float -> Float -> Float -> IO ()
+
+foreign import javascript unsafe "$1.vertexAttrib4fv($2, $3)"
+        glVertexAttrib4fv :: Ctx -> Word -> Float32Array -> IO ()
+
+{-
+foreign import javascript unsafe "$1.vertexAttrib4fv($2 Sequence Float ->)"
+        vertexAttrib4fv :: Ctx -> Word -> Sequence Float -> IO ()
+-}
+
+foreign import javascript unsafe "$1.vertexAttribPointer($2, $3, $4, $5, $6, $7)"
+        glVertexAttribPointer :: Ctx -> Word -> Int -> Word -> Bool -> Int -> Word -> IO ()
+
+foreign import javascript unsafe "$1.viewport($2, $3, $4, $5)"
+        glViewport :: Ctx -> Int -> Int -> Int -> Int -> IO ()
diff --git a/FWGL/Backend/JavaScript/WebGL/Types.hs b/FWGL/Backend/JavaScript/WebGL/Types.hs
new file mode 100644
--- /dev/null
+++ b/FWGL/Backend/JavaScript/WebGL/Types.hs
@@ -0,0 +1,136 @@
+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}
+
+module FWGL.Backend.JavaScript.WebGL.Types (
+        Ctx,
+        Image,
+        Float32Array,
+        Int32Array,
+        Uint16Array,
+        Program,
+        Shader,
+        Buffer,
+        FrameBuffer,
+        RenderBuffer,
+        Texture,
+        UniformLocation,
+        ActiveInfo,
+        ShaderPrecisionFormat,
+        ArrayBufferView,
+        getCtx,
+        float32Array,
+        int32Array,
+        uint16Array,
+        uint8Array,
+        float32View,
+        int32View,
+        uint16View,
+        uint8View,
+        toJSArray,
+        listToJSArray,
+        noBuffer,
+        noTexture,
+        noArray
+) where
+
+import Data.Int (Int32)
+import Data.Word (Word8, Word16)
+import GHCJS.Marshal
+import GHCJS.Foreign
+import GHCJS.Types
+
+data Ctx_
+type Ctx = JSRef Ctx_
+
+data Image_
+type Image = JSRef Image_
+
+data Float32Array_
+type Float32Array = JSRef Float32Array_
+
+data Int32Array_
+type Int32Array = JSRef Int32Array_
+
+data Uint16Array_
+type Uint16Array = JSRef Uint16Array_
+
+data Uint8Array_
+type Uint8Array = JSRef Uint8Array_
+
+data Program_
+type Program = JSRef Program_
+
+data Shader_
+type Shader = JSRef Shader_
+
+data Buffer_
+type Buffer = JSRef Buffer_
+
+data FrameBuffer_
+type FrameBuffer = JSRef FrameBuffer_
+
+data RenderBuffer_
+type RenderBuffer = JSRef RenderBuffer_
+
+data Texture_
+type Texture = JSRef Texture_
+
+data UniformLocation_
+type UniformLocation = JSRef UniformLocation_
+
+data ActiveInfo_
+type ActiveInfo = JSRef ActiveInfo_
+
+data ShaderPrecisionFormat_
+type ShaderPrecisionFormat = JSRef ShaderPrecisionFormat_
+
+data ArrayBufferView_
+type ArrayBufferView = JSRef ArrayBufferView_
+
+noBuffer :: Buffer
+noBuffer = jsNull
+
+noTexture :: Texture
+noTexture = jsNull
+
+noArray :: IO ArrayBufferView
+noArray = return jsNull
+
+float32View :: JSArray Float -> IO ArrayBufferView
+float32View = fmap castRef . float32Array
+
+int32View :: JSArray Int32 -> IO ArrayBufferView
+int32View = fmap castRef . int32Array
+
+uint16View :: JSArray Word16 -> IO ArrayBufferView
+uint16View = fmap castRef . uint16Array
+
+uint8View :: JSArray Word8 -> IO ArrayBufferView
+uint8View = fmap castRef . uint8Array
+
+toJSArray :: ToJSRef a => (v -> Maybe (a, v)) -> v -> IO (JSArray a)
+toJSArray next iv = newArray >>= iterPush iv
+        where iterPush v arr = case next v of
+                                        Just (x, v') -> do xRef <- toJSRef x
+                                                           pushArray xRef arr
+                                                           iterPush v' arr
+                                        Nothing -> return arr
+
+listToJSArray :: ToJSRef a => [a] -> IO (JSArray a)
+listToJSArray = toJSArray deconstr
+        where deconstr (x : xs) = Just (x, xs)
+              deconstr [] = Nothing
+
+foreign import javascript unsafe "$r = new Float32Array($1);"
+        float32Array :: JSArray Float -> IO Float32Array
+
+foreign import javascript unsafe "$r = new Int32Array($1);"
+        int32Array :: JSArray Int32 -> IO Int32Array
+
+foreign import javascript unsafe "$r = new Uint16Array($1);"
+        uint16Array :: JSArray Word16 -> IO Uint16Array
+
+foreign import javascript unsafe "$r = new Uint8Array($1);"
+        uint8Array :: JSArray Word8 -> IO Uint8Array
+
+foreign import javascript unsafe "$r = $1.getContext(\"webgl\");"
+        getCtx :: JSRef a -> IO Ctx
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2014-2015, Luca Prezzavento
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Luca "ZioCrocifisso" Prezzavento nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/fwgl-javascript.cabal b/fwgl-javascript.cabal
new file mode 100644
--- /dev/null
+++ b/fwgl-javascript.cabal
@@ -0,0 +1,21 @@
+name:                fwgl-javascript
+version:             0.1.0.2
+synopsis:            FWGL GHCJS backend
+description:         FWGL GHCJS backend
+homepage:            https://github.com/ZioCrocifisso/FWGL
+stability:           experimental
+license:             BSD3
+license-file:        LICENSE
+author:              Luca "ZioCrocifisso" Prezzavento
+maintainer:          ziocroc@gmail.com
+category:            Game, Game Engine, Javascript
+build-type:          Simple
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     FWGL.Backend.JavaScript
+  other-modules:       FWGL.Backend.JavaScript.WebGL, FWGL.Backend.JavaScript.Event, FWGL.Backend.JavaScript.WebGL.Const, FWGL.Backend.JavaScript.WebGL.Types, FWGL.Backend.JavaScript.WebGL.Raw
+  other-extensions:    FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances
+  build-depends:       fwgl >= 0.1 && < 0.2, Yampa, base >=4.7 && <4.8, hashable >=1.2 && <1.3, unordered-containers >=0.2 && <0.3, ghcjs-base
+  hs-source-dirs:      .
+  default-language:    Haskell2010
