Archetypes

Scripts to create a templates for new content.

Archetypes are scripts that edit or create new files in your source directory with some preconfigured content. A typical example are posts on a blog: instead of creating a markdown file from scratch every time you want to create a new post, you can create and run an archetype to do this job for you.

Archetypes in Lume are JavaScript or TypeScript files, stored in the _archetypes directory that default export a function returning the configuration of the file that is going to be created. For example:

// _archetypes/example.js

export default function () {
  return {
    path: "/pages/example.md",
    content: "Content of the file",
  };
}

This archetype creates the file /pages/example.md inside your src directory with the content Content of the file. The archetype filename is example.js, so the name of the archetype is example. To execute it just run deno task new example (or simply lume new example if you're using the Lume CLI).

Running archetypes

As you can see, to run an archetype, just run deno task new [archetype_name]. The archetype name is the file name (without extension) and Lume will search that file in the _archetypes directory, inside the src folder.

It's possible to run other archetypes using a relative path. In this case you need to include the path of the file including the extension. For example:

deno task new ./my-templates/new-post.ts

Use an URL to run a remote archetype:

deno task new https://example.com/my-templates/new-post.ts

Content

The content variable can be a string, a Uint8Array (for binary files) or an object. If the content is an object, it will be converted to a string depending on the extension of the path:

  • If the path has the yml or yaml extension, the object will be stringified as YAML.
  • If the path has the json extension, the object will be stringified as JSON.
  • For other extensions, the object will be converted to frontmatter + text.

This is an example of YAML conversion:

export default function () {
  return {
    path: "/pages/example.yml",
    content: {
      title: "Title content",
      content: "Page content",
    },
  };
}
title: Title content
content: Page content

Same example, but for JSON conversion:

export default function () {
  return {
    path: "/pages/example.json",
    content: {
      title: "Title content",
      content: "Page content",
    },
  };
}
{
  "title": "Title content",
  "content": "Page content",
}

Same example, but for any other extension (for example, md):

export default function () {
  return {
    path: "/pages/example.md",
    content: {
      title: "Title content",
      content: "Page content",
    },
  };
}
---
title: Title content
---

Page content

Passing arguments

Arguments allow passing variables to the archetype to configure how the new content is created. For example, if we want to create new pages based on the provided title:

// _archetypes/page.ts

export default function (title: string) {
  const slug = title.replace(/\s+/g, "-").toLowerCase();

  return {
    path: `/pages/${slug}.md`,
    content: {
      title: title,
      content: "Page content",
    },
  };
}

This function uses the title argument to generate the final path and the content. Now you can run deno task lume new page "My first page" (or lume new page "My first page" if you're using the Lume CLI), and the new /pages/my-first-page.md file will be created. Any extra arguments passed to the CLI command will be passed to the archetype's function.

Multiple files

It's possible to generate multiple files from the same archetype. To do that, use a generator to yield all files. In the following example, the archetype creates a new section in the site with several pages and a _data.yml file:

// _archetypes/section.ts

export default function* (title: string) {
  const slug = title.replace(/\s+/g, "-").toLowerCase();

  // Create the shared data
  yield {
    path: `/pages/${slug}/_data.yml`,
    content: {
      layout: "section.vto",
      section_title: title,
    },
  };

  // Create 3 more pages
  const pages = [1, 2, 3];
  for (const page of pages) {
    yield {
      path: `/pages/${slug}/${page}.md`,
      content: {
        title: `Page ${page}`,
        content: "Write the content here",
      },
    };
  }
}

As you can see, Lume's archetypes are simple but flexible and powerful. And because they are just plain JavaScript/TypeScript files, it's possible to reuse them. For example, you can create an archetype that imports other archetypes.

base option

By default, the paths of the generated files are relative to the src folder. Use the property base to change the base path to the root folder (the same folder of _config.ts and deno.json files).

export default function () {
  return {
    path: "example.txt",
    base: "root",
    content: "Content of the file",
  };
}

Edit existing files

Archetypes can be used to edit existing files. To do that, use a function in the content property. Lume will execute this function passing the existing content in the first argument. For example, to edit the deno.json file to add a new import:

export default function () {
  return {
    path: "deno.json",
    base: "root", // to save the file in the root directory instead of src
    content(json) {
      json.imports["new-import/"] = "https://example.com/";
      return json;
    },
  };
}

When running this archetype, the deno.json file is read, and the parsed JSON is passed to the content function. If the file doesn't exist, the argument is undefined.

Built-in archetypes

Lume provides the following archetypes out of the box:

  • deno task new plugin: Creates the boilerplate code for a custom plugin in the _plugins folder
  • deno task new archetype: Creates the boilerplate code for a custom archetype in the _archetypes folder.
  • deno task new cms: Creates the _cms.ts file to use LumeCMS and updates the deno.json file to add lume/cms/ to the import map.

Defining archetypes in the _config file

Instead of using the _archetypes folder, it's possible to add new archetypes in the _config.ts using the site.archetype() function. This is useful for plugins or themes to register their own archetypes.

// Use a file path or URL
site.archetype("post", "_archetypes/post.ts");

// Use a function:
site.archetype("post", () => {
  const name = prompt("Name of the post");
  return {
    path: `/posts/${name}.md`,
    content: "Start typing...",
  };
});

Run deno task new post and the archetype is executed.