Skip to content

daryablog/daryablog.github.io

Repository files navigation

Darya banner

Stack: Vite, React, TypeScript Hosting: GitHub Pages Status: exclusive, single author CI status License: see repository

daryablog.github.io


Darya

Darya is a private, content-first publishing engine built around a single idea: writing a post should be a content change, not a code change. A Markdown file is dropped into the content folder, pushed, and it is live within minutes. There is no database, no external CMS, and no build step that regenerates a manifest by hand.

The name comes from the Persian word for sea, chosen for a platform meant to feel calm, deliberate, and easy to navigate. This is a closed, exclusive publication with a single author. It is not open for contributions, issues, or pull requests, and this document exists purely to describe how the system is built.


Table of Contents


Design Philosophy

Every visual decision in Darya answers to three principles, carried directly from the site's own design system.

Principle What it means in practice
Attention An element that does not clarify something gets removed. No decoration for its own sake.
Honesty Surfaces are flat, never deceptive. No gradient exists to mask a weak design decision.
Silence Whitespace is part of the message. Low density, controlled contrast, a single action color.

The result is a reading surface designed to disappear, so the writing is the only thing that holds attention.


Color System

Darya's palette is built from five roles rather than a list of pleasant colors: a neutral canvas for reading, an ink for content, and exactly one action color used to direct attention. Gold appears only as a secondary accent and never competes with the primary color. There are no gradients anywhere in the system; every surface is flat and consistent across both light and dark mode.

Color system: Void, Panel, Ink, Rose, and Gold tokens in light and dark mode

Token Role Light Dark Usage
Void Primary background #faf9f6 #080810 The neutral canvas. Deliberately ivory rather than pure white, so long reading sessions stay comfortable.
Panel Secondary surface #f2f0ea #0d0d18 Card and image backgrounds, separated from the page without a hard border.
Ink Primary text #232019 #f0eef8 Warm charcoal rather than pure black, for sufficient contrast without eye fatigue.
Rose Brand and action color #b3312b #d85a50 The only action color on the site: active links, the primary button, article titles, attention markers. Used sparingly and precisely.
Gold Secondary accent #a9822f #c9a96e Reserved for second-tier emphasis such as ruled quotes and marginal notes, never as a section's primary color.

Typography

Two type families, two distinct jobs. Noto Naskh Arabic carries headlines and the emotional beats of the text, where rhythm and character outweigh rapid legibility. Vazirmatn carries body copy, navigation, and interface elements, set in a light weight for long paragraphs so the eye does not tire.

Role Sample Size Typeface
Hero یادداشت‌هایی درباره هوش مصنوعی clamp(3rem, 7.5vw, 6.5rem) Noto Naskh Arabic · 400
Page H1 این‌جا برای نگاه‌کردن آهسته ساخته شده است clamp(2.4rem, 6vw, 4.4rem) Noto Naskh Arabic · 400
Section H2 چرا این‌جا نوشته می‌شود clamp(1.35rem, 3.5vw, 1.7rem) Noto Naskh Arabic · 500
Body copy نوشتن، شکلی از توجه‌کردن است clamp(0.95rem, 2vw, 1.05rem) Vazirmatn · 300
Label / metadata یک دفترچه شخصی · از ۱۴۰۳ 0.72rem – 0.85rem Vazirmatn · 300–400

Motion follows the same restraint. Most transitions use cubic-bezier(0.16, 1, 0.3, 1), with a gentler overshoot curve reserved for small interactions like buttons. No animation is added purely for spectacle; every motion either aids legibility or confirms an action.


Architecture

Darya is organized into four layers, each with a single responsibility. Content flows downward through parsing and typing before it ever reaches a rendered page, which keeps the UI layer entirely free of parsing or fetching logic.

Four layer architecture: Content, Services, Models, UI

Layer 1, Content. Plain text: site configuration, Markdown posts, and cover images. Nothing here is generated, and nothing here requires a database.

Layer 2, Services. Domain logic that turns raw text into structured data: a content service acting as repository and cache, a frontmatter parser for post metadata, a Markdown parser that converts the post body into typed blocks, and a Jalali date formatter that handles both calendar systems and estimated read time.

Layer 3, Models. Typed, immutable domain objects, namely Post and SiteConfig, giving the rest of the application a stable shape to work with regardless of how the underlying text was authored.

Layer 4, UI. Pages and components that consume typed data exclusively. No component parses Markdown, fetches raw files, or manipulates the DOM directly.


Content Pipeline

This is the concrete path a single post takes from a saved file to a rendered page.

