1.0.0-beta.16 • Published 7 days ago

@indiekit/frontend v1.0.0-beta.16

Weekly downloads
13
License
MIT
Repository
github
Last release
7 days ago

Indiekit

Build status

Indiekit is a small but powerful server that acts as the go-between your website and the wider independent web. Using IndieWeb protocols and standards, Indiekit lets you:

  • publish content to your website using applications like iAWriter, Micro.blog, Icro, Indigenous and other tools that support the Micropub API
  • accept likes, comments and other feedback on your content using Webmentions
  • syndicate content to social networks like Twitter, Mastodon and LinkedIn

Quick start

The easiest way to get started is to deploy this application to Heroku.

This assumes you’ll be saving files to GitHub and publishing to a Jekyll (or similar) static site generator.

Clicking the button below will guide you through the process.

Deploy

You’ll be asked to provide the following values:

  • GITHUB_TOKEN - A GitHub personal access token
  • GITHUB_USER - Your username on GitHub
  • GITHUB_REPO - Name of the repository where you want to save files
  • PUBLICATION_URL - URL of the website you want to publish to

Contents

Requirements

  • Node.js v12+

Features

  • Create, update and delete posts
  • Upload files
  • Configure different post types
  • Accept post status and visibility
  • Review previously published posts and files
  • Bookmarklet to save and share bookmarks
  • Publish to different content stores (GitHub and GitLab)
  • Support for popular static site generators (Jekyll, Hugo, 11ty)
  • Plugin API

Install

npm install @indiekit/indiekit

Usage

Set up your server

Create a configuration file, indiekit.config.js, setup Indiekit and export its server:

import {Indiekit} from '@indiekit/indiekit';

// Create a new indiekit instance
const indiekit = new Indiekit();

// Create a server
const server = indiekit.server();

// Export server
export default server;

Start the server with node indiekit.config.js.

Indiekit can now listen for Micropub requests, but a few bits of information are needed before it can publish content to your website.

Configure your publication

Indiekit needs to know your website’s URL. You can provide this information using Indiekit’s configuration API, like so:

indiekit.set('publication.me', 'https://paulrobertlloyd.com');

Add a publication preset

Indiekit needs to know what post types you want to publish (for example notes and photos) and in which format. This information can be provided by setting publication.postTypes and publication.postTemplate. See Configuring post types and Creating a post template.

A publication preset plugin can provide default values for these options (which you can override in your configuration file).

If you use the Jekyll static site generator, you can install the Jekyll plugin:

npm install @indiekit/preset-jekyll

Then add it to your configuration file:

import {JekyllPreset} from '@indiekit/preset-jekyll';
const jekyll = new JekyllPreset();
indiekit.set('publication.preset', jekyll);

Add a content store

Indiekit needs to know where to store your posts and media files. A content store plugin provides this functionality.

If you are saving your files to GitHub, install the GitHub plugin:

npm install @indiekit/store-github

Then add it to your configuration file:

import {GithubStore} from '@indiekit/store-github';
const github = new GithubStore({
  user: 'username', // Your username on GitHub
  repo: 'reponame', // Repository files will be saved to
  branch: 'main', // Branch to publish to
  token: 'token' // GitHub personal access token
});
indiekit.set('publication.store', github);

Example configuration

With all these settings in place, your configuration file will look something like this:

import {Indiekit} from '@indiekit/indiekit';
import {JekyllPreset} from '@indiekit/preset-jekyll';
import {GithubStore} from '@indiekit/store-github';

// Create a new indiekit instance
const indiekit = new Indiekit();

// Configure GitHub content store
const github = new GithubStore({
  user: 'username', // Your username on GitHub
  repo: 'reponame', // Repository files will be saved to
  branch: 'main', // Branch to publish to
  token: 'token' // GitHub personal access token
});

// Configure Jekyll publication preset
const jekyll = new JekyllPreset();

// Configure publication
indiekit.set('publication.me', 'https://paulrobertlloyd.com');
indiekit.set('publication.preset', jekyll);
indiekit.set('publication.store', github);

// Create a server
const server = indiekit.server();

// Export server
export default server;

Enable automatic discovery

To ensure Indiekit’s endpoint can be discovered by Micropub clients (and have permission to post to your website), you need to add the follow values to your website’s <head>:

<link rel="micropub" href="[INDIEKIT_URL]/micropub">
<link rel="authorization_endpoint" href="https://indieauth.com/auth">
<link rel="token_endpoint" href="https://tokens.indieauth.com/token">

Options

application.locale

The language used in the application interface. Available languages: en

