Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/bemit/create-amp-page

Static site generator for AMP with Twig templates and a lot of config options.
https://github.com/bemit/create-amp-page

amp frontmatter gulp html-renderer sass ssr static-site static-site-generator template-engine twig twigjs

Last synced: 3 months ago
JSON representation

Static site generator for AMP with Twig templates and a lot of config options.

Awesome Lists containing this project

README

        

# Create AMP Page

Fast development of fast pages.

[![npm (scoped)](https://img.shields.io/npm/v/create-amp-page?style=flat-square)](https://www.npmjs.com/package/create-amp-page)
[![npm (scoped)](https://img.shields.io/npm/dm/create-amp-page.svg?style=flat-square)](https://npmcharts.com/compare/create-amp-page?interval=30)
[![Travis (.com) master build](https://img.shields.io/travis/com/bemit/create-amp-page/master?style=flat-square)](https://travis-ci.com/github/bemit/create-amp-page)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
![Typed](https://flat.badgen.net/badge/icon/Typed?icon=typescript&label&labelColor=blue&color=555555)

Static site generator built with gulp tasks, using Twig templates, optimized for building [AMP](https://amp.dev) pages - but not limited to AMP.

Support for Sass, CSS optimizing, CSS into head injection, media file compressing, automatic resizing of images by `srcset`, endless copy tasks, Twig global and optional per-page data with JSON and/or frontmatter, browsersync with custom static server middlewares, [AMP Optimizer](https://amp.dev/documentation/guides-and-tutorials/optimize-and-measure/amp-optimizer-guide/) or HTML Minifier (for non-AMP), remove unused CSS (currently only for inline CSS). Different ways to define pages, can be connected with e.g. netlify cms.

🚀 Checkout the [starter template repositories!](#starter-templates)

## Quick Start

**1.** Create a project folder, init your project with `npm init`

**2.** Create a `Gulpfile.js` and paste the following content in it. For all options and docs see the [AmpCreatorOptions typing](https://github.com/bemit/create-amp-page/blob/master/src/AmpCreatorOptions.d.ts).

```js
import path from 'path'
import gulp from 'gulp'
import {ampCreator, getPageInfo} from 'create-amp-page'
// since `1.0.0-beta.0` the amp-optimizer is a peer-dep (you need to install it additionally!)
// makes only sense if you want AMP-valid HTML
import AmpOptimizer from '@ampproject/toolbox-optimizer'

const port = 4488

/**
* @type {PagesUrlsMap}
*/
const urls = {
example: {
local: {base: 'http://localhost:' + port + '/default/'},
prod: {base: 'https://example.org/'},
},
}

const pages = {
example: {
paths: {
styles: 'src/styles',
stylesInject: 'main.css',
style: 'main.scss',
html: 'src/html',
dist: 'build',
distStyles: 'styles',
},
},
}
const isDev = process.env.NODE_ENV === 'development'

const tasks = ampCreator({
port: port,
dist: 'build',
srcMedia: 'src/media',
distMedia: 'media',
pages: pages,
collections: [{
fm: (file) => 'src/data/' + path.basename(file).slice(0, '.twig'.length * -1) + '.md',
tpl: 'src/html/pages/*.twig',
base: '',
pageId: 'example',
}, {
fm: 'src/data/blog/*.md',
tpl: 'src/html/blog.twig',
base: 'blog',
pageId: 'example',
}],
// when `ampEnabled: true` use the `ampOptimizer` for HTML minification and more
ampOptimizer: !isDev ? AmpOptimizer.create({}) : undefined,
// when `ampEnabled: false` use `minifyHtml` for HTML minification and more
// minifyHtml: false,
cleanInlineCSS: !isDev,
cleanInlineCSSWhitelist: ['#anc-*'],
// for css injection of non-AMP pages:
// cssInjectTag: '',
twig: {
data: {ampEnabled: true},
fmMap: (data, files) => {
const pageId = files.pageId
const {
pagePath, pageBase,
} = getPageInfo(files, urls, pageId, isDev ? 'local' : 'prod')
const pageData = pages[pageId]
return {
pageId: pageId,
styleSheets: [
pageData.paths.stylesInject,
],
head: {
title: data.attributes.title,
description: data.attributes.description,
lang: data.attributes.lang,
},
links: {
canonical: pageBase + pagePath,
origin: pageBase,
cdn: isDev ? 'http://localhost:' + port + '/' : pageBase,
},
content: data.body,
}
},
logicLoader: async () => {
return {}
},
},
prettyUrlExtensions: ['html'],
})

Object.keys(tasks).forEach(taskName => gulp.task(taskName, tasks[taskName]))
```

**3.** Add those scripts into `package.json`, the project must be `type=module`:

```json
{
"type": "module",
"scripts": {
"tasks": "gulp --tasks",
"start": "cross-env NODE_ENV=development gulp watch",
"build": "cross-env NODE_ENV=production gulp build",
"clean": "gulp clean"
}
}
```

**4.** Create a `postcss.config.js` with:

```js
module.exports = {
plugins: [
require('cssnano')({
preset: ['default', {
discardComments: {
removeAll: true,
},
}],
}),
],
}
```

**5.** Add your `src` folders & files, minimum for this config: `src/styles/main.scss`, `src/html/pages/index.twig`, `src/data/index.md` and `src/media/.gitkeep`

**6.** Install this SSR: `npm i --save create-amp-page`

**7.** Run `npm start` and happy coding!

## Starter Templates

Checkout the starter repos:

- ⚡ [bemit/create-amp-page-starter](https://github.com/bemit/create-amp-page-starter)
- ready configured for static AMP valid pages
- includes a simple twig template
- ⚛️ [bemit/create-page-starter](https://github.com/bemit/create-page-starter)
- ready configured for static pages, non-AMP pages
- with babel/webpack build process
- support for typescript/react configured
- service worker example integrated
- includes a simple twig template

## Page generations

Two integrated ways of page generation:

1. One page per template file
2. One page per content file, for multiple content-files one template

Since `1.0.0-alpha.8` both page generations are configured by `collections`:

```js
const options = {
collections: [
{
// create one page per `twig` file, `fm` needs to return the relative path to the frontmatter file (or `undefined` fo no-fm`
fm: (file) => 'example/data/' + path.basename(file).slice(0, '.twig'.length * -1) + '.md',
tpl: 'example/html/pages/*.twig',
base: '',
pageId: 'example',
},
{
// create one page per `fm` file, one `tpl` is used for all pages
fm: 'example/data/blog/*.md',
tpl: 'example/html/blog.twig',
base: 'blog',
pageId: 'example',
}
],
}
```

## Twig Functions

### getImage

Get metadata and sizing for image, caches the read-result for each execution, purging cache on each watch trigger of html.

- params:
- `src` is the relative path to media folder incl. media folder
- `srcset` is an array of objects, define in which image sizes the image should be resized
- `w` = width in pixels, internally it calculates the other value proportional
- returns:
- `src` path to file
- `width` of file
- `height` of file
- `hash` sha1 hash of file content

#### getImage Twig Example

Template using `getImage(src, srcset)` to fetch metadata and resize images when needed:

```twig
{% set image = getImage(src, srcset) %}
<amp-img
src="{{ image.src ~ '?key=' ~ (image.hash|slice(0,12)) }}"
width="{{ image.width }}"
height="{{ image.height }}"
{# generate srcset with same syntax like `getImage` #}
srcset="{% for set in srcset %}{{ addImageSuffix(image.src, '_'~set.w~'w') ~ '?key=' ~ (image.hash|slice(0,12))~' '~set.w~'w' }}{% if loop.index < (srcset|length) %}, {% endif %}{% endfor %}"
sizes="{{ sizes }}"
layout="responsive"
></amp-img>
```

Embed then in file, pixels at `srcset`:

```twig
{% embed 'image.twig' with {
src: '/media/img-01.png',
alt: 'A blog hero image',
classes: 'flex',
srcset: [
{w: '320'},
{w: '680'},
{w: '920'}
],
sizes: '(max-width: 320px) 320px, (max-width: 600px) 680px',
} %}
{% endembed %}
```

Generates HTML like:

```html

<amp-img
src="/media/img-01.png?key=2l8ybbe1tjSP"
width="1280" height="421"
srcset="/media/img-01_320w.png?key=2l8ybbe1tjSP 320w, /media/img-01_680w.png?key=2l8ybbe1tjSP 680w, /media/img-01_920w.png?key=2l8ybbe1tjSP 920w"
sizes="(max-width: 320px) 320px, (max-width: 600px) 680px"
layout="responsive"
></amp-img>
```

### addImageSuffix

Add an image suffix between name and extension:

```twig
{{ addImageSuffix(image.src, '_suffix') }}
```

### embedScript

To embed e.g. css or js files directly in build template, uses the `src` relative to configured `dist`:

```twig
{{ embedScript('js/main.js') }}
```

## License

This project is free software distributed under the **MIT License**.

See: [LICENSE](LICENSE).

© 2022 [Michael Becker](https://i-am-digital.eu)

### Versions

See [github release notes](https://github.com/ui-schema/ui-schema/releases) for updates, especially incompatibilities, for features check the current `AmpCreatorOptions` typing.

This project adheres to [semver](https://semver.org/).

### Contributors

By committing your code/creating a pull request to this repository you agree to release the code under the MIT License attached to the repository.