Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,24 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.4.6] - 2026-03-06
## [1.5.0] - 2026-03-06

### Added

- Configurable characters per page in reader mode via `reader.charsPerPage` in `config.yaml`. Users may not need to change this at all. But the idea is to keep it configurable in case there are some visual artifacts in the reader mode. This is responsible for splitting the pages for the reader mode.
- Configurable pagination parameters via `reader.pagination` in `config.yaml` with `columnWidth`, `columnHeight`, `lineHeight`, `avgCharWidth`, and `safetyMargin` options.

### Changed

- **Breaking**: Rewrote pagination algorithm from line-based to character-based for more accurate page breaks.
- CSS columns now allow content to break inside blocks (`break-inside: auto`) for natural text flow.
- Theme scale overrides (`ui.theme.overrides.font.scale`) now affect pagination calculations.

### Fixed

- Reader mode now correctly paginates lists, code blocks, and blockquotes instead of truncating them mid-element.
- Body of Work page now appears on first deploy when using a custom slug; reliably.
- Theme config path now correctly reads `ui.theme.preset` instead of top-level `theme`.
- Reader mode no longer overflows or cuts off content at column boundaries.
- Blockquotes and lists split mid-content when needed instead of jumping entirely to next column.
- Body of Work page now appears on first deploy when using a custom slug.

## [1.4.5] - 2026-03-05

Expand Down
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

> An ode to those who love the craft, an ode to the old internet, an ode to a time before numbers and figures dominated writing, an ode to a time where readers remembered their favourite writers, and an ode to the hope that all of it is still present, somewhere.

