Dig-in! (learn…)

This manual is a pre-release preview. Please follow Moonstalk on Twitter or Facebook to be notified of a public release.

Create

This section provides an an overview for the use of Moonstalk, and the basics of adapting it to common needs. See the develop page for detailed attributes, behaviours and functionality.

Lua

If you've not learned the basics of the Lua language yet, now might be a good time. Programming In Lua is an easy to understand and straight-to-the-point guide that'll introduce you to the essentials in just a couple of hours. If you know other languages you may well be able soldier on and extrapolate much of its syntax.

Bundles

Moonstalk hosts both sites and applications, and we refer to both generically as ‘bundles’. Each are defined by folders containing much the same set of files for their resources.

Creating a bundle is as simple as creating a folder, and putting some files in it. The following are files common to bundles (both sites and applications). All are optional and may define functionality indepedantly of each other, or in combination.

Any file not otherwise noted and having an extension, is considered to be static content and will be served directly by the web server. See the design page, and bundles reference section for specific details.

You may create subfolders and organise your files as you wish, so long as top-level sub-folders do not correspond to the name of another application as this provides an override facility.

Sites

Site bundles are created inside the Moonstalk sites folder, and each bundle (folder) defines an individual site, named with its primary domain.

The primary domain my be specified with or without the www prefix, but both are always handled, therefore ensure your DNS is setup with records for both.

See the Tenants application for details of how sites can be stored in a database (e.g. for SaaS).

Features

Files

Applications

Application bundles are created inside the Moonstalk applications folder, and each bundle defines an individual application, named with its ID.

Applications provide shared or generic functionality (such as a blog system) for use on multiple sites (disparate domains). Applications must typically be enabled in a site's settings in order to use them, refer to an application's own documentation for details of its behaviour, configuration, and usage. Moonstalk includes a number of bundled applications.

Features

Files

The generic server not-found and error pages are provided by the Generic application, see its documentation to customise them.

Applications are for installation by a server operator only, and should be audited for security.

Static resources

Moonstalk configures the webserver to serve any file accessed with a filename extension on a site's primary domain, straight from disk (or RAM if cached) and without processing by Moonstalk's Scribe backend.

If your visitors primarily come from more than a single country (or state) the use of a Content Delivery Network (CDN) is highly recommend for improved performance in preference to hosting your assets from your server itself.

Assets

These are files such as images, CSS, and Javascript that are referenced in and enhance HTML pages, and also PDFs, video and other downloadable files.

Typically you would group all your assets together inside an assets subfolder of your site. When you link to them in HTML you simply use the relative src or href "assets/myfile.type" and the assets will work both on and offline.

Pages

Moonstalk's primary purpose is serving content that is at least partly dynamic, however you may serve static pages (i.e. complete HTML files) in the same manner as other static assets.

Dynamic resources

Any requests for an address not containing a filename extension is considered a dynamic request, to be processed by Moonstalk's Scribe backend, which runs a sequence of functions to handle the request and provide a response.

Moonstalk provides built-in handling for dynamic pages, generated from a view file providing the primary layout and content (HTML markup), and optionally supplemented with a controller providing separate processing logic (Lua code).

Both views and controllers run as handler functions with access to the same Lua environment and Moonstalk functions—the difference lies only in the file format (tags in views, code in controllers). See the develop page for details of the environment available.

See the Content application for details of how static pages can be stored in a database.

Views

These are simply .html files, either complete HTML pages or fragments of formatted content for display, such as within a template. Views may utilise the following two forms of dynamic markup.

Expression tags

?( expression )

The expression tag is a macro for the write() function and is replaced in the page by the resulting value of a Lua expression.

An expression may be a variable name, function call (but not if it returns more than a single parameter), concatenation operation, or a combination of these (grouped inside brackets). Code blocks such as if and while are not handled. Expression tags may be used anywhere in your HTML file (including inside attributes).

Processing tags

<? code ?>

These may contain any valid Lua code including blocks, and are stripped out of the page, except for the result of any calls to the write() function which may be used to append output to the page. Code may be split across multiple tags such as to define conditional output.

<? if mytest then ?>
	<b>mytest is true</b>
<? end ?>

Controllers

These are predominantly used to separate and protect the logic (Lua code) from the layout in a view, thus avoiding placing complex server processing tags within a view's markup.

When paired with a view, a controller's code is placed in a .lua file of the same name. I.e. myfile.html is the view and myfile.lua is the controller. Controllers run before views and are used to process and prepare variables (such as from the request, or a database) for insertion as strings into a page, using expression or processing tags in the corresponding view.

