npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@yusufaytas/yapress

v0.3.0

Published

A modern, content-first blogging platform built with Next.js and MDX.

Downloads

291

Readme

Yapress

Yapress is a markdown-first publishing engine scaffold built around a strict split between framework-owned code and site-owned content. Built with Next.js 15 and React 19, it provides a modern, type-safe foundation for content-driven websites.

Quick Start

# Install dependencies
npm install

# Start development server
npm run dev

# Build for production
npm run build

# Validate content structure
npm run validate:content

Project Structure

Framework-Owned (Don't modify)

  • src/app/ - Next.js App Router pages and layouts
  • src/components/ - Reusable React components
  • src/lib/ - Core utilities (content loading, SEO, feeds)
  • scripts/ - Build and maintenance scripts

Site-Owned (Customize freely)

  • content/posts/ - Blog posts in Markdown/MDX
  • content/pages/ - Static pages (about, contact, etc.)
  • content/categories.ts - Category registry
  • public/ - Static assets (images, fonts, etc.)
  • site.config.ts - Site configuration and theming

Features

Content Management

  • Markdown/MDX Support - Write content in Markdown with optional React components
  • Frontmatter Metadata - Title, description, date, author, categories, tags, series
  • Draft Posts - Mark posts as drafts to exclude from production builds
  • Related Posts - Automatic discovery based on shared taxonomies

Taxonomies

  • Categories - Required, must be registered in content/categories.ts
  • Tags - Optional, flexible tagging system
  • Tag Registry - Optional metadata in content/tags.ts for custom titles and descriptions
  • Series - Optional, must be registered in content/series.ts to group related posts

SEO & Discovery

  • Canonical URLs - Proper canonical link tags
  • Open Graph - Social media preview cards
  • RSS Feed - Auto-generated at /rss.xml
  • Taxonomy Feeds - Auto-generated feeds for categories and tags under /feeds/
  • Sitemap - Auto-generated sitemap.xml
  • Robots.txt - Configurable robots.txt

Design & UX

  • Theme Presets + Overrides - Start from dark, earth, ocean, or forest, then override tokens, typography, or full CSS
  • Responsive Design - Mobile-optimized layouts
  • Social Sharing - Share buttons for Twitter, LinkedIn, Reddit, email, copy link, and native share where supported
  • Pagination - Configurable posts per page
  • Search - Client-side content search
  • Date Archives - Month-based archive pages such as /2026/04
  • Media Pages - Attachment-style pages for referenced local images

Developer Experience

  • TypeScript - Full type safety
  • Content Validation - Validate frontmatter and category references
  • WordPress Import - Migrate from WordPress XML exports
  • Clean Builds - Automated cleanup scripts

Configuration

Edit site.config.ts to customize your site:

const siteConfig: SiteConfig = {
  title: "Your Site Name",
  tagline: "Your tagline",
  description: "Site description for SEO",
  siteUrl: "https://yourdomain.com",
  language: "en",
  author: "Your Name",
  url: {
    postPermalink: {
      style: "slug" // or "prefix-slug", "year-month-slug", "prefix-year-month-slug"
    },
    redirects: [
      { from: "/old-path", to: "/new-path" }
    ]
  },
  theme: {
    preset: "dark",
    typography: {
      sans: '"IBM Plex Sans", var(--font-sans-base), sans-serif',
      serif: '"Fraunces", var(--font-serif-base), serif'
    },
    tokens: {
      accent: "#f97316",
      link: "#c2410c",
      heroTitleSize: "clamp(3rem, 10vw, 7rem)",
      h4Size: "1.2rem",
      maxWidth: "78rem"
    },
    customCssHref: "/theme.css"
  },
  postsPerPage: 5,
  excerptLength: 180,
  // ... more options
};

Theme Options

  • dark - Clean dark theme with high contrast
  • earth - Warm, earthy tones
  • ocean - Cool blue palette
  • forest - Natural green theme

Theming Strategy

Use site.config.ts for structured overrides:

  • theme.preset picks the starting palette
  • theme.tokens overrides CSS variables such as colors, links, heading sizes, shadows, radius, width, and base type scale
  • theme.typography overrides the body, heading, and monospace font stacks
  • theme.customCssHref loads a site-owned stylesheet after the framework CSS so selectors can be fully overridden

Example public/theme.css:

:root {
  --accent: #2563eb;
  --link: #1d4ed8;
  --radius-lg: 2rem;
  --hero-title-size: clamp(3rem, 8vw, 5.5rem);
}

.brand {
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.article h1 {
  font-size: clamp(3rem, 8vw, 5rem);
}

The practical split is:

  • Use theme.tokens for system-level design values
  • Use theme.typography for font families
  • Use public/theme.css when you want full selector-level control without forking framework files

URL Strategy

Use site.config.ts to control public URL behavior:

  • url.postPermalink.style controls canonical post URLs
  • url.redirects is deployment metadata you can use outside YaPress if your host supports redirects
  • aliases can be used to record legacy URLs during migration, but YaPress does not serve redirects for them

Supported post permalink styles:

  • slug -> /<slug>
  • prefix-slug -> /blog/<slug> using url.postPermalink.prefix
  • year-month-slug -> /<year>/<month>/<slug>
  • prefix-year-month-slug -> /blog/<year>/<month>/<slug>

Other public URL features:

  • Month archives are generated at /<year>/<month>
  • Category feeds are generated at /feeds/categories/<slug>.xml
  • Tag feeds are generated at /feeds/tags/<slug>.xml
  • Search is available at /search with shareable query URLs like /search?q=markdown
  • Referenced local images get attachment-style pages under /media/...

Content Guidelines

Post Frontmatter

---
title: "Your Post Title"
description: "Brief description for SEO"
date: "2026-04-09"
author: "Author Name"
language: "tr"
locale: "tr"
categories: ["category-slug"]
tags: ["tag1", "tag2"]
series:
  - slug: series-name
aliases: ["/old-post-path"]
draft: false
---

Your content here...

Use language for the post's content language and locale when you need locale-specific casing, slug normalization, and date formatting. For example, Turkish posts should normally use language: "tr" and locale: "tr" so I/İ casing behaves correctly.

Image Grids

Create responsive image galleries with built-in grid layouts:

<!-- 3 columns (default) -->
<div className="image-grid">
  <img src="/image1.jpg" alt="Description" />
  <img src="/image2.jpg" alt="Description" />
  <img src="/image3.jpg" alt="Description" />
</div>

<!-- 2 columns -->
<div className="image-grid-2">
  <img src="/image1.jpg" alt="Description" />
  <img src="/image2.jpg" alt="Description" />
</div>

<!-- 4 or 5 columns also available -->
<div className="image-grid-4">...</div>
<div className="image-grid-5">...</div>

Features:

  • Responsive (auto-fit on mobile, fixed columns on desktop 64rem+)
  • Consistent styling with rounded corners and borders
  • Equal height images with object-fit: cover
  • Available classes: image-grid (3 col), image-grid-2, image-grid-4, image-grid-5

Category Registration

Before using a category, register it in content/categories.ts:

export const categories = [
  {
    slug: "tutorials",
    name: "Tutorials",
    description: "Step-by-step guides"
  }
];

Series Registration

Before using a series, register it in content/series.ts:

export const series = [
  {
    slug: "getting-started",
    title: "Getting Started",
    description: "Introduction to YaPress and basic setup guides"
  }
];

Available Scripts

  • npm run dev - Start development server on http://localhost:3000
  • npm run build - Build static site for production
  • npm run start - Preview production build locally
  • npm run lint - Run ESLint
  • npm run validate:content - Validate content structure and references
  • npm run import:wordpress - Import content from WordPress XML export

Updating from Upstream

YaPress is designed to be forked and customized. To pull framework updates while preserving your content:

Setup Upstream Remote

# Add the original YaPress repo as upstream (one-time setup)
git remote add upstream https://github.com/yusufaytas/yapress.git

# Fetch upstream changes
git fetch upstream

# Merge upstream changes into your branch
git merge upstream/main

Merge Strategy

The .gitattributes file automatically handles merge conflicts:

  • Site-owned files (your content) - Always keeps your local version

    • content/** - Your posts, pages, categories, series
    • site.config.ts - Your site configuration
    • public/** - Your static assets
  • Framework-owned files - Always takes upstream version

    • src/** - Framework code (app, components, lib)
    • scripts/** - Build and utility scripts
    • Config files - Next.js, TypeScript, PostCSS configs

Note: If you've added custom npm packages, remove the package.json merge=theirs line from .gitattributes to manually merge dependencies.

Deployment

YaPress generates a static site that can be deployed to any static hosting provider:

  1. Run npm run build to generate the static site
  2. Deploy the out/ directory to your hosting provider
  3. Compatible with: Vercel, Netlify, GitHub Pages, Cloudflare Pages, AWS S3, etc.

Tech Stack

  • Framework: Next.js 15 (App Router, Static Export)
  • UI: React 19, Tailwind CSS 4
  • Content: MDX, gray-matter, remark-gfm
  • Language: TypeScript 5
  • Testing: Vitest

Plugins

YaPress supports a plugin system for extending functionality without modifying framework code.

Available Official Plugins

Installing a Plugin

# Quick install with configuration setup
npm run enable-plugin subscription

# Or manual install
npm install @yusufaytas/yapress-plugin-subscription

The enable-plugin script will:

  1. Install the plugin package from npm
  2. Create a configuration file at plugins/<plugin-name>/config.ts
  3. Register the plugin in plugins.config.ts

Configuring a Plugin

After installation, edit the plugin configuration file:

// plugins/subscription/config.ts
import type { SubscriptionConfig } from '@yusufaytas/yapress-plugin-subscription';

export const config: SubscriptionConfig = {
  enabled: true,
  provider: 'mailchimp',
  apiKey: process.env.MAILCHIMP_API_KEY!,
  listId: process.env.MAILCHIMP_LIST_ID!,
  
  placement: {
    afterPost: true,  // Show after blog posts
    popup: false,     // Disable popup
    footer: true,     // Show in footer
  },
  
  ui: {
    title: "Subscribe to our newsletter",
    description: "Get the latest posts delivered right to your inbox.",
    buttonText: "Subscribe",
  }
};

Add any required environment variables to .env.local:

# .env.local
MAILCHIMP_API_KEY=your-api-key-here
MAILCHIMP_LIST_ID=your-list-id-here

Plugin Architecture

Plugins are npm packages that integrate with YaPress through a standardized interface:

  • Components: Inject UI at predefined slots (header, footer, before/after posts, etc.)
  • Configuration: Type-safe, site-owned configuration with environment variable support
  • Static-First: Plugins render to static HTML where possible, with optional client-side interactivity

When multiple plugins render into the same slot, YaPress sorts them by ascending order. Plugins with the same order keep their registration order from plugins.config.ts.

Plugin CSS should stay inside the plugin's own markup and inherit the host theme via CSS variables. Avoid relying on app-owned layout selectors or assumptions about surrounding containers beyond the slot you were given.

Creating Custom Plugins

You can create your own plugins by following the plugin interface:

// my-plugin/plugin.ts
import type { Plugin } from '@yusufaytas/yapress-core';

export function createMyPlugin(config: MyConfig): Plugin {
  return {
    name: 'my-plugin',
    version: '1.0.0',
    enabled: config.enabled,
    order: 0,
    components: {
      afterPost: [MyComponent],  // Inject after posts
      footerEnd: [MyFooter],     // Inject in footer
    },
  };
}

See the Plugin Development Guide for more details.

License

This project structure is designed to be forked and customized for your own site.