You cannot have a script in your Wikipage, since they sanitize the HTML (See what they allow here). To do what you want, you could generate that page in Gitlab-CI as part of your project's deploy pipeline, using whatever rendering engine and putting that variable in there, and update it automatically using Gitlab's Wiki APIs.

How to

I created a demo NodeJS project here, which, when I push to the master branch, auto-generates the Wiki pages. You can look at the code to see how it works.

This example app exposes a function to get a list of fruit and quantities in stock. We'll automatically add that data in the Wiki.

Step 1 - Create page templates

You can add templates to your project for your Wiki pages. In my example, I used MustacheJS. And I put everything in a wiki folder (see folder structure at the end of step 5). Your template can look something like this:

wiki/templates/home.mst

# Welcome to the supermarket

The biggest quantity we have in stock is for **{{topProduct.label}}**,
with a total of **{{topProduct.stock}}**!

|   Fruit   |   Quantity   |
|-----------|--------------|
{{#inventory}}
| {{label}} | {{stock}} |
{{/inventory}}

In this example, the data will come from the project code itself.

Step 2 - Build your pages

Note: The scripts I wrote as a demo use axios to make requests to the Gitlab API, mustache to render the pages, and qs to format the data as a query string before posting it to Gitlab. You can use other ones or install them as dev dependencies: npm install --save-dev axios mustache qs

Create a js file which will get the data from your app, and render the templates into a build directory. Something like this:

wiki/build.js

const fs = require('fs');
const Mustache = require('mustache');
const myApp = require('../src/index.js');
const inventory = myApp.getInventory();

// Get the Mustache template
const homeTemplate = fs.readFileSync(__dirname + '/templates/home.mst', 'utf-8');

// Get the fruit with the highest quantity
const topProduct = inventory.reduce((acc, curr) => {
  if (acc === null || curr.stock > acc.stock) {
    return curr;
  } else {
    return acc;
  }
}, null);

// Render the page using your variables
const homeContent = Mustache.render(homeTemplate, { inventory, topProduct });

// Write the file in a build directory
const buildDir = __dirname + '/../build';
if (!fs.existsSync(buildDir)) {
  fs.mkdirSync(buildDir);
}

fs.writeFileSync(buildDir + '/home.md', homeContent);

And in your package.json, add a command to run that script:

"scripts": {
    // ...
    "wiki:build": "node wiki/build.js"
  }

Step 3 - Deploy your Wiki pages

Create a script which will upload the pages to your Wiki. This may work as-is without much modification, if you're also using NodeJS.

wiki/deploy.js

const fs = require('fs');
const Axios = require('axios');
const qs = require('qs');

const config = {
  gitlabBaseUrl: 'https://gitlab.com', // Update this if you're on a private Gitlab
  projectId: process.env.CI_PROJECT_ID, // Provided by Gitlab-CI
  privateToken: process.env.WIKI_DEPLOY_TOKEN, // Added through Gitlab interface
  buildDir: __dirname + '/../build'
};

const axios = Axios.create({
  baseURL: config.gitlabBaseUrl,
  headers: { 'Private-Token': config.privateToken, Accept: 'application/json' }
});

(async function deploy() {
  const existingPages = await getExistingWikiPages();
  const updatedPages = getUpdatedPages();
  // Pages which existed but are no longer in the build (obsolete)
  const pagesToDelete = existingPages.filter(p1 => updatedPages.every(p2 => p2.slug !== p1.slug));
  // Pages which didn't exist before
  const pagesToCreate = updatedPages.filter(p1 => existingPages.every(p2 => p2.slug !== p1.slug));
  // Pages which already exist
  const pagesToUpdate = updatedPages.filter(p1 => existingPages.some(p2 => p2.slug === p1.slug));

  console.log(
    `Found ${pagesToDelete.length} pages to delete, ${pagesToCreate.length} pages to create, ${pagesToUpdate.length} pages to update.`
  );
  for (let page of pagesToDelete) {
    await deletePage(page);
  }
  for (let page of pagesToCreate) {
    await createPage(page);
  }
  for (let page of pagesToUpdate) {
    await updatePage(page);
  }
  console.log('Deploy complete!');
})();

function getExistingWikiPages() {
  return axios.get(`/api/v4/projects/${config.projectId}/wikis`).then(res => res.data);
}

function getUpdatedPages() {
  const files = fs.readdirSync(config.buildDir);
  return files.map(file => {
    const name = file // Remove the file extension
      .split('.')
      .slice(0, -1)
      .join('.');
    return {
      format: 'markdown', // You could make this depend on the file extension
      slug: name,
      title: name,
      content: fs.readFileSync(`${config.buildDir}/${file}`, 'utf-8')
    };
  });
}

function deletePage(page) {
  console.log(`Deleting ${page.slug}...`);
  return axios.delete(`/api/v4/projects/${config.projectId}/wikis/${page.slug}`);
}

function createPage(page) {
  console.log(`Creating ${page.slug}...`);
  return axios.post(`/api/v4/projects/${config.projectId}/wikis`, qs.stringify(page));
}

function updatePage(page) {
  console.log(`Updating ${page.slug}...`);
  return axios.put(`/api/v4/projects/${config.projectId}/wikis/${page.slug}`, qs.stringify(page));
}

In the config at the top, you need to specify which URL your Gitlab is using. CI_PROJECT_ID will be provided by Gitlab-CI itself as an environment variable. WIKI_DEPLOY_TOKEN, however, will not. Set it up in step 4.

And in your package.json, add a command to run that script:

"scripts": {
    // ...
    "wiki:build": "node wiki/build.js",
    "wiki:deploy": "node wiki/deploy.js"
  }

Note: This example will delete obsolete pages, and update or create new ones depending on files it finds in the build folder and the ones the Wiki already contains. If you want to have attachments as well (images), you'll need to make use of this API also.

Step 4 - Setup a private token WIKI_DEPLOY_TOKEN

For this, you'll need to click on your profile picture at the top right corner > Settings. Then in the left menu, Access Tokens, and create a token with the api scope. The name does not matter. Copy this token now, since it will only be shown once.

Then, go to your project. In the menu on the left, click Settings > CI/CD. Expand the Variables section, and use the previously copied token to create a variable called WIKI_DEPLOY_TOKEN, make it Masked so that it does not appear in any logs, and Save variables:

This will make that token available only in your pipelines, as an environment variable.

Step 5 - Create your pipeline

If you don't already have a pipeline, all you need to do is create a .gitlab-ci.yml file at the root of your project. Declare a generate_wiki stage:

.gitlab-ci.yml

stages:
  # - tests
  # - deploy
  # ...
  - generate_wiki

generate_wiki:
  image: node:10
  stage: generate_wiki
  script:
    - npm install
    - npm run wiki:build  # build the wiki in a directory
    - npm run wiki:deploy # update it in Gitlab
  only:
    - master # Only when merging or pushing to master branch


# ... rest of your pipeline ...

As you can see, we use the commands wiki:build and wiki:deploy declared in steps 2 and 3.

Now, your project structure should look something like this:

/
├───src
│    └── index.js
├───wiki
│    ├── templates
│    │    └── home.mst
│    ├── build.js
│    └── deploy.js
├── .gitlab-ci.yml
└── package.json

Step 6 - Push to master, and enjoy the magic

After pushing, if everything went right, you can click on CI/CD in the left menu, and you should see your pipeline running:

If you click on the little circle, you should see the logs:

And if you go to your Wiki pages, they should be up to date, automagically:

Answer from blex on Stack Overflow
🌐
GitLab
docs.gitlab.com › gitlab docs › use gitlab › deploy and release your application › gitlab pages
GitLab Pages | GitLab Docs
GitLab Pages publishes static websites directly from a repository in GitLab. ... Deploy automatically with GitLab CI/CD pipelines. Support any static site generator (like Hugo, Jekyll, or Gatsby) or plain HTML, CSS, JavaScript, and Wasm.
Top answer
1 of 1
9

You cannot have a script in your Wikipage, since they sanitize the HTML (See what they allow here). To do what you want, you could generate that page in Gitlab-CI as part of your project's deploy pipeline, using whatever rendering engine and putting that variable in there, and update it automatically using Gitlab's Wiki APIs.

How to

I created a demo NodeJS project here, which, when I push to the master branch, auto-generates the Wiki pages. You can look at the code to see how it works.

This example app exposes a function to get a list of fruit and quantities in stock. We'll automatically add that data in the Wiki.

Step 1 - Create page templates

You can add templates to your project for your Wiki pages. In my example, I used MustacheJS. And I put everything in a wiki folder (see folder structure at the end of step 5). Your template can look something like this:

wiki/templates/home.mst

# Welcome to the supermarket

The biggest quantity we have in stock is for **{{topProduct.label}}**,
with a total of **{{topProduct.stock}}**!

|   Fruit   |   Quantity   |
|-----------|--------------|
{{#inventory}}
| {{label}} | {{stock}} |
{{/inventory}}

In this example, the data will come from the project code itself.

Step 2 - Build your pages

Note: The scripts I wrote as a demo use axios to make requests to the Gitlab API, mustache to render the pages, and qs to format the data as a query string before posting it to Gitlab. You can use other ones or install them as dev dependencies: npm install --save-dev axios mustache qs

Create a js file which will get the data from your app, and render the templates into a build directory. Something like this:

wiki/build.js

const fs = require('fs');
const Mustache = require('mustache');
const myApp = require('../src/index.js');
const inventory = myApp.getInventory();

// Get the Mustache template
const homeTemplate = fs.readFileSync(__dirname + '/templates/home.mst', 'utf-8');

// Get the fruit with the highest quantity
const topProduct = inventory.reduce((acc, curr) => {
  if (acc === null || curr.stock > acc.stock) {
    return curr;
  } else {
    return acc;
  }
}, null);

// Render the page using your variables
const homeContent = Mustache.render(homeTemplate, { inventory, topProduct });

// Write the file in a build directory
const buildDir = __dirname + '/../build';
if (!fs.existsSync(buildDir)) {
  fs.mkdirSync(buildDir);
}

fs.writeFileSync(buildDir + '/home.md', homeContent);

And in your package.json, add a command to run that script:

"scripts": {
    // ...
    "wiki:build": "node wiki/build.js"
  }

Step 3 - Deploy your Wiki pages

Create a script which will upload the pages to your Wiki. This may work as-is without much modification, if you're also using NodeJS.

wiki/deploy.js

const fs = require('fs');
const Axios = require('axios');
const qs = require('qs');

const config = {
  gitlabBaseUrl: 'https://gitlab.com', // Update this if you're on a private Gitlab
  projectId: process.env.CI_PROJECT_ID, // Provided by Gitlab-CI
  privateToken: process.env.WIKI_DEPLOY_TOKEN, // Added through Gitlab interface
  buildDir: __dirname + '/../build'
};

const axios = Axios.create({
  baseURL: config.gitlabBaseUrl,
  headers: { 'Private-Token': config.privateToken, Accept: 'application/json' }
});

(async function deploy() {
  const existingPages = await getExistingWikiPages();
  const updatedPages = getUpdatedPages();
  // Pages which existed but are no longer in the build (obsolete)
  const pagesToDelete = existingPages.filter(p1 => updatedPages.every(p2 => p2.slug !== p1.slug));
  // Pages which didn't exist before
  const pagesToCreate = updatedPages.filter(p1 => existingPages.every(p2 => p2.slug !== p1.slug));
  // Pages which already exist
  const pagesToUpdate = updatedPages.filter(p1 => existingPages.some(p2 => p2.slug === p1.slug));

  console.log(
    `Found ${pagesToDelete.length} pages to delete, ${pagesToCreate.length} pages to create, ${pagesToUpdate.length} pages to update.`
  );
  for (let page of pagesToDelete) {
    await deletePage(page);
  }
  for (let page of pagesToCreate) {
    await createPage(page);
  }
  for (let page of pagesToUpdate) {
    await updatePage(page);
  }
  console.log('Deploy complete!');
})();

function getExistingWikiPages() {
  return axios.get(`/api/v4/projects/${config.projectId}/wikis`).then(res => res.data);
}

function getUpdatedPages() {
  const files = fs.readdirSync(config.buildDir);
  return files.map(file => {
    const name = file // Remove the file extension
      .split('.')
      .slice(0, -1)
      .join('.');
    return {
      format: 'markdown', // You could make this depend on the file extension
      slug: name,
      title: name,
      content: fs.readFileSync(`${config.buildDir}/${file}`, 'utf-8')
    };
  });
}

function deletePage(page) {
  console.log(`Deleting ${page.slug}...`);
  return axios.delete(`/api/v4/projects/${config.projectId}/wikis/${page.slug}`);
}

function createPage(page) {
  console.log(`Creating ${page.slug}...`);
  return axios.post(`/api/v4/projects/${config.projectId}/wikis`, qs.stringify(page));
}

function updatePage(page) {
  console.log(`Updating ${page.slug}...`);
  return axios.put(`/api/v4/projects/${config.projectId}/wikis/${page.slug}`, qs.stringify(page));
}

In the config at the top, you need to specify which URL your Gitlab is using. CI_PROJECT_ID will be provided by Gitlab-CI itself as an environment variable. WIKI_DEPLOY_TOKEN, however, will not. Set it up in step 4.

And in your package.json, add a command to run that script:

"scripts": {
    // ...
    "wiki:build": "node wiki/build.js",
    "wiki:deploy": "node wiki/deploy.js"
  }

Note: This example will delete obsolete pages, and update or create new ones depending on files it finds in the build folder and the ones the Wiki already contains. If you want to have attachments as well (images), you'll need to make use of this API also.

Step 4 - Setup a private token WIKI_DEPLOY_TOKEN

For this, you'll need to click on your profile picture at the top right corner > Settings. Then in the left menu, Access Tokens, and create a token with the api scope. The name does not matter. Copy this token now, since it will only be shown once.

Then, go to your project. In the menu on the left, click Settings > CI/CD. Expand the Variables section, and use the previously copied token to create a variable called WIKI_DEPLOY_TOKEN, make it Masked so that it does not appear in any logs, and Save variables:

This will make that token available only in your pipelines, as an environment variable.

Step 5 - Create your pipeline

If you don't already have a pipeline, all you need to do is create a .gitlab-ci.yml file at the root of your project. Declare a generate_wiki stage:

.gitlab-ci.yml

stages:
  # - tests
  # - deploy
  # ...
  - generate_wiki

generate_wiki:
  image: node:10
  stage: generate_wiki
  script:
    - npm install
    - npm run wiki:build  # build the wiki in a directory
    - npm run wiki:deploy # update it in Gitlab
  only:
    - master # Only when merging or pushing to master branch


# ... rest of your pipeline ...

As you can see, we use the commands wiki:build and wiki:deploy declared in steps 2 and 3.

Now, your project structure should look something like this:

/
├───src
│    └── index.js
├───wiki
│    ├── templates
│    │    └── home.mst
│    ├── build.js
│    └── deploy.js
├── .gitlab-ci.yml
└── package.json

Step 6 - Push to master, and enjoy the magic

After pushing, if everything went right, you can click on CI/CD in the left menu, and you should see your pipeline running:

If you click on the little circle, you should see the logs:

And if you go to your Wiki pages, they should be up to date, automagically:

Discussions

javascript - How can I use GitLab pages to host webpages with a user input form, which updates a GitLab repo when saved? - Stack Overflow
I know that GitLab pages is made to host static pages rather than dynamic but I'm not too clear on the borderlines between static and dynamic and whether there are different levels of how dynamic a More on stackoverflow.com
🌐 stackoverflow.com
Pages not showing javascript site
When I want to view the site through the site-url provided in Pages I currently get to see an empty page, indicating that no webserver is running in order to run the JavaScript code in the html-file (viewing the source code of the empty page shows that the index file is shown, but the JavaScript ... More on forum.gitlab.com
🌐 forum.gitlab.com
0
0
April 24, 2023
Gitlab Pages with an HTTP POST?
Yes 100%. I actually built and maintain a GitLab pages website and CLI tool that are both wrappers around the GitLab api to parameterize and trigger pipelines on behalf of my teammates. In order to do this on the GitLab pages side, we need a few things: Create a GitLab application in Preferences -> Applications, and configure it to allow OAUTH and whichever permissions you need for yourself/teammates. Set the website up to login with OAUTH to get an access token for the user that logged in Using that access token, you can now access the GitLab API and can use it to call the GitLab triggers api endpoint. Given you mention Hugo, you'll need to write your own JavaScript modules to handle the API calls and letting the user know about success/failure statuses. One simple way is to have your inputs all within a ``, and then intercept the submit call, make the API call to trigger your GitLab pipeline, and then open the running pipeline page in a new tab (part of the Trigger pipeline response). Another Consideration: - Since GitLab pages can be protected behind private organizations (i.e. GitLab will protect your site from anyone who doesn't have access to your GitLab account), you can skip the OAUTH part and create an AccessToken that you deploy with the site. The access token can be used to call the GitLab API directly without having people login. This solution assumes some familiarity with JavaScript, web technologies, and authenticated web apps/apis. Let me know if you need help with any of these! More on reddit.com
🌐 r/gitlab
18
5
February 2, 2022
javascript - Access and display a gitlab username on a private gitlab pages hosted website - Stack Overflow
It uses Jekyll and some HTML templates to build the site pages from markdown files. Some of the info on the site would be clearer to the users if I could display their gitlab usernames to them. I would have to indicate where it would be displayed on the markdown file. Is there any way to set their gitlab username as a variable in html, liquid, or JavaScript ... More on stackoverflow.com
🌐 stackoverflow.com
🌐
How-To
how-to.dev › how-to-build-frontend-javascript-on-gitlab
How to build frontend JavaScript on GitLab
September 2, 2021 - To update our build, we can set .gitlab-ci.yml to: pages: image: node:14 artifacts: paths: - public script: - npm ci - npm run build
🌐
GitLab
forum.gitlab.com › gitlab ci/cd
Pages not showing javascript site - GitLab CI/CD - GitLab Forum
April 24, 2023 - When I want to view the site through the site-url provided in Pages I currently get to see an empty page, indicating that no webserver is running in order to run the JavaScript code in the html-file (viewing the source c…
Find elsewhere
🌐
Zabbix
sbcode.net › threejs › gitlab-pages
Host using GitLab Pages - Three.js Tutorials
Go back to the root of your project, and create a new file, and select gitlab-ci.yml, then Apply Template and then find and choose the HTML option. The HTML template is already correctly configured to serve static files, so you can press the Commit Changes button right away. Go to Settings/Pages ...
🌐
Embl-community
grp-bio-it-workshops.embl-community.io › building-websites-with-gitlab › 03-gitlab-pages › index.html
Hosting Pages on GitLab – Building Websites with GitLab
August 2, 2023 - As anticipated by the previous chapters, to publish a website with GitLab Pages you can use several different technologies like Jekyll, Gatsby, Hugo, Middleman, Harp, Hexo, and Brunch, just to name a few. You can also publish any static website written directly in plain HTML, CSS, and JavaScript.
🌐
Medium
medium.com › turpialdev › how-to-host-an-html-page-in-gitlab-pages-47bbfbdeb4d1
How to host an HTML page in GitLab Pages | by Turpial Development | Turpial Dev | Medium
November 27, 2018 - In this article, we will focus on html pages and we will see step by step how to host our projects in GitLab. To begin with, you must be familiar with git and have a GitLab account. If you are not registered you can do it using your GitHub, BitBucket, Twitter or Google credentials. Once you have logged in, create a new project and upload your html code with its index.html file and dependencies, like css style sheets, javascript scripts, fonts, images, etc…
🌐
W3Schools
w3schools.com › git › git_remote_pages.asp
Git GitLab Pages
GitHub Bitbucket GitLab · ❮ Previous Next ❯ · ★ +1 · Sign in to track progress · REMOVE ADS · PLUS · SPACES · GET CERTIFIED · FOR TEACHERS · BOOTCAMPS · CONTACT US · × · If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail: sales@w3schools.com · If you want to report an error, or if you want to make a suggestion, send us an e-mail: help@w3schools.com · HTML Tutorial CSS Tutorial JavaScript Tutorial How To Tutorial SQL Tutorial Python Tutorial W3.CSS Tutorial Bootstrap Tutorial PHP Tutorial Java Tutorial C++ Tutorial jQuery Tutorial ·
🌐
Faun
faun.pub › a-simple-to-do-app-with-gitlab-pages-8c56c7c1c762
A Simple To-do App With Gitlab Pages | by Amir | FAUN.dev() 🐾
July 27, 2021 - In this article, I’m going to describe how you could set up a static website with GitLab pages and also using your domain for it. For this tutorial you will need to work with the console, a GitLab repository, owning a domain, and understand react and javascript a little
🌐
GitLab
about.gitlab.com › blog › engineering › hosting on gitlab.com with gitlab pages
Hosting on GitLab.com with GitLab Pages
April 7, 2016 - Hexo is a powerful blog-aware framework built with NodeJS, a server-side JavaScript environment based on Google V8 high-performance engine. To build our Hexo site, we can start with this .gitlab-ci.yml: ... image: node:4.2.2 pages: cache: paths: - node_modules/ script: - npm install hexo-cli -g - npm install - hexo deploy artifacts: paths: - public only: - main
🌐
Programonaut
programonaut.com › home › blog › host your website for free with gitlab pages (step-by-step)
Host your website for free with GitLab Pages (step-by-step)
June 5, 2022 - GitLab Pages is a static site hosting service provided by GitLab. It uses HTML, CSS, and JavaScript inside a repository to publish your website to the web! The coolest thing… all of this is completely free of charge.
🌐
Reddit
reddit.com › r/gitlab › gitlab pages with an http post?
r/gitlab on Reddit: Gitlab Pages with an HTTP POST?
February 2, 2022 -

Rather than spend a few hours digging into this, I just wanted to ask the question to the community for some guidance.

I need to create a web page for the purposes of kicking off a pipeline with parameters passed to it. Originally, I wanted to use Gitlab Pages, host a site that had drop-down boxes and text boxes, and the like, but reading through Hugo (the most starred example on Gitlab Pages), I don't think I can do an HTTP Post.

Is there anything I can run in Gitlab Pages to make this work? Or am I screwed and I need to just get something up and running on a flask server?

Top answer
1 of 3
5
Yes 100%. I actually built and maintain a GitLab pages website and CLI tool that are both wrappers around the GitLab api to parameterize and trigger pipelines on behalf of my teammates. In order to do this on the GitLab pages side, we need a few things: Create a GitLab application in Preferences -> Applications, and configure it to allow OAUTH and whichever permissions you need for yourself/teammates. Set the website up to login with OAUTH to get an access token for the user that logged in Using that access token, you can now access the GitLab API and can use it to call the GitLab triggers api endpoint. Given you mention Hugo, you'll need to write your own JavaScript modules to handle the API calls and letting the user know about success/failure statuses. One simple way is to have your inputs all within a ``, and then intercept the submit call, make the API call to trigger your GitLab pipeline, and then open the running pipeline page in a new tab (part of the Trigger pipeline response). Another Consideration: - Since GitLab pages can be protected behind private organizations (i.e. GitLab will protect your site from anyone who doesn't have access to your GitLab account), you can skip the OAUTH part and create an AccessToken that you deploy with the site. The access token can be used to call the GitLab API directly without having people login. This solution assumes some familiarity with JavaScript, web technologies, and authenticated web apps/apis. Let me know if you need help with any of these!
2 of 3
2
Do you need to have random people do it? Maybe a HTML form would be enough to make it possible. You just need to make sure the api token is there but no one can do more with it than you intended.
🌐
Medium
nfrankel.medium.com › gitlab-pages-preview-d582431ebf99
GitLab Pages preview. When I write Apache APISIX-related blog… | by Nicolas Fränkel | Medium
June 8, 2023 - To publish a website with Pages, you can use any static site generator, like Gatsby, Jekyll, Hugo, Middleman, Harp, Hexo, or Brunch. You can also publish any website written directly in plain HTML, CSS, and JavaScript.
🌐
Hexo
hexo.io › docs › gitlab-pages
GitLab Pages | Hexo
July 29, 2026 - Add .gitlab-ci.yml file to the root folder of your repo (alongside _config.yml & package.json) with the following content (replacing 16 with the major version of Node.js you noted in previous step):
🌐
Gitlab
soykje.gitlab.io › en › blog › jamstack-gitlab-pages
Jamstack & Gitlab Pages | J Paul Lescouzères
Based on a Next.js project, we will see how to configure the Gitlab CI/CD, thanks to the .gitlab-ci.yml file and some tweaks, to deploy directly to Gitlab Pages!
🌐
PRACE
repository.prace-ri.eu › help
Index · Pages · Project · User · Help · GitLab
Host your site on your own GitLab instance or on GitLab.com for free. Connect your custom domains and TLS certificates. Attribute any license to your content. To publish a website with Pages, you can use any static site generator, like Gatsby, Jekyll, Hugo, Middleman, Harp, Hexo, or Brunch. You can also publish any website written directly in plain HTML, CSS, and JavaScript...