<commit_before>What Are Snaplets?
==================

A snaplet is a composable web application.  Snaplets allow you to build
self-contained pieces of functionality and glue them together to make larger
applications.  Here are some of the things provided by the snaplet API:

  - Infrastructure for application state/environment

  - Snaplet initialization, reload, and cleanup

  - Management of filesystem data and automatic snaplet installation

  - Unified config file infrastructure

One example might be a wiki snaplet.  It would be distributed as a haskell
package that would be installed with cabal and would probably include code,
config files, HTML templates, stylesheets, JavaScript, images, etc.  The
snaplet's code would provide the necessary API to let your application
interact seamlessly with the wiki functionality.  When you run your
application for the first time, all of the wiki snaplet's filesystem resources
will automatically be copied into the appropriate places.  Then you will
immediately be able to customize the wiki to fit your needs by editing config
files, providing your own stylesheets, etc.  We will discuss this in more
detail later.

A snaplet can represent anything from backend Haskell infrastructure with no
user facing functionality to a small widget like a chat box that goes in the
corner of a web page to an entire standalone website like a blog or forum.
The possibilities are endless.  A snaplet is a web application, and web
applications are snaplets.  This means that using snaplets and writing
snaplets are almost the same thing, and it's trivial to drop a whole website
into another one.

We're really excited about the possibilities available with snaplets.  In
fact, Snap already ships with snaplets for sessions, authentication, and
templating (with Heist),  This gives you useful functionality out of the box,
and jump starts your own snaplet development by demonstrating some useful
design patterns.  So without further ado, let's get started.

Snaplet Overview
================

The heart of the snaplets infrastructure is state management.  Most nontrivial
pieces of a web app need some kind of state or environment data.  Components
that do not need any kind of state or environment are probably more
appropriate as a standalone library than as a snaplet.

Before we continue, we must clarify an important point.  The Snap web server
processes each request in its own green thread.  This means that each request
will receive a separate copy of the state defined by your application and
snaplets, and modifications to that state only affect the local thread that
generates a single response.  From now on, when we talk about state this is
what we are talking about.  If you need global application state, you have to
use a thread-safe construct such as an MVar or IORef.

This post is written in literate Haskell.  It uses a small external module
called Part2 that is [available
here](https://github.com/snapframework/snap/blob/master/project_template/tutorial/src/Part2.lhs).
You can alsa install the full code in the current directory with the command
`snap init tutorial`.  First we need to get imports out of the way.

> {-# LANGUAGE TemplateHaskell #-}
> {-# LANGUAGE OverloadedStrings #-}
> 
> module Main where
> 
> import           Data.IORef
> import qualified Data.ByteString.Char8 as B
> import           Data.Maybe
> import           Snap
> import           Snap.Snaplet.Heist
> import           Part2

We start our application by defining a data structure to hold the state.  This
data structure includes the state of all snaplets (wrapped in a Snaplet) used
by our application as well as any other state we might want.

> data App = App
>     { _heist       :: Snaplet (Heist App)
>     , _foo         :: Snaplet Foo
>     , _bar         :: Snaplet Bar
>     , _companyName :: IORef B.ByteString
>     }
><commit_msg>Opps, fix typo.<commit_after>What Are Snaplets?
==================

A snaplet is a composable web application.  Snaplets allow you to build
self-contained pieces of functionality and glue them together to make larger
applications.  Here are some of the things provided by the snaplet API:

  - Infrastructure for application state/environment

  - Snaplet initialization, reload, and cleanup

  - Management of filesystem data and automatic snaplet installation

  - Unified config file infrastructure

One example might be a wiki snaplet.  It would be distributed as a haskell
package that would be installed with cabal and would probably include code,
config files, HTML templates, stylesheets, JavaScript, images, etc.  The
snaplet's code would provide the necessary API to let your application
interact seamlessly with the wiki functionality.  When you run your
application for the first time, all of the wiki snaplet's filesystem resources
will automatically be copied into the appropriate places.  Then you will
immediately be able to customize the wiki to fit your needs by editing config
files, providing your own stylesheets, etc.  We will discuss this in more
detail later.

A snaplet can represent anything from backend Haskell infrastructure with no
user facing functionality to a small widget like a chat box that goes in the
corner of a web page to an entire standalone website like a blog or forum.
The possibilities are endless.  A snaplet is a web application, and web
applications are snaplets.  This means that using snaplets and writing
snaplets are almost the same thing, and it's trivial to drop a whole website
into another one.

We're really excited about the possibilities available with snaplets.  In
fact, Snap already ships with snaplets for sessions, authentication, and
templating (with Heist),  This gives you useful functionality out of the box,
and jump starts your own snaplet development by demonstrating some useful
design patterns.  So without further ado, let's get started.

Snaplet Overview
================

The heart of the snaplets infrastructure is state management.  Most nontrivial
pieces of a web app need some kind of state or environment data.  Components
that do not need any kind of state or environment are probably more
appropriate as a standalone library than as a snaplet.

Before we continue, we must clarify an important point.  The Snap web server
processes each request in its own green thread.  This means that each request
will receive a separate copy of the state defined by your application and
snaplets, and modifications to that state only affect the local thread that
generates a single response.  From now on, when we talk about state this is
what we are talking about.  If you need global application state, you have to
use a thread-safe construct such as an MVar or IORef.

This post is written in literate Haskell.  It uses a small external module
called Part2 that is [available
here](https://github.com/snapframework/snap/blob/master/project_template/tutorial/src/Part2.lhs).
You can also install the full code in the current directory with the command
`snap init tutorial`.  First we need to get imports out of the way.

> {-# LANGUAGE TemplateHaskell #-}
> {-# LANGUAGE OverloadedStrings #-}
> 
> module Main where
> 
> import           Data.IORef
> import qualified Data.ByteString.Char8 as B
> import           Data.Maybe
> import           Snap
> import           Snap.Snaplet.Heist
> import           Part2

We start our application by defining a data structure to hold the state.  This
data structure includes the state of all snaplets (wrapped in a Snaplet) used
by our application as well as any other state we might want.

> data App = App
>     { _heist       :: Snaplet (Heist App)
>     , _foo         :: Snaplet Foo
>     , _bar         :: Snaplet Bar
>     , _companyName :: IORef B.ByteString
>     }
>
{'fraction_non_alphanumeric': 0.04628439187451787, 'fraction_numerical': 0.0010285420416559527, 'mean_word_length': 3.892452830188679, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 39, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3631708', 'n_tokens_mistral': 1969, 'n_tokens_neox': 1861, 'n_words': 1120}