Controllers may provide output before a view runs, using write[[<p>content</p>]] (typically using a Lua 'long-string' to avoid issues with escaping), and may thus also be used in place of a view entirely, particularly where a non-HTML response is required (e.g. a JSON or XML API).

Templates

With templates you can define the common layout or features of all pages, or groups of pages, such as providing a navigation menu, header, footer and so forth. A template wraps the content or layout (e.g. from a view) with its additional markup.

Templates are identical to dynamic pages, having both a view and an optional controller, but are run after the page controller and view. Templates may thus have both layout and logic.

In a template you must specify where to merge the page content generated by the page controller and view, using the following command.

<? merge "content" ?>

Templates may be defined in the following manner, the latter methods take precedence over any prior.

Sections

By default all output is placed into a section container named content, from which the page response is generated. You may define your own output sections, to capture output to merge into the page later in an arbitrary order. Use the following command to define a section.

<? section "name" ?>

All output following this will be captured, until another section is defined (or the page is generated). Templates use this same mechanism.

Once output is collected you must concatenate any custom sections into the page content. To combine your sections with the page, use the merge command with the name of your previously defined section.

<? merge "name" ?>

Chaining

You may include or run any view or controller in any other, by using the following commands, however bear in mind that the output response will be affected by the order that they run unless you use sections.

All application view and controller names are prefixed with the application name, e.g. appname/viewname. The current site's is accessed with just its name.

Chaining behaviour is akin to forwarding in J2EE, and should not be confused with HTTP redirection.

Redirection

To cause the user's browser to send a new request for a specified address use the following command, this will not abandon the current request and will occur only when it is complete. This is often used after successfully processing a submitted form to change the URL to a bookmarkable action ID, instead of simply displaying a different view at an unchanged address. The given address may be a path or an absolute URL.

scribe.Redirect "address"

Routing

To provide a response, a request's URL path must be mapped to a function (typically a controller) or content (typically a view). Moonstalk provides built-in mapping through its addressing mechanism, and ad-hoc routing through the chaining mechanism.

By default views in site bundles (but not applications) are automatically mapped to an address corresponding to their file names (without extension). E.g. the file sites/example.com/mypage.html would be accessed as http://example.com/mypage.

You may define your own mappings, by declaring an addresses array in a bundle's settings file. Each address in the array takes the following form, specifying one selector, one or more handlers, with optional attributes inherited by the page. (See addresses on the develop page for full usage.)

{selector="path", handler="name", attribute=value}

Authentication

Moonstalk has built-in generic handling for user access control. You may employ this either on addresses, or within your own functions (see develop). Addresses and pages may be defined as having restricted access using locks, and users may be granted access to such locked pages using keys. Locks and keys are simply names that denote membership of certain user 'groups' as desired.

An additional application is required to define behaviours for user and key management (i.e. assignment, retraction). Moonstalk includes the people application for managing users within the Teller database.

To restrict a view to a particular key holder, add a locks attribute to the page, or to desired addresses in the settings.

{ matches="private/page", view="private-page", locks={ "Private", } }

A user requiring access to that address must then be granted a key with the corresponding name in their keychain.

By default all signed-in users have a default "Guest" key, you may therefore require sign-in on pages by adding a lock of the same name.

Internationalisation

Moonstalk includes built-in support for language translations (vocabularies), easily retrieved via a simple key-prefix, and built-in but optional support for locales via formatter functions. Additional behaviours facilitate ‘i18n’ development and improve the user experience for localised projects.

When serving localised and translated pages, a user's preferred or profile-derived locale and language is used wherever possible, followed by the site's specified default locale and language, with fallbacks to the first or only language defined (such as if translation is incomplete or only has a single language defined).

If enabled GeoIP lookups are performed on a cached dataset to supplement an unprofiled user's locale.

Address paths are normalised using case-insensitivity and transliteration of latin accented characters to ASCII. Pages may be addressed with or without such characters, whilst the original (i.e. with accents if your file or page names contain them) is preserved as the canonical name.

