A minimal static site generator written in Rust • ink • eternal
- Minimal Design: Clean, typography-focused design
- Markdown Support: Write posts in Markdown with frontmatter
- Illuminated Initials: AI-generated decorative initials (requires OpenAI API)
- IPFS Support: Pin your site to IPFS for decentralized hosting
- Backlinks: Automatic detection of links between posts
- Responsive: Mobile-friendly design
- Fast: Written in Rust for performance
- Folded Annotations: Add per-paragraph related links that fold open on click
git clone <repository-url>
cd scribe
cargo install --path .cargo install scribe- Create a new site directory:
mkdir my-site && cd my-site
scribe- This will create the default directory structure:
my-site/
├── config.json
├── posts/
└── dist/
- Add your posts to the
posts/directory as Markdown files:
---
title: My First Post
date: 2024-01-20T10:00:00Z
excerpt: A brief description of the post
---
Your post content here...- Generate the site:
scribe- The generated site will be in the
dist/directory.
Scribe can pin your generated site to IPFS for decentralized hosting:
- First, make sure you have IPFS installed and running:
# Install IPFS (if not already installed)
# Visit https://ipfs.io/docs/install/ for installation instructions
# Start IPFS daemon
ipfs daemon- Generate your site and pin it to IPFS:
# Generate the site
scribe generate
# Pin to IPFS
scribe pin
# Pin with custom options
scribe pin --dist dist --name "My Blog v1.0" --ipfs-api http://127.0.0.1:5001- Your site will be available via IPFS gateways:
- IPFS Hash:
QmX...(returned by the pin command) - Public Gateway:
https://ipfs.io/ipfs/QmX... - Local Gateway:
http://127.0.0.1:8080/ipfs/QmX...
- IPFS Hash:
IPFS Pin Options:
--dist <DIR>: Directory to pin (default: dist)--ipfs-api <URL>: IPFS API endpoint (default: http://127.0.0.1:5001)--name <NAME>: Optional pin name/description--recursive: Pin recursively (default: true)
The config.json file allows you to customize your site:
{
"title": "My Site",
"description": "A site about technology and design",
"author": "Your Name",
"url": "https://example.com",
"posts_dir": "posts",
"output_dir": "dist",
"openai_api_key": "your-api-key-here",
"theme": {
"primary_color": "#f5f5f5",
"background_color": "#0a0a0a",
"text_color": "#f5f5f5",
"accent_color": "#8b8b8b"
}
}Generate: Build the static site
scribe generate [OPTIONS]-c, --config <FILE>: Specify config file (default: config.json)
Serve: Start local development server
scribe serve [OPTIONS]-d, --dist <DIR>: Directory to serve (default: dist)-p, --port <PORT>: Port to serve on (default: 3007)--host <HOST>: Host to bind to (default: 127.0.0.1)
Create: Create a new blog project
scribe create <DIRECTORY>Initials: Generate illuminated initials
scribe initials [OPTIONS]-l, --letters <LETTERS>: Letters to generate (e.g., "ABC" or "A,B,C")-c, --config <FILE>: Config file (default: config.json)-o, --output <DIR>: Output directory (default: initials)
Pin: Pin site to IPFS
scribe pin [OPTIONS]-d, --dist <DIR>: Directory to pin (default: dist)--ipfs-api <URL>: IPFS API endpoint (default: http://127.0.0.1:5001)-n, --name <NAME>: Pin name/description-r, --recursive: Pin recursively (default: true)
Global Options:
-h, --help: Show help-V, --version: Show version
site/
├── config.json # Site configuration
├── posts/ # Markdown posts
│ ├── post-1.md
│ └── post-2.md
└── dist/ # Generated site
├── index.html
├── style.css
├── initials/ # Generated illuminated initials
└── post-slug/
└── index.html
Posts are written in Markdown with optional YAML frontmatter:
---
title: Post Title
date: 2024-01-20T10:00:00Z
excerpt: Brief description of the post
---
Your post content here...
## Subheadings
More content...You can attach related links to the previous paragraph or list. They are hidden by default and revealed with a small chevron on hover/click. They render as minimal previews: title (full-link) and an optional description line.
Block-style (fenced) annotations:
Some paragraph that mentions a topic.
```links
- [Great explainer](https://example.com/explainer) - Concise overview
- https://example.com/paper — Research paper
Title — https://example.com/deep-dive — Longer discussion
[Spec](https://www.w3.org/) : W3C spec
List-style annotations using a `Links:` marker:
```markdown
Some paragraph that mentions a topic.
Links:
- [Great explainer](https://example.com/explainer) - Concise overview
- https://example.com/paper — Research paper
Supported syntaxes inside annotations:
- Title - Optional description
- Title — https://domain.tld/path — Optional description
- https://domain.tld/path — Optional description
Rendering result (each item):
Title (https://domain.tld/path)
Optional description
cargo buildcargo testcargo runMIT License