usite
v3.0.0
Published
Tiny static site generator
Maintainers
Readme
uSite
uSite is a tiny, flexible static website generator designed for programmers.
It consists of a powerful content transformation API and a minimal footprint—less than 90 lines of code can build a fully functional blog. With uSite, you are in full control of your build pipeline, conventions, and site structure.
🚀 Features
- Minimalist: Core logic is lightweight and unopinionated.
- Flexible: Define your own conventions and build steps.
- Programmatic: Use standard JavaScript/TypeScript to generate your site.
- Fast: Built on modern Node.js.
📦 Installation
Install uSite globally via npm:
npm install -g usite🏁 Quick Start
Create a project folder:
mkdir my-website cd my-websiteInitialize a barebones site:
usite initInstall dependencies:
npm installGenerate your site:
usite generate blogThis runs the
blogtask defined in your configuration.
📝 Example: Custom Blog Build
Here is a complete example of how to build a blog using uSite. This script loads settings, processes markdown files, and renders them using Nunjucks templates.
const blog = new uSite();
// 1. Load website settings into the global context
blog.context.global = blog.loadOptions('website.json');
// 2. Load and process post files
const posts = blog.loadContent('content/post/*')
.map((item) => {
const file = item.rawContent;
const [frontMatter, ...rest] = file.split('+++');
const content = rest.join('+++').trim();
const [excerpt] = content.split('<!-- excerpt -->');
const meta = blog.utils.parseOptions(frontMatter);
const slug = meta.slug || blog.utils.generateSlug(meta.title);
return {
meta,
slug,
content: blog.utils.parseMarkdown(content),
excerpt: blog.utils.parseMarkdown(excerpt),
relativeUrl: `post/${slug}`
};
})
.sort((a, b) => b.meta.date.getTime() - a.meta.date.getTime());
// 3. Render individual post pages
posts.emit('template/single.njk', 'www/post/{slug}');
// 4. Group posts for pagination (e.g., 10 posts per page)
const postsPerPage = blog.context.global.postsPerPage || 10;
const postGroups = posts.group((post, index) => {
return Math.floor(index / postsPerPage).toString();
});
// 5. Render pagination pages
postGroups.emit('template/list.njk', 'www/posts/{groupKey}');
// 6. Copy static assets
blog.copy('content/images', 'www/images');
// 7. Create the index page (alias for the first page of posts)
blog.copy('www/posts/0/index.html', 'www/index.html');📚 API Reference
uSite
The main class for the static site generator.
loadOptions(path: string): ObjectReads a file (JSON/YAML), detects the content type, and parses it into a JavaScript object.loadContent<T>(path: string): ContentList<T>Loads files matching the glob pattern and returns aContentListofContentItems.copy(sourcePath: string, destinationPath: string): voidCopies files or directories from source to destination.
ContentItem
Represents a single file loaded by loadContent.
context: Object: Holds internal context and helper functions.filePath: string: The absolute path to the source file.rawContent: string: The raw string content of the file.
ContentList<T>
A collection of content items with transformation methods.
map<U>(fn: (item: T) => U): ContentList<U>Transforms each item in the list. Properties from the original item are copied to the new item, overriding duplicates.emit(templateFn: string, destination: string): voidRenders items using a Nunjucks template and writes them to the destination pattern (e.g.,www/post/{slug}).group(keyFn: (item: T, index: number) => string): ContentMap<T>Groups items by a key returned by the function. Useful for pagination or categories.sort(sortFn: (a: T, b: T) => number): ContentList<T>Sorts the items in the list.count(): numberReturns the number of items.get(i: number): TReturns the item at the specified index.
ContentMap<T>
A collection of grouped ContentLists.
emit(templateFn: string, destination: string): voidRenders each group using a template.filter(predicate: (group: ContentList<T>) => boolean): ContentMap<T>Filters groups based on the predicate.
📄 License
MIT