Five step content pipeline from Markdown file to rendered page

  1. Markdown file. A post is authored as a single .md file with a frontmatter header and a Markdown body.
  2. Vite glob. The file is discovered automatically at build time through import.meta.glob, with nothing manually imported or registered.
  3. Parse. The frontmatter parser and Markdown parser convert raw text into structured blocks.
  4. Post instance. The parsed data becomes a typed, immutable Post object, sorted by date alongside the rest of the catalog.
  5. Rendered. The post appears both as a card on the listing page and as a full post page, with zero manual wiring.

Adding a post means dropping a file into the posts folder and pushing. There is no posts.json to regenerate, no route to register, and no import statement to add anywhere in the codebase.


Publishing Workflow

A first class admin interface lives at /admin, authenticated through GitHub OAuth, sharing the same build and the same design system as the public site rather than existing as a separate tool.

Publishing workflow from sign in to live deployment

Cover images are named after the post's slug rather than a random suffix, so re-uploading a cover always overwrites the same file instead of leaving orphaned copies behind. A background cleanup sweep runs after every save or delete, comparing each post's declared cover against everything actually committed, and removes anything left unreferenced.


Testing

A small, fast test suite backs the parts of the system that are easiest to break silently: the shape of the content itself, and the handful of places that write directly into the page rather than rendering through a component.

  • Unit tests (Vitest, jsdom, Testing Library) cover the document-head logic in isolation, asserting that page title, description, and related tags are written correctly and cleaned up correctly as a reader moves between routes.
  • Content integrity tests run the same ContentService the app uses at runtime and assert on the result: every post has a unique slug, a valid date, a non-empty title and excerpt, and a cover image that actually exists on disk.

npm run test runs the suite once; npm run test:watch keeps it running while editing. npm run verify chains lint, tests, and a production build together, the same sequence CI runs.


Tech Stack

Concern Choice
Build tool Vite
UI layer React 18
Language TypeScript, strict mode
Routing React Router, client side, with a GitHub Pages 404 redirect fallback
Content format Markdown with frontmatter
Content discovery import.meta.glob at build time
Date handling Jalali and Gregorian calendar formatting
Testing Vitest, jsdom, Testing Library
Admin authentication GitHub OAuth
Admin persistence GitHub REST API, direct commits
Hosting GitHub Pages
CI/CD GitHub Actions

Project Structure

daryablog.github.io/
├── src/
│   ├── content/
│   │   ├── site.json              # site wide configuration
│   │   └── posts/                 # one .md file per post
│   ├── services/
│   │   ├── ContentService.*
│   │   ├── FrontmatterParser.*
│   │   ├── MarkdownParser.*
│   │   └── JalaliDateFormatter.*
│   ├── models/
│   │   ├── Post.*
│   │   └── SiteConfig.*
│   ├── components/                # PostCard, MarkdownBody, SiteNav, and friends
│   ├── admin/
│   │   ├── components/            # editor UI, image fields
│   │   ├── context/                # auth and toast providers
│   │   ├── lib/                    # GitHub API, auth, image processing, media cleanup
│   │   └── pages/                  # login, post list, post editor, settings
│   ├── pages/                     # HomePage, PostPage, AboutPage
│   └── test/
│       └── setup.*                # jsdom + Testing Library setup
└── public/
    └── images/                    # post cover images

Continuous Integration

Every push to main runs through a single pipeline: install, lint with zero warnings tolerated, run tests, type-check, build, then deploy to GitHub Pages. Nothing reaches production without passing the same checks that run locally.

checkout → install (npm ci) → lint → test → type-check → build → upload → deploy

Localization

Persian is treated as a first class concern rather than an afterthought. The interface reads right to left throughout, and dates are rendered using the Jalali calendar alongside standard formatting, reflecting how both calendar systems coexist in everyday Persian language contexts.


Key Design Principles

  • Content as code. Posts are plain text, reviewed and versioned exactly like source code.
  • No hidden state. No database, no generated manifest that can silently drift from the actual content.
  • Typed boundaries. Once content passes through the services layer, every downstream consumer works with typed, predictable objects instead of raw strings.
  • Dumb components on purpose. UI components render data. They do not fetch it, parse it, or transform it.
  • One action color. Rose is the only color used to direct attention, anywhere in the interface.
  • Localization is not an afterthought. Calendar and date formatting are handled centrally rather than duplicated across components.

Darya is a private, single author publication. This repository is not open for external contributions.

About

Darya is a lightweight, content-first blogging platform built around a simple idea: writing a post should be a content change, not a code change.

Topics

Resources

License

Stars

13 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors