Directives

Directives are pre-execution instructions that Salata resolves before any runtime blocks execute. They control HTTP response metadata, file inclusion, and routing behavior.

Key rule: Directives appear outside runtime blocks only. Placing a directive inside a <python>, <ruby>, or any other runtime block is invalid. For data sharing between runtime blocks, use macros instead.

#include

C-style text substitution. The referenced file's contents are pasted in place of the directive.

Syntax:

#include "path/to/file.slt"

Rules:

  • Included files can contain runtime blocks, directives, and static text
  • Included runtime blocks participate in shared scope (variables are visible)
  • Maximum include depth: 16 levels (deeper recursion produces an error)
  • Paths are relative to the file containing the #include

Example:

#include "includes/header.slt"

<h1>Page Content</h1>

<python>
  print("<p>Dynamic content here.</p>")
</python>

#include "includes/footer.slt"

See Includes for detailed usage patterns.

#status

Sets the HTTP response status code.

Syntax:

#status CODE

Rules:

  • Only once per page (multiple #status directives produce a parse error)
  • Default: 200
  • Any runtime failure automatically overrides this to 500
  • No runtime block can set the status code -- only this directive can

Examples:

#status 404

<h1>Page Not Found</h1>
<p>The requested page does not exist.</p>
#status 201

<python>
  import json
  print(json.dumps({"created": True}))
</python>

#content-type

Sets the response MIME type.

Syntax:

#content-type MIME_TYPE

Rules:

  • Only once per page (multiple produces a parse error)
  • Default: text/html; charset=utf-8

Examples:

#content-type application/json

<python>
  import json
  data = {"users": [{"name": "Alice"}, {"name": "Bob"}]}
  print(json.dumps(data, indent=2))
</python>
#content-type text/plain

This is a plain text response.
<shell>echo "Generated at: $(date)"</shell>
#content-type text/csv

<ruby>
  puts "name,email,age"
  puts "Alice,alice@example.com,30"
  puts "Bob,bob@example.com,25"
</ruby>

Adds a custom HTTP response header.

Syntax:

#header "Header-Name" "value"

Rules:

  • Can appear multiple times (each adds a header)
  • Both the header name and value must be quoted

Examples:

#header "X-Powered-By" "Salata"
#header "Cache-Control" "no-cache, no-store, must-revalidate"
#header "X-Request-Id" "abc-123"

<h1>Hello</h1>

Sets a response cookie.

Syntax:

#cookie "name" "value" [flags...]

Rules:

  • Can appear multiple times (each sets a different cookie)
  • The cookie name and value must be quoted
  • Optional flags follow the value, space-separated: httponly, secure, samesite=Strict, samesite=Lax, samesite=None, path=/..., max-age=SECONDS, domain=...

Examples:

#cookie "session" "abc123" httponly secure

<h1>Welcome back</h1>
#cookie "theme" "dark" path=/ max-age=31536000
#cookie "lang" "en" path=/ samesite=Lax

<python>
  print("<p>Preferences saved.</p>")
</python>

#redirect

Issues an HTTP redirect response.

Syntax:

#redirect "destination"

Examples:

#redirect "/login"
#redirect "/dashboard"

When a #redirect directive is present, the response body is typically empty since the client will follow the redirect.

Summary

DirectiveRepeatableWherePurpose
#includeYesOutside blocksPaste file contents in place
#statusNoOutside blocksSet HTTP status code
#content-typeNoOutside blocksSet response MIME type
#headerYesOutside blocksAdd custom response header
#cookieYesOutside blocksSet response cookie
#redirectNoOutside blocksIssue HTTP redirect