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
pathhas theymloryamlextension, the object will be stringified as YAML. - If the
pathhas thejsonextension, 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_pluginsfolderdeno task new archetype: Creates the boilerplate code for a custom archetype in the_archetypesfolder.deno task new cms: Creates the_cms.tsfile to use LumeCMS and updates thedeno.jsonfile to addlume/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.