You may use any desired encoding for your HTML and strings in Lua (but UTF-8 is recommended as this used by all Moonstalk's applications), simply be sure to use the same encoding throughout, and ensure that the correct encoding is declared in your HTML.

Lua does not handle Unicode sorting, and you may need to use your own or third-party routines for this if needed.

Non-ASCII (e.g. UTF-8) encoded files must be saved without a BOM, otherwise they will fail to load. See the utilities section for some editors that won't muck this up, if yours does.

Locales

These define the formatting of numbers, currency, dates and so forth, with their country-specific variations. Moonstalk will always attempt to locate and honour a user's locale and language (see vocabularies below), but if not available, the site default or the US locale is used.

Values are displayed respecting a locale if you output them using Moonstalk's format functions.

Default locales are included with Moonstalk, however additions or corrections should be submitted to us, or you may override them in the global environment from a settings file.

Vocabularies

These enable localisation, and store the translated text values (strings) for each translated language. If you don't expect to need to use localised content you may ignore this functionality and it will not affect the display of pages.

Applications, sites and pages may specify their own individual vocabularies (translations) that supplement each other.

Pages are displayed using the language matching a user's locale or request when available, otherwise it will be substituted with a regionally acceptable language, the site or application default, or finally English, when these are available in the vocabularies.

Partial translations are undesirable, as missing translation are replaced with alternate translations according to the user's locale, which results in pages being displayed in a mix of languages, therefore it is important to ensure all applications, sites, and pages support the desired languages.

In developer mode missing translations are not substituted with alternates, but are instead displayed as ¶name to assist in identifying missing translations.

Individual translated words or phrases are represented by keys (untranslated names) for which one is defined for each language (using its language code as defined in globals/Attributes.lua) in the bundle settings file.

vocabulary = { en={}, fr={} }
vocabulary.en.aword = "a word"
vocabulary.fr.aword = "un mot"

In settings files vocabulary is typically abbreviated as v to simplify typing, by defining local v = vocabulary.

Vocabulary item names (keys) should be globally unique (amongst all applications) else will be replaced. A page vocabularly may be used to supplement or customise these definitions.

You may replace a key in any application scope from anywhere, however you may only replace a key for the site in a page, and you cannot replace a key defined in a page as it is the final scope.

Translated words from the active vocabulary (the current user's language) are accessed using a variable named correspondingly but prefixed l. (for the original word) or L. (reformats the word with an initial cap).

In views the translated value's variable may be used in a placeholder as with any other variable.

Plural forms for translated words are also supported, these are defined in the same manner as words above, but using the number of plural forms corresponding to the language using the Mozilla rules e.g. 2 forms for Germanic languages (defined as an array of two strings), or 1 form for Asian languages (defined as a single string not an array).

en.items = {"item","items"}

Once defined you can access the translated plural by calling the localised vocabulary function with the identifier and a number that specifies the correct plural form to be used.

l("items", number)

Manage

Each individual server (virtual or dedicated) on which Moonstalk runs is called a node, and comprises the components inside the install folder. No other location is used for configuration or temporary files, withstanding the startup script.

Runner

This shell utility is your interface for managing a Moonstalk node. Run without any command it will provide you with its status. It will always report any application or site compilation (syntax) errors. All instructions are optional, accepted in any order and with several synonyms. For further usage instructions issue the help command.

The server control commands are:

These control commands may be accompanied by a server name:

To ./runner start web you must use super-user priveleges (sudo or login as root).

Configuration

The node configuration is stored in the data/configuration/Node.lua file and contains node-specific options for both Moonstalk and other applications. You may edit this directly, or for node attributes, you may use the runner to change it.

For production (non-development) servers, set a unique node ID that is between 101 and 999.

For development computers, you can enable development mode.

You may also need to set a FQDN if the default hostname is not adequate.

See the develop page for additional configuration options.

Manager

Moonstalk includes a web administration application called the Manager. This is enabled on the localhost site, which is also accessible on the server's default hostname. The Manager's user database is created with a default operator user, having a unique password that is the secret from the node configuration. The runner will notify you of these upon first use.

Updating

Moonstalk can be updated to the current release version with a single command on a non-development server (id~=100).

Your sites, applications and data will be untouched by this command, but be aware that updates to applications may require adjustments to your code or settings, therefore it is advisable to check the release notes before updating.

Repositories

You may create your own repositories using your preferred CVS for each of your application and site folders, or one for the entire sites folder—but not the entire applications folder, unless you are not using Mercurial and exclude moonstalk.* from being tracked.

If you use Mercurial for your site and application repositories, Moonstalk's update command can also pull from them for you. Simply push your changes before attempting an update, and add your repository folder names to the node configuration.

Forking

As the moonstalk directory is a version-managed Mercurial repository, if you change any of Moonstalk's managed files, the changes will be lost when Moonstalk is updated.

You may however fork/clone Moonstalk's repository, and change Moonstalk's default respoitory in .hg/hgrc to your own forked repository. Once an initial installation pull has been made from your respository on each of your deployment servers, the Moonstalk update command may be used to pull from your repoisitory thereafter.

Develop…

Now that you've got a hang of the fundamentals, read the develop page to learn about data tables, configuration, functions and more that will enable you to develop your own solutions as desired.

Addendum

Questions

Useful libraries