Nomnom Pumpernickle Muffins


    0.14.6 • Public • Published



    Pre-render your Single-Page Application.



    • Prerender the Single-Page Application.
    • Automatically collect sitemaps from <meta>s.
    • Generate robots.txt with sitemap directives.
    • Sync prerendering.
    • Async prerendering with callback URL.
    • URL rewriting.
    • Works as a proxy server.
    • Rich APIs.
    • Caching.


    SPA compatibility adjustments

    In order to make the pre-rendered SPA works correctly in the client-side browser, you need to do some works:

    • When pre-rendering, intercept the anonymous AJAX requests and store the responses into <script> tag, so AJAX requests would not send again on the client-side. Our AJAX library teleman and teleman-ssr-cache may help you.
    • On the client-side, mount the SPA and replace the pre-rendered content.
    • Set <meta> tags, so search engine can know more about the page. You can use set-meta.


    npm i -g kasha


    docker pull kasha/kasha


    See config.sample.js


    Start the server:

    kasha server --config=/path/to/config.js


    docker run -v /path/to/config.js:/dest/to/config.js kasha/kasha server --config=/dest/to/config.js

    Start the worker:

    kasha worker --config=/path/to/config.js
    # async worker 
    # requests with 'callbackURL' parameter will be dispatched to async workers. 
    kasha worker --async --config=/path/to/config.js


    docker run -v /path/to/config.js:/dest/to/config.js kasha/kasha worker [--async] --config=/dest/to/config.js

    Site Config

      // The hostname of your site.
      host: '',
      // In proxy mode, if the request doesn't contain 'X-Forwarded-Proto' or 'Forwarded:...proto=...' header,
      // then use 'defaultProtocol'.
      defaultProtocol: 'https',
      // If your site use REST-style URLs, like /article/123, the query string isn't necessary to the page,
      // you can remove the query string to improve the cache hit rate:
      // keepQuery: false,
      // You can also keep the required query parameter of some URLs
      keepQuery: [
          '/search', // the first element is the pathname of URL.
          'type', // starting from the second element, specifies the query names you need to keep.
        // another URL and its query names
        ['/product', 'id']
      // You can use the '/render' API to crawl the hash-based Single-page application.
      // For example, you can crawl via
      // /render?
      // But if this site is not hash-based, you can remove the hash:
      keepHash: false,
      // Rewrites the request URL.
      rewrites: [
        // [from, to]
        // If 'to' is an empty string, the request will be aborted.
        // pattern syntax see
        // route all requests to the entry point HTML file
        ['*)', ''],
        // except robots.txt
        ['', ''],
        // or block it if you do not have one
        // ['', ''],
        // block google analytics requests
        ['*)', '']
      // Excludes the pages that don't need pre-rendering.
      excludes: [
      // But include these pages that matched the excludes pattern
      includes: [
      // Specifies the User-Agent
      userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/73.0.3683.103 Safari/537.36',
      // You can create profiles for different device types.
      // A profile can override keepQuery, keepHash, rewrites, excludes, includes, userAgent.
      profiles: {
        desktop: {
          userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/73.0.3683.103 Safari/537.36',
          rewrites: [
        mobile: {
          userAgent: 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/73.0.3683.103 Mobile Safari/537.36',
          rewrites: [
      // If profile param of the request isn't set, use this profile
      defaultProfile: 'desktop'


    Please confirm apiHost has been set correctly.

    For example, if set apiHost: '', then only requests from http(s)://* can access the APIs, All other domains are served in proxy mode.

    GET /render

    Renders the page.

    Query string params:

    url: The encoded URL of the webpage to render.

    profile: The profile to use.

    type: Set the response type. Defaults to json.

    • html: Returns html with header Content-Type: text/html.
    • json: Returns json with header Content-Type: application/json.
    • static: Returns html with header Content-Type: text/html, but stripped the <script> tags and on* event handlers.

    callbackURL: Don't wait the result. Once the job is done, POST the result to the given URL with json format. If callbackURL is set, type is ignored.

    metaOnly: If type is json, only returns meta data without html content.

    followRedirect: Follows the redirects if the page return 301/302.

    refresh: Forces to refresh the cache.

    noWait: Don't wait for the response. It is useful for pre-caching the page.

    fallback: If no cache found or the cache is expired, the request is proxied to the origin directly. If fallback is set, type must be html, callbackURL, metaOnly, followRedirect, refresh and noWait can not be set.

    To the boolean parameters, if the param is absent or set to 0, it means false. If set to 1 or empty value (e.g., &refresh, &refresh=, &refresh=1), it means true.

    Example: http://localhost:3000/render?

    The returned JSON format example:

      "url": "",
      "profile": "",
      "status": 200,
      "redirect": null,
      "meta": {
        "title": "Facebook Open Graph META Tags",
        "description": "Facebook's Open Graph protocol allows for web developers to turn their websites into Facebook \"graph\" objects, allowing a certain level of customization over how information is carried over from a non-Facebook website to Facebook when a page is \"recommended\" and \"liked\".",
        "image": "",
        "canonicalUrl": "",
        "author": "David Walsh",
        "keywords": null
      "openGraph": {
        "og": {
          "locale": {
            "current": "en_US"
          "type": "article",
          "title": "Facebook Open Graph META Tags",
          "description": "Facebook's Open Graph protocol allows for web developers to turn their websites into Facebook \"graph\" objects, allowing a certain level of customization over how information is carried over from a non-Facebook website to Facebook when a page is \"recommended\" and \"liked\".",
          "url": "",
          "site_name": "David Walsh Blog",
          "updated_time": "2016-02-23T00:44:54+00:00",
          "image": [
              "url": "",
              "secure_url": ""
              "url": "",
              "secure_url": ""
        "article": {
          "publisher": "",
          "section": "APIs",
          "published_time": "2011-04-25T09:24:28+00:00",
          "modified_time": "2016-02-23T00:44:54+00:00"
      "content": "<!DOCTYPE html><html>...</html>",
      "date": "2018-03-13T09:53:00.921Z"

    GET /:url

    Alias of /render?url=ENCODED_URL&type=html.

    For example, http://localhost:3000/ is equivalent to http://localhost:3000/render?

    And profile param can be set from Kasha-Profile header, fallback can be set from Kasha-Fallback header.

    Notice: the hash of the url won't be sent to server. If you need the hash to be sent to the server, use the /render API.

    Proxy mode

    If host header of the request is not apiHost, or X-Forwarded-Host or header is set, Then the requested URL will be treated as url query param of /render API. And type is set to html.

    For example, the following request

    GET /
    Kasha-Profile: mobile
    Kasha-Fallback: 1

    is equivalent to http://localhost:3000/render?

    GET /cache?url=URL

    Alias of /render?url=ENCODED_URL&noWait

    GET /:site/robots.txt

    Get robots.txt file with sitemaps collected by kasha. e.g.:


    It will fetch the file, then append sitemap directives at the end. The result example:

    User-agent: *
    Disallow: /cgi-bin/
    Disallow: /tmp/
    Disallow: /private/

    GET /:site/sitemaps.:page.xml

    Get sitemap of page N.

    For example:


    GET /:site/

    Get Google sitemap of page N.

    GET /:site/

    Get Google news sitemap of page N.

    GET /:site/

    Get Google image sitemap of page N.

    GET /:site/

    Get Google video sitemap of page N.

    GET /:site/sitemaps.index.:page.xml

    Get sitemap index file of page N.

    GET /:site/

    Get Google sitemap index file of page N.

    GET /:site/

    Get Google news sitemap index file of Page N.

    GET /:site/

    Get Google image sitemap index file of Page N.

    GET /:site/

    Get Google video sitemap index file of page N.

    Collecting sitemap data

    kasha can collect sitemap data from custom Open Graph <meta> tags. For example:

    <head prefix="og: sitemap:">
    canonical url is used as <loc> tag of sitemap xml.
    <meta property="og:url" content="..."> can be used also.
    <link rel="canonical" href="">
    <meta property="sitemap:changefreq" content="hourly">
    <meta property="sitemap:priority" content="1">
    <meta property="sitemap:news:publication:name" content="The Example Times">
    <meta property="sitemap:news:publication:language" content="en">
    <meta property="sitemap:news:publication_date" content="2018-05-25T09:19:54.000Z">
    <meta property="sitemap:news:title" content="Page Title">
    <meta property="sitemap:image:loc" content="">
    <meta property="sitemap:image:caption" content="The caption of the image.">
    <meta property="sitemap:image:geo_location" content="Limerick, Ireland">

    Sitemap data will be collected only if the origin of the canonical URL is the same as the current page.

    See here for available tags: sitemap protocol and Google sitemap extensions



    The logo is made from Prosymbols's camera icon licensed by Creative Commons BY 3.0.


    npm i kasha

    DownloadsWeekly Downloads






    Unpacked Size

    125 kB

    Total Files


    Last publish


    • jiangfengming