Ode is for writers who want to publish in an aesthetically pleasing website, who ignore the bells and whistles of the modern internet, and who want to create a better experience for their readers. It is opinionated, minimal, and easy to use, guided by its own [ethos](https://github.com/DeepanshKhurana/ode/blob/main/ETHOS.md).
Ode is for writers who want to publish in an aesthetically pleasing website, who ignore the bells and whistles of the modern internet, and who want to create a better experience for their readers. It is opinionated, minimal, and easy to use, guided by its own [ethos](https://github.com/DeepanshKhurana/ode/blob/main/docs/ETHOS.md).

## Inspiration

Expand All @@ -22,16 +22,17 @@ You can find a live demo of the app [here](https://demo.ode.dimwit.me/).
## Documentation

- **[README.md](https://github.com/DeepanshKhurana/ode/blob/main/README.md)**: Overview, features, and getting started
- **[ETHOS.md](https://github.com/DeepanshKhurana/ode/blob/main/ETHOS.md)**: Core principles and philosophy behind Ode
- **[WRITING.md](https://github.com/DeepanshKhurana/ode/blob/main/WRITING.md)**: Content repository, auto-deployment, and GitHub Actions
- **[THEMING.md](https://github.com/DeepanshKhurana/ode/blob/main/THEMING.md)**: Theme presets, customization, local fonts, and visual examples
- **[CONFIGURATION.md](https://github.com/DeepanshKhurana/ode/blob/main/docs/CONFIGURATION.md)**: Full config.yaml reference
- **[ETHOS.md](https://github.com/DeepanshKhurana/ode/blob/main/docs/ETHOS.md)**: Core principles and philosophy behind Ode
- **[WRITING.md](https://github.com/DeepanshKhurana/ode/blob/main/docs/WRITING.md)**: Content repository, auto-deployment, and GitHub Actions
- **[THEMING.md](https://github.com/DeepanshKhurana/ode/blob/main/docs/THEMING.md)**: Theme presets, customization, local fonts, and visual examples
- **[CHANGELOG.md](https://github.com/DeepanshKhurana/ode/blob/main/CHANGELOG.md)**: Version history and release notes
- **[REFERENCES.md](https://github.com/DeepanshKhurana/ode/blob/main/REFERENCES.md)**: Credits and inspirations
- **[REFERENCES.md](https://github.com/DeepanshKhurana/ode/blob/main/docs/REFERENCES.md)**: Credits and inspirations

## Screenshots

> [!NOTE]
> For theme-specific screenshots, see [THEMING.md](https://github.com/DeepanshKhurana/ode/blob/main/THEMING.md)
> For theme-specific screenshots, see [THEMING.md](https://github.com/DeepanshKhurana/ode/blob/main/docs/THEMING.md)

### Homepage
![Homepage - Light Mode](.github/media/homepage_light.png)
Expand Down Expand Up @@ -70,7 +71,7 @@ https://github.com/user-attachments/assets/222af674-11f0-4b5a-8232-a31aca8a61b1
## Getting Started

> [!TIP]
> For detailed notes on how to setup a **content repository** with sync, look into the [WRITING.md](https://github.com/DeepanshKhurana/ode/blob/main/WRITING.md)
> For detailed notes on how to setup a **content repository** with sync, look into the [WRITING.md](https://github.com/DeepanshKhurana/ode/blob/main/docs/WRITING.md)

### Docker Compose (Recommended)

Expand Down Expand Up @@ -141,7 +142,7 @@ If you are coming from WordPress, you can use the awesome [lonekorean/wordpress-
## Writing Content

> [!TIP]
> A longer guide is in [WRITING.md](https://github.com/DeepanshKhurana/ode/blob/main/WRITING.md)
> A longer guide is in [WRITING.md](https://github.com/DeepanshKhurana/ode/blob/main/docs/WRITING.md)

### Pieces

Expand Down Expand Up @@ -177,7 +178,7 @@ Tell everyone everything!
## Theming

> [!NOTE]
> For complete theming documentation, including all available presets, customization options, and local font support, see [THEMING.md](https://github.com/DeepanshKhurana/ode/blob/main/THEMING.md)
> For complete theming documentation, including all available presets, customization options, and local font support, see [THEMING.md](https://github.com/DeepanshKhurana/ode/blob/main/docs/THEMING.md)

Ode comes with 10 built-in themes that you can use and customize. Switch between presets, override colors and fonts, or build your own theme from scratch.

Expand Down
8 changes: 7 additions & 1 deletion build/defaults/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,13 @@ exclude:
pieces:
-
reader:
charsPerPage: 2200
columns: 2
pagination:
columnWidth: 330
columnHeight: 540
lineHeight: 24
avgCharWidth: 8
safetyMargin: 0.85
order:
default: descending
rss:
Expand Down
18 changes: 16 additions & 2 deletions build/paginate-pieces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import fs from 'fs';
import path from 'path';
import fm from "front-matter";
import yaml from 'js-yaml';
import { chunkContent } from './utils/markdown-chunker';
import { chunkContent, getCharsPerPage, PaginationConfig } from './utils/markdown-chunker';
import { loadTheme } from './utils/theme-loader';

const publicDir = path.join(__dirname, '..', 'public');
const piecesPath = path.join(publicDir, 'content', 'pieces');
Expand All @@ -12,7 +13,20 @@ const configPath = path.join(publicDir, 'config.yaml');

const configRaw = fs.readFileSync(configPath, 'utf-8');
const config = yaml.load(configRaw) as any;
const CHARS_PER_PAGE = config?.reader?.charsPerPage ?? 2200;

const themeName = config?.ui?.theme?.preset || config?.theme || 'journal';
const theme = loadTheme(themeName);
const themeScaleOverride = config?.ui?.theme?.overrides?.font?.scale;
const themeScale = themeScaleOverride ?? theme?.font?.scale ?? 1;

const paginationConfig: PaginationConfig = {
columns: config?.reader?.columns ?? 2,
pagination: config?.reader?.pagination,
};

const CHARS_PER_PAGE = getCharsPerPage(paginationConfig, themeScale);

console.log(`[pagination]: theme=${themeName}, scale=${themeScale}, charsPerPage=${CHARS_PER_PAGE}`);

type PiecePage = {
pieceSlug: string;
Expand Down
Loading