Rino.js
Language

Content Navigation:


Published: 2025-04-14T01:21:00.000Z

Project Structure

Rino.js turns HTML, Markdown, CSS, JavaScript, and TypeScript into a static website. Only the folders you use are required.

my-site/
  rino-config.js
  dev.js
  generate.js
  sitemap.js
  feed.js
  backoffice.js
  pages/
  components/
  mds/
  public/
  scripts/export/
  styles/export/
  contents/en/blog/
  content-theme/en/
  i18n/en/

Pages and components

Files in pages/ keep their relative paths:

pages/index.html      -> dist/index.html
pages/about.html      -> dist/about.html
pages/docs/index.html -> dist/docs/index.html

Reusable HTML belongs in components/. Import a component without its .html extension:

<component rino-import="layout/header"></component>

This loads components/layout/header.html. Use rino-tag to wrap the result and copy other attributes to that wrapper:

<component rino-import="button" rino-tag="button" type="button" class="primary"></component>

Use rino-import, not the old rino-path; rino-path is unsupported in v3. Avoid circular component imports.

Markdown files

Reusable Markdown goes in mds/:

<script rino-type="md" rino-import="intro" rino-tag="section"></script>

Public files

Files in public/ are copied directly to the output root:

public/favicon.ico       -> dist/favicon.ico
public/images/photo.webp -> dist/images/photo.webp

Browser scripts and styles

JavaScript and TypeScript in scripts/export/ are bundled into dist/scripts/:

scripts/export/app.js -> dist/scripts/app.js
scripts/export/app.ts -> dist/scripts/app.js

CSS in styles/export/ is resolved and minified into dist/styles/. Local dependencies use standard CSS syntax such as @import "../shared/tokens.css";. Reference generated assets normally:

<link rel="stylesheet" href="/styles/app.css" />
<script src="/scripts/app.js"></script>

Content collections

Markdown collections follow contents/{theme}/{category}/{number-title}.md:

contents/en/blog/1-first-post.md

A file starts with metadata in a JSON comment:

<!--
{
  "title": "Welcome",
  "time": "2026-08-31T10:00:00.000Z",
  "description": "The first post."
}
-->

# Hello

Each theme needs content-theme/{theme}/content.html and content-list.html. Content templates can use {{ content.title }}, {{ content.body }}, {{ content.urlPath }}, and {{ content.time }}. Content list template receive content list data from argument. And we can create pagination system.

dist/contents/en/blog/1-first-post.html
dist/contents-list/en/blog/blog-1.html

Configuration and generated metadata

rino-config.js controls the output directory, development port, site URL, extra sitemap URLs, and locales:

export default {
  dist: "./dist",
  port: 3000,
  site: { url: "https://example.com" },
  sitemap: ["https://example.com/custom-page"],
  i18n: { defaultLocale: "en", locales: ["en", "ko"] },
};

Rino.js can generate sitemap.xml, RSS and Atom feeds from content metadata, and theme-specific feed files. The optional backoffice server provides content and image tools and starts at the next available port from 3100.