diff --git a/cmd/prototype.go b/cmd/prototype.go
index 097281ffe4ec47525300c86353219d059cab12d7..92f85e91f1425338c58e9f554c5e4b1e08e7c68f 100644
--- a/cmd/prototype.go
+++ b/cmd/prototype.go
@@ -104,8 +104,8 @@ var prototypeDescribeCmd = &cobra.Command{
 		fmt.Println(`OPTIONAL PARAMETERS:`)
 		fmt.Println(proto.OptionalParams().PrettyString("  "))
 		fmt.Println()
-		fmt.Println(`TEMPLATE:`)
-		fmt.Println(strings.Join(proto.Template.Body, "\n"))
+		fmt.Println(`TEMPLATE TYPES AVAILABLE:`)
+		fmt.Println(fmt.Sprintf("  %s", proto.Template.AvailableTemplates()))
 
 		return nil
 	},
@@ -163,7 +163,7 @@ var prototypeSearchCmd = &cobra.Command{
 }
 
 var prototypeUseCmd = &cobra.Command{
-	Use:                "use <prototype-name> [parameter-flags]",
+	Use:                "use <prototype-name> [type] [parameter-flags]",
 	Short:              `Instantiate prototype, emitting the generated code to stdout.`,
 	DisableFlagParsing: true,
 	RunE: func(cmd *cobra.Command, rawArgs []string) error {
@@ -187,9 +187,27 @@ var prototypeUseCmd = &cobra.Command{
 		}
 
 		cmd.DisableFlagParsing = false
-		cmd.ParseFlags(rawArgs)
+		err = cmd.ParseFlags(rawArgs)
+		if err != nil {
+			return err
+		}
 		flags := cmd.Flags()
 
+		// Try to find the template type (if it is supplied) after the args are
+		// parsed. Note that the case that `len(args) == 0` is handled at the
+		// beginning of this command.
+		var templateType prototype.TemplateType
+		if args := flags.Args(); len(args) == 1 {
+			templateType = prototype.Jsonnet
+		} else if len(args) == 2 {
+			templateType, err = prototype.ParseTemplateType(args[1])
+			if err != nil {
+				return err
+			}
+		} else {
+			return fmt.Errorf("Incorrect number of arguments supplied to 'prototype use'\n\n%s", cmd.UsageString())
+		}
+
 		missingReqd := prototype.ParamSchemas{}
 		values := map[string]string{}
 		for _, param := range proto.RequiredParams() {
@@ -202,7 +220,11 @@ var prototypeUseCmd = &cobra.Command{
 				return fmt.Errorf("Prototype '%s' has multiple parameters with name '%s'", proto.Name, param.Name)
 			}
 
-			values[param.Name] = val
+			quoted, err := param.Quote(val)
+			if err != nil {
+				return err
+			}
+			values[param.Name] = quoted
 		}
 
 		if len(missingReqd) > 0 {
@@ -217,10 +239,19 @@ var prototypeUseCmd = &cobra.Command{
 				return fmt.Errorf("Prototype '%s' has multiple parameters with name '%s'", proto.Name, param.Name)
 			}
 
-			values[param.Name] = val
+			quoted, err := param.Quote(val)
+			if err != nil {
+				return err
+			}
+			values[param.Name] = quoted
 		}
 
-		tm := snippet.Parse(strings.Join(proto.Template.Body, "\n"))
+		template, err := proto.Template.Body(templateType)
+		if err != nil {
+			return err
+		}
+
+		tm := snippet.Parse(strings.Join(template, "\n"))
 		text, err := tm.Evaluate(values)
 		if err != nil {
 			return err
@@ -241,16 +272,13 @@ unique enough to resolve to 'io.ksonnet.pkg.prototype.simple-deployment'.`,
   # the 'nginx' image, and port 80 exposed.
   ksonnet prototype use io.ksonnet.pkg.prototype.simple-deployment \
     --name=nginx                                                   \
-    --image=nginx                                                  \
-    --port=80                                                      \
-    --portName=http
+    --image=nginx
 
-  # Instantiate prototype using a unique suffix of an identifier. That is, this
-  # command only requires a long enough suffix to uniquely identify a ksonnet
-  # prototype. In this example, the suffix 'simple-deployment' is enough to
-  # uniquely identify 'io.ksonnet.pkg.prototype.simple-deployment', but
-  # 'deployment' might not be, as several names end with that suffix.
-  ksonnet prototype describe simple-deployment`,
+  # Instantiate prototype using a unique suffix of an identifier. See
+  # introduction of help message for more information on how this works.
+  ksonnet prototype use simple-deployment \
+    --name=nginx                          \
+    --image=nginx`,
 }
 
 func fundUniquePrototype(query string) (*prototype.SpecificationSchema, error) {
diff --git a/prototype/prototype_test.go b/prototype/prototype_test.go
index 30c5473e53ae7824fa6e293cf9766c6a4dd660ed..5f78632b17dbd693fd7aa57c8c8f358b8c7cf005 100644
--- a/prototype/prototype_test.go
+++ b/prototype/prototype_test.go
@@ -110,16 +110,16 @@ func TestSearch(t *testing.T) {
 	assertSearch(t, idx, Prefix, "service", []string{})
 	assertSearch(t, idx, Prefix, "simple", []string{})
 	assertSearch(t, idx, Prefix, "io.ksonnet", []string{
-		"io.ksonnet.pkg.yaml-single-port-service",
-		"io.ksonnet.pkg.yaml-namespace",
-		"io.ksonnet.pkg.yaml-empty-configMap",
-		"io.ksonnet.pkg.yaml-single-port-deployment",
+		"io.ksonnet.pkg.single-port-service",
+		"io.ksonnet.pkg.namespace",
+		"io.ksonnet.pkg.configMap",
+		"io.ksonnet.pkg.single-port-deployment",
 	})
 	assertSearch(t, idx, Prefix, "foo", []string{})
 
 	// Suffix searches.
 	assertSearch(t, idx, Suffix, "service", []string{
-		"io.ksonnet.pkg.yaml-single-port-service",
+		"io.ksonnet.pkg.single-port-service",
 		"io.some-vendor.pkg.simple-service",
 	})
 	assertSearch(t, idx, Suffix, "simple", []string{})
@@ -128,7 +128,7 @@ func TestSearch(t *testing.T) {
 
 	// Substring searches.
 	assertSearch(t, idx, Substring, "service", []string{
-		"io.ksonnet.pkg.yaml-single-port-service",
+		"io.ksonnet.pkg.single-port-service",
 		"io.some-vendor.pkg.simple-service",
 	})
 	assertSearch(t, idx, Substring, "simple", []string{
@@ -136,10 +136,10 @@ func TestSearch(t *testing.T) {
 		"io.some-vendor.pkg.simple-service",
 	})
 	assertSearch(t, idx, Substring, "io.ksonnet", []string{
-		"io.ksonnet.pkg.yaml-single-port-service",
-		"io.ksonnet.pkg.yaml-single-port-deployment",
-		"io.ksonnet.pkg.yaml-empty-configMap",
-		"io.ksonnet.pkg.yaml-namespace",
+		"io.ksonnet.pkg.single-port-service",
+		"io.ksonnet.pkg.single-port-deployment",
+		"io.ksonnet.pkg.configMap",
+		"io.ksonnet.pkg.namespace",
 	})
 	assertSearch(t, idx, Substring, "foo", []string{})
 }
diff --git a/prototype/specification.go b/prototype/specification.go
index d957cda66735ab3f8639006df24cd1d056cf928b..d0322d52c7820ddb498244961ba4ced56fa96bdd 100644
--- a/prototype/specification.go
+++ b/prototype/specification.go
@@ -2,6 +2,7 @@ package prototype
 
 import (
 	"fmt"
+	"strconv"
 	"strings"
 )
 
@@ -50,6 +51,34 @@ func (s *SpecificationSchema) OptionalParams() ParamSchemas {
 	return opt
 }
 
+// TemplateType represents the possible type of a prototype.
+type TemplateType string
+
+const (
+	// YAML represents a prototype written in YAML.
+	YAML TemplateType = "yaml"
+
+	// JSON represents a prototype written in JSON.
+	JSON TemplateType = "json"
+
+	// Jsonnet represents a prototype written in Jsonnet.
+	Jsonnet TemplateType = "jsonnet"
+)
+
+// ParseTemplateType attempts to parse a string as a `TemplateType`.
+func ParseTemplateType(t string) (TemplateType, error) {
+	switch strings.ToLower(t) {
+	case "yaml":
+		return YAML, nil
+	case "json":
+		return JSON, nil
+	case "jsonnet":
+		return Jsonnet, nil
+	default:
+		return "", fmt.Errorf("Unrecognized template type '%s'; must be one of: [yaml, json, jsonnet]", t)
+	}
+}
+
 // SnippetSchema is the JSON-serializable representation of the TextMate snippet
 // specification, as implemented by the Language Server Protocol.
 type SnippetSchema struct {
@@ -58,38 +87,150 @@ type SnippetSchema struct {
 	// Description describes what the prototype does.
 	Description string `json:"description"`
 
-	// Body of the prototype. Follows the TextMate snippets syntax, with several
-	// features disallowed.
-	Body []string `json:"body"`
+	// Various body types of the prototype. Follows the TextMate snippets syntax,
+	// with several features disallowed. At least one of these is required to be
+	// filled out.
+	JSONBody    []string `json:"jsonBody"`
+	YAMLBody    []string `json:"yamlBody"`
+	JsonnetBody []string `json:"jsonnetBody"`
 }
 
-// ParamSchema is the JSON-serializable representation of a parameter provided to a prototype.
+// Body attempts to retrieve the template body associated with some
+// type `t`.
+func (schema *SnippetSchema) Body(t TemplateType) (template []string, err error) {
+	switch t {
+	case YAML:
+		template = schema.YAMLBody
+	case JSON:
+		template = schema.JSONBody
+	case Jsonnet:
+		template = schema.JsonnetBody
+	default:
+		return nil, fmt.Errorf("Unrecognized template type '%s'; must be one of: [yaml, json, jsonnet]", t)
+	}
+
+	if len(template) == 0 {
+		available := schema.AvailableTemplates()
+		err = fmt.Errorf("Template does not have a template for type '%s'. Available types: %s", t, available)
+	}
+
+	return
+}
+
+// AvailableTemplates returns the list of available `TemplateType`s this
+// prototype implements.
+func (schema *SnippetSchema) AvailableTemplates() (ts []TemplateType) {
+	if len(schema.YAMLBody) != 0 {
+		ts = append(ts, YAML)
+	}
+
+	if len(schema.JSONBody) != 0 {
+		ts = append(ts, JSON)
+	}
+
+	if len(schema.JsonnetBody) != 0 {
+		ts = append(ts, Jsonnet)
+	}
+
+	return
+}
+
+// ParamType represents a type constraint for a prototype parameter (e.g., it
+// must be a number).
+type ParamType string
+
+const (
+	// Number represents a prototype parameter that must be a number.
+	Number ParamType = "number"
+
+	// String represents a prototype parameter that must be a string.
+	String ParamType = "string"
+
+	// NumberOrString represents a prototype parameter that must be either a
+	// number or a string.
+	NumberOrString ParamType = "numberOrString"
+
+	// Object represents a prototype parameter that must be an object.
+	Object ParamType = "object"
+
+	// Array represents a prototype parameter that must be a array.
+	Array ParamType = "array"
+)
+
+func (pt ParamType) String() string {
+	switch pt {
+	case Number:
+		return "number"
+	case String:
+		return "string"
+	case NumberOrString:
+		return "number-or-string"
+	case Object:
+		return "object"
+	case Array:
+		return "array"
+	default:
+		return "unknown"
+	}
+}
+
+// ParamSchema is the JSON-serializable representation of a parameter provided
+// to a prototype.
 type ParamSchema struct {
-	Name        string  `json:"name"`
-	Alias       *string `json:"alias"` // Optional.
-	Description string  `json:"description"`
-	Default     *string `json:"default"` // `nil` only if the parameter is optional.
+	Name        string    `json:"name"`
+	Alias       *string   `json:"alias"` // Optional.
+	Description string    `json:"description"`
+	Default     *string   `json:"default"` // `nil` only if the parameter is optional.
+	Type        ParamType `json:"type"`
+}
+
+// Quote will parse a prototype parameter and quote it appropriately, so that it
+// shows up correctly in Jsonnet source code. For example, `--image nginx` would
+// likely need to show up as `"nginx"` in Jsonnet source.
+func (ps *ParamSchema) Quote(value string) (string, error) {
+	switch ps.Type {
+	case Number:
+		_, err := strconv.ParseFloat(value, 64)
+		if err != nil {
+			return "", fmt.Errorf("Could not convert parameter '%s' to a number", ps.Name)
+		}
+		return value, nil
+	case String:
+		return fmt.Sprintf("\"%s\"", value), nil
+	case NumberOrString:
+		_, err := strconv.ParseFloat(value, 64)
+		if err == nil {
+			return value, nil
+		}
+		return fmt.Sprintf("\"%s\"", value), nil
+	case Array, Object:
+		return value, nil
+	default:
+		return "", fmt.Errorf("Unknown param type for param '%s'", ps.Name)
+	}
 }
 
 // RequiredParam constructs a required parameter, i.e., a parameter that is
 // meant to be required by some prototype, somewhere.
-func RequiredParam(name, alias, description string) *ParamSchema {
+func RequiredParam(name, alias, description string, t ParamType) *ParamSchema {
 	return &ParamSchema{
 		Name:        name,
 		Alias:       &alias,
 		Description: description,
 		Default:     nil,
+		Type:        t,
 	}
 }
 
 // OptionalParam constructs an optional parameter, i.e., a parameter that is
 // meant to be optionally provided to some prototype, somewhere.
-func OptionalParam(name, alias, description, defaultVal string) *ParamSchema {
+func OptionalParam(name, alias, description, defaultVal string, t ParamType) *ParamSchema {
 	return &ParamSchema{
 		Name:        name,
 		Alias:       &alias,
 		Description: description,
 		Default:     &defaultVal,
+		Type:        t,
 	}
 }
 
@@ -124,15 +265,17 @@ func (ps ParamSchemas) PrettyString(prefix string) string {
 		p := ps[i]
 		flag := flags[i]
 
-		defaultVal := ""
+		var info string
 		if p.Default != nil {
-			defaultVal = fmt.Sprintf(" [default: %s]", *p.Default)
+			info = fmt.Sprintf(" [default: %s, type: %s]", *p.Default, p.Type.String())
+		} else {
+			info = fmt.Sprintf(" [type: %s]", p.Type.String())
 		}
 
 		// NOTE: If we don't add 1 here, the longest line will look like:
 		// `--flag=<flag>Description is here.`
 		space := strings.Repeat(" ", max-len(flag)+1)
-		pretty := fmt.Sprintf(prefix + flag + space + p.Description + defaultVal)
+		pretty := fmt.Sprintf(prefix + flag + space + p.Description + info)
 		prettyFlags = append(prettyFlags, pretty)
 	}
 
diff --git a/prototype/systemPrototypes.go b/prototype/systemPrototypes.go
index 679a43fb4b1014b248aa511108d5a86ccebe559f..192c575ea239de95cd29a1c6f04e1529876ae031 100644
--- a/prototype/systemPrototypes.go
+++ b/prototype/systemPrototypes.go
@@ -3,14 +3,14 @@ package prototype
 var defaultPrototypes = []*SpecificationSchema{
 	&SpecificationSchema{
 		APIVersion: "0.1",
-		Name:       "io.ksonnet.pkg.yaml-namespace",
+		Name:       "io.ksonnet.pkg.namespace",
 		Params: ParamSchemas{
-			RequiredParam("name", "name", "Name to give the namespace."),
+			RequiredParam("name", "name", "Name to give the namespace.", String),
 		},
 		Template: SnippetSchema{
 			Description: `A simple namespace. Labels are automatically populated from the name of the
 namespace.`,
-			Body: []string{
+			YAMLBody: []string{
 				"kind: Namespace",
 				"apiVersion: v1",
 				"metadata:",
@@ -18,22 +18,42 @@ namespace.`,
 				"  labels:",
 				"    name: ${name}",
 			},
+			JSONBody: []string{
+				`{`,
+				`  "kind": "Namespace",`,
+				`  "apiVersion": "v1",`,
+				`  "metadata": {`,
+				`    "name": ${name},`,
+				`    "labels": {`,
+				`      "name": ${name}`,
+				`    }`,
+				`  }`,
+				`}`,
+			},
+			JsonnetBody: []string{
+				`local k = import "k.libsonnet";`,
+				`local ns = k.core.v1.namespace;`,
+				``,
+				`ns.new() +`,
+				`ns.mixin.metadata.name(${name}) +`,
+				`ns.mixin.metadata.labels({name: ${name}})`,
+			},
 		},
 	},
 	&SpecificationSchema{
 		APIVersion: "0.1",
-		Name:       "io.ksonnet.pkg.yaml-single-port-service",
+		Name:       "io.ksonnet.pkg.single-port-service",
 		Params: ParamSchemas{
-			RequiredParam("name", "serviceName", "Name of the service"),
-			RequiredParam("targetLabelSelector", "selector", "Label for the service to target (e.g., 'app: MyApp')."),
-			RequiredParam("servicePort", "port", "Port for the service to expose."),
-			RequiredParam("targetPort", "port", "Port for the service target."),
-			OptionalParam("protocol", "protocol", "Protocol to use (either TCP or UDP).", "TCP"),
+			RequiredParam("name", "serviceName", "Name of the service", String),
+			RequiredParam("targetLabelSelector", "selector", "Label for the service to target (e.g., 'app: MyApp').", Object),
+			RequiredParam("servicePort", "port", "Port for the service to expose.", NumberOrString),
+			RequiredParam("targetPort", "port", "Port for the service target.", NumberOrString),
+			OptionalParam("protocol", "protocol", "Protocol to use (either TCP or UDP).", "TCP", String),
 		},
 		Template: SnippetSchema{
 			Description: `A service that exposes 'servicePort', and directs traffic
 to 'targetLabelSelector', at 'targetPort'.`,
-			Body: []string{
+			YAMLBody: []string{
 				"kind: Service",
 				"apiVersion: v1",
 				"metadata:",
@@ -46,40 +66,89 @@ to 'targetLabelSelector', at 'targetPort'.`,
 				"    port: ${servicePort}",
 				"    targetPort: ${targetPort}",
 			},
+			JSONBody: []string{
+				`{`,
+				`  "kind": "Service",`,
+				`  "apiVersion": "v1",`,
+				`  "metadata": {`,
+				`    "name": ${name}`,
+				`  },`,
+				`  "spec": {`,
+				`    "selector": {`,
+				`      ${targetLabelSelector}`,
+				`    },`,
+				`    "ports": [`,
+				`      {`,
+				`        "protocol": ${protocol},`,
+				`        "port": ${servicePort},`,
+				`        "targetPort": ${targetPort}`,
+				`      }`,
+				`    ]`,
+				`  }`,
+				`}`,
+			},
+			JsonnetBody: []string{
+				`local k = import "k.libsonnet";`,
+				`local service = k.core.v1.service;`,
+				`local port = k.core.v1.service.mixin.spec.portsType;`,
+				``,
+				`service.new(`,
+				`  ${name},`,
+				`  ${targetLabelSelector},`,
+				`  port.new(${servicePort}, ${targetPort}))`,
+			},
 		},
 	},
 	&SpecificationSchema{
 		APIVersion: "0.1",
-		Name:       "io.ksonnet.pkg.yaml-empty-configMap",
+		Name:       "io.ksonnet.pkg.empty-configMap",
 		Params: ParamSchemas{
-			RequiredParam("serviceName", "name", "Name to give the configMap."),
+			RequiredParam("name", "name", "Name to give the configMap.", String),
+			OptionalParam("data", "data", "Data for the configMap.", "{}", Object),
 		},
 		Template: SnippetSchema{
 			Description: `A simple config map. Contains no data.`,
-			Body: []string{
+			YAMLBody: []string{
 				"apiVersion: v1",
 				"kind: ConfigMap",
 				"metadata:",
 				"  name: ${name}",
-				"data:",
-				"  // K/V pairs go here.",
+				"data: ${data}",
+			},
+			JSONBody: []string{
+				`{`,
+				`  "apiVersion": "v1",`,
+				`  "kind": "ConfigMap",`,
+				`  "metadata": {`,
+				`    "name": ${name}`,
+				`  },`,
+				`  "data": ${data}`,
+				`}`,
+			},
+			JsonnetBody: []string{
+				`local k = import "k.libsonnet";`,
+				`local configMap = k.core.v1.configMap;`,
+				``,
+				`configMap.new() +`,
+				`configMap.mixin.metadata.name("${name}") +`,
+				`configMap.data("${data}")`,
 			},
 		},
 	},
 	&SpecificationSchema{
 		APIVersion: "0.1",
-		Name:       "io.ksonnet.pkg.yaml-single-port-deployment",
+		Name:       "io.ksonnet.pkg.single-port-deployment",
 		Params: ParamSchemas{
-			RequiredParam("name", "deploymentName", "Name of the deployment"),
-			RequiredParam("image", "containerImage", "Container image to deploy"),
-			OptionalParam("replicas", "replicas", "Number of replicas", "1"),
-			OptionalParam("port", "containerPort", "Port to expose", "80"),
+			RequiredParam("name", "deploymentName", "Name of the deployment", String),
+			RequiredParam("image", "containerImage", "Container image to deploy", String),
+			OptionalParam("replicas", "replicas", "Number of replicas", "1", Number),
+			OptionalParam("port", "containerPort", "Port to expose", "80", NumberOrString),
 		},
 		Template: SnippetSchema{
 			Description: `A deployment that replicates container 'image' some number of times
 (default: 1), and exposes a port (default: 80). Labels are automatically
 populated from 'name'.`,
-			Body: []string{
+			YAMLBody: []string{
 				"apiVersion: apps/v1beta1",
 				"kind: Deployment",
 				"metadata:",
@@ -95,7 +164,52 @@ populated from 'name'.`,
 				"      - name: ${name}",
 				"        image: ${image}",
 				"        ports:",
-				"        - containerPort: ${containerPort:80}",
+				"        - containerPort: ${port:80}",
+			},
+			JSONBody: []string{
+				`{`,
+				`  "apiVersion": "apps/v1beta1",`,
+				`  "kind": "Deployment",`,
+				`  "metadata": {`,
+				`    "name": ${name}`,
+				`  },`,
+				`  "spec": {`,
+				`    "replicas": ${replicas:1},`,
+				`    "template": {`,
+				`      "metadata": {`,
+				`        "labels": {`,
+				`          "app": ${name}`,
+				`        }`,
+				`      },`,
+				`      "spec": {`,
+				`        "containers": [`,
+				`          {`,
+				`            "name": ${name},`,
+				`            "image": ${image},`,
+				`            "ports": [`,
+				`              {`,
+				`                "containerPort": ${port:80}`,
+				`              }`,
+				`            ]`,
+				`          }`,
+				`        ]`,
+				`      }`,
+				`    }`,
+				`  }`,
+				`}`,
+			},
+			JsonnetBody: []string{
+				`local k = import "k.libsonnet";`,
+				`local deployment = k.apps.v1beta1.deployment;`,
+				`local container = k.apps.v1beta1.deployment.mixin.spec.template.spec.containersType;`,
+				`local port = container.portsType;`,
+				``,
+				`deployment.new(`,
+				`  ${name},`,
+				`  ${replicas},`,
+				`  container.new(${name}, ${image}) +`,
+				`    container.ports(port.new(${port:80})),`,
+				`  {app: ${name}})`,
 			},
 		},
 	},