Type: string\ Optional, defaults to en

application.mongodbUrl

To cache files and save information about previously posts and files, you will need to connect Indiekit to a MongoDB database. You can host one on MongoDB Atlas.

Type: URL\ Optional

application.name

The name of your server.

Type: string\ Optional, defaults to Indiekit

application.themeColor

Accent colour used in the application interface.

Type: string\ Optional, defaults to #0000ee

publication.categories

A list of categories or tags used on your website. Can be an array of values, or the location of a JSON file providing an array of values.

Type: Array | URL\ Optional

publication.locale

Your publication’s locale, this value is currently used to format dates.

Type: string\ Optional, defaults to value in application.locale

publication.me

Your website’s URL.

Type: URL\ Required

publication.mediaEndpoint

Indiekit provides a media endpoint, but you can use a third-party endpoint by setting a value for this option.

Type: URL\ Optional

publication.postTemplate

A post template is a function that takes post properties received and parsed by the Micropub endpoint and renders them in a given file format, for example, a Markdown file with YAML frontmatter.

Type: Function\ Optional, defaults to MF2 JSON

publication.postTypes

A set of default paths and templates for different post types. See Configuring post types.

Type: Array\ Optional if using a preset

publication.preset

A publication preset plugin.

Type: Function\ Optional

publication.slugSeparator

The character used to replace spaces when creating a slug.

Type: string\ Optional, defaults to -

publication.store

A content store plugin.

Type: Function\ Required

publication.sydnicationTargets

An array of syndication targets. Example:

[{
  uid: 'https://twitter.com/paulrobertlloyd/',
  name: 'Paul Robert Lloyd on Twitter'
}, {
  uid: 'https://mastodon.social/@paulrobertlloyd',
  name: 'Paul Robert Lloyd on Mastodon'
}, {
  uid: 'https://micro.blog/paulrobertlloyd',
  name: 'Paul Robert Lloyd on Micro.blog'
}]

Type: Array\ Optional

publication.timeZone

The time zone for your publication. By default this is set to UTC, however if you want to offset dates according to your time zone you can provide a time zone name, for example, Europe/London:

indiekit.set('publication.timeZone', 'Europe/London');

Some servers will have a time zone saved in the TZ environment variable. In which case, you could supply that value instead:

indiekit.set('publication.timeZone', process.env.TZ);

Type: string\ Optional, defaults to UTC

publication.tokenEndpoint

An IndieAuth token endpoint.

Type: URL\ Optional, defaults to https://tokens.indieauth.com/token

Configuring post types

Micropub clients let you publish a variety of post types, and Indiekit lets you decide how these different types are handled. You can do this by using a publication preset, configuring values manually, or a combination of both.

For example, to use the Jekyll preset but override the note and photo post types, you would use the following configuration:

import {JekyllPreset} from '@indiekit/preset-jekyll';

// Use a preset
const jekyll = new JekyllPreset();
indiekit.set('publication.preset', jekyll);

// Override preset post type
indiekit.set('publication.postTypes', [{
  type: 'note',
  name: 'Journal entry',
  post: {
    path: '_journal/{​yyyy}-{MM}-{dd}-{​slug}.md',
    url: 'journal/{yyyy}/{MM}/{​slug}'
  },
}, {
  type: 'photo',
  name: 'Photograph',
  post: {
    path: '_photos/{​yyyy}-{MM}-{dd}-{​slug}.md',
    url: 'photos/{yyyy}/{MM}/{​slug}'
  },
  media: {
    path: 'media/photos/{​yyyy}/{​filename}',
  }
}]);

Each post type can take the following values:

  • type: The IndieWeb post type.

  • name: The name you use for this post type on your own site. You needn’t specify this value, but some Micropub clients use it in their publishing interfaces.

  • post.path: Where posts should be saved in your repository.

  • post.url: Permalink (the URL path) for posts on your website.

  • media.path: Where media files should be saved in your repository. This applies only to photo, video and audio post types.

  • media.url: Public accessible URL for media files. This can use the same template variables as media.path. If no value is provided, defaults to media.path.

Creating custom paths and URLs

Both path and url values can be customised using the following date tokens:

TokenDescription
yCalendar year, eg 2020
yyyyCalendar year (zero-padded), eg 2020
MMonth number, eg 9
MMMonth number (zero-padded), eg 09
MMMMonth name (abbreviated), eg Sep
MMMMMonth name (wide), eg September
wWeek number, eg 1
wwWeek number (zero-padded), eg 01
DDay of the year, eg 1
DDDDay of the year (zero-padded), eg 001
D60Day of the year (sexageismal), eg 57h
dDay of the month, eg 1
ddDay of the month (zero-padded), eg 01
hHour (12-hour-cycle), eg 1
hhHour (12-hour-cycle, zero-padded), eg 01
HHour (24-hour-cycle), eg 1
HHHour (24-hour-cycle, zero-padded), eg 01
mMinute, eg 1
mmMinute (zero-padded), eg 01
sSecond, eg 1
ssSecond (zero-padded), eg 01
tUNIX epoch seconds, eg 512969520
TUNIX epoch milliseconds, eg 51296952000

The following template tokens are available for post paths and URLs:

TokenDescription
slugProvided slug, slugified name or a 5 character string, eg ycf9o
uuidA random UUID

The following template tokens are available for media file paths and URLs:

TokenDescription
basename5 character alpha-numeric string, eg w9gwi
extFile extension of uploaded file, eg jpg
filenamebasename plus ext, eg w9gwi.jpg
originalnameOriginal name of uploaded file, eg flower.jpg
uuidA random UUID

Creating a post template

A post template is a function that takes post properties received and parsed by the Micropub endpoint and renders them in a given file format, for example, a Markdown file with YAML frontmatter. You can see examples of this function in the Jekyll and Hugo presets:

Plugins

Endpoints

The following endpoints are included by default:

Content stores

Publication presets

Local development

npm start

If you’re developing a new feature, and want the application to automatically restart whenever a file change is detected, use npm run dev.

Testing

npm test

The following environment variables need to be set before running tests:

  • TEST_PUBLICATION_URL
  • TEST_BEARER_TOKEN
  • TEST_BEARER_TOKEN_NOSCOPE

TEST_BEARER_TOKEN and TEST_BEARER_TOKEN_NOSCOPE provide IndieAuth access tokens whose me value matches that set in TEST_PUBLICATION_URL.TEST_BEARER_TOKEN should provide scoped permissions create update delete, whereas TEST_BEARER_TOKEN_NOSCOPE should provide no permissions at all.

Homebrew Access Token is a useful tool for creating access tokens for this purpose.

Credits

Developed by Paul Robert Lloyd.

Thank-you to Aron Carroll for mentoring me during the development of this project. Indiekit is a much better project for his feedback and advice.

Similar projects

Indiekit is inspired by similar projects made by members of the IndieWeb community, all of which you are encouraged to try:

1.0.0-beta.15

7 days ago

1.0.0-beta.16

7 days ago

1.0.0-beta.14

11 days ago

1.0.0-beta.13

16 days ago

1.0.0-beta.12

17 days ago

1.0.0-beta.11

18 days ago

1.0.0-beta.10

18 days ago

1.0.0-beta.9

2 months ago

1.0.0-beta.8

2 months ago

1.0.0-beta.4

10 months ago

1.0.0-beta.5

9 months ago

1.0.0-beta.6

6 months ago

1.0.0-beta.7

6 months ago

1.0.0-beta.3

11 months ago

1.0.0-alpha.16

1 year ago

1.0.0-alpha.18

1 year ago

1.0.0-alpha.17

1 year ago

1.0.0-alpha.13

1 year ago

1.0.0-beta.2

1 year ago

1.0.0-beta.0

1 year ago

1.0.0-beta.1

1 year ago

1.0.0-alpha.9

2 years ago

1.0.0-alpha.8

2 years ago

1.0.0-alpha.7

2 years ago

1.0.0-alpha.6

2 years ago

1.0.0-alpha.12

2 years ago

1.0.0-alpha.11

2 years ago

1.0.0-alpha.5

2 years ago

1.0.0-alpha.0

2 years ago

0.3.0

2 years ago

0.2.0

2 years ago

0.1.4

3 years ago

0.1.3

3 years ago

0.1.1

3 years ago

0.1.0

3 years ago

0.1.0-alpha.23

3 years ago

0.1.0-alpha.22

3 years ago

0.1.0-alpha.21

3 years ago

0.1.0-alpha.18

3 years ago

0.1.0-alpha.15

3 years ago

0.1.0-alpha.14

3 years ago

0.1.0-alpha.12

3 years ago

0.1.0-alpha.11

4 years ago

0.1.0-alpha.10

4 years ago

0.1.0-alpha.9

4 years ago

0.1.0-alpha.8

4 years ago

0.1.0-alpha.6

4 years ago

0.1.0-alpha.5

4 years ago

0.1.0-alpha.4

4 years ago

0.1.0-alpha.3

4 years ago

0.1.0-alpha.2

4 years ago

0.1.0-alpha.1

4 years ago