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

@markuxt/markuxt

v0.1.32

Published

A Markdown-first academic portal framework for laboratories, research groups, and knowledge communities, powered by Nuxt.

Readme

Markuxt

A Markdown-first academic portal framework for laboratories, research groups, and knowledge communities, powered by Nuxt 3.

Markuxt provides a complete theme layer — layouts, pages, components, content transformers, and i18n — so that consuming sites only need to provide content and configuration.

Features

  • Markdown-driven content — Pages, members, publications, projects, positions, and news are all authored in Markdown with YAML frontmatter.
  • Configurable navigation — Define which pages appear in the header, footer, and route guard via a single navigation array in appConfig.
  • Configurable member categories — Define the member groups (e.g. Faculty / Students / Alumni) in appConfig; authors reference them from each member's category: frontmatter.
  • Internationalization — Built-in i18n support via @nuxtjs/i18n. Consuming sites provide their own locale files.
  • Design system — CSS custom properties for colors, spacing, typography, and more. Easy to override.
  • Content transformers — Binary assets (images, videos) placed next to Markdown files are automatically synced to public/ for static serving.
  • Mermaid diagrams — First-class support with proper font loading and overflow handling.
  • LaTeX / KaTeX — Math rendering via remark-math + rehype-katex.
  • 404 page — Custom error page with header and footer preserved.
  • Dark / Light mode — Built-in toggle button in the header. Defaults to the OS preference; the user's choice is persisted to localStorage.

Theme Templates

Markuxt defaults to the Seaside theme (ocean blue/teal palette). Three additional themes are available as separate template repositories — each extends markuxt and applies its own CSS color overrides:

| Theme | Palette | Demo | |-------------|-------------------------|--------------------------------------------------------------------------------------------------| | Seaside | Ocean blue / teal | markuxt.github.io/markuxt-template-seaside | | Forest | Nature green | markuxt.github.io/markuxt-template-forest | | Sunset | Warm amber / terracotta | markuxt.github.io/markuxt-template-sunset | | Slate | Cool gray / steel blue | markuxt.github.io/markuxt-template-slate |

To start a new site with a specific theme, clone the corresponding template repo and follow its README. The theme is applied entirely through CSS custom properties in styles/_theme.css — no build-time configuration needed.

Architecture

markuxt/
├── nuxt.config.ts            # Layer configuration (modules, hooks, vite, etc.)
├── app.config.d.ts           # TypeScript declarations for markuxt AppConfig
├── src/
│   ├── assets/main.css       # Design system & global styles
│   ├── components/           # Vue components (AppHeader, AppFooter, Hero, etc.)
│   ├── composables/          # Shared composables
│   ├── content-transformers/ # Custom Nuxt Content transformers
│   ├── error.vue             # Custom 404 error page
│   ├── layouts/default.vue   # Default layout with header + footer
│   ├── middleware/            # Route middleware (navigation guard)
│   ├── pages/                # All page routes
│   │   ├── index.vue         # Homepage
│   │   ├── members/          # Members listing & detail pages
│   │   ├── news/             # News listing & detail pages
│   │   ├── positions/        # Open positions
│   │   ├── projects/         # Projects listing & detail pages
│   │   └── publications/     # Publications listing & detail pages
│   ├── plugins/              # Nuxt plugins
│   └── server/plugins/       # Server-side Nitro plugins
└── package.json

Configuration Reference

Consuming sites configure Markuxt through appConfig.markuxt in their nuxt.config.ts:

export default defineNuxtConfig({
  appConfig: {
    markuxt: {
      // Logo image path
      logo: {
        src: '/images/logo.png',
      },

      // Navigation items — controls header nav, footer quick links,
      // and route guarding. Pages NOT listed here will return 404.
      navigation: [
        { to: '/', labelKey: 'nav.home' },
        { to: '/members', labelKey: 'nav.members' },
        { to: '/publications', labelKey: 'nav.publications' },
        { to: '/projects', labelKey: 'nav.projects' },
        { to: '/positions', labelKey: 'nav.positions' },
        { to: '/news', labelKey: 'nav.news' },
      ],

      // Contact information shown in footer
      contact: {
        email: '[email protected]',
        externalUrl: 'https://www.example.edu',
        externalLabelKey: 'footer.universityLink', // i18n key
      },

      // Homepage carousel
      carousel: {
        fallbackImage: '/images/logo.png',
        images: [
          { src: '/images/photo1.jpg', alt: 'Lab', caption: 'Our Lab' },
        ],
      },

      // Research areas on homepage — `icon` references a globally
      // registered Vue component name (see Icons section below)
      researchAreas: [
        { icon: 'IconSearch', titleKey: 'research.aerospace', descKey: 'research.aerospaceDesc' },
      ],

      // Member categories — `key` is referenced from each member's
      // `category:` frontmatter; `labelKey` is an i18n key. Array order is
      // the display / filter / sort order. No built-in defaults — declare
      // your own.
      members: {
        categories: [
          { key: 'staff', labelKey: 'members.staff' },
        ],
      },
    },
  },
})

Navigation Guard

Pages defined in navigation are accessible. Any markuxt section page (/members, /publications, /projects, /positions, /news) that is not listed will return a 404. The home page (/) is always accessible.

Member Categories

The groups on the Members page are configurable via members.categories. Each entry's key matches the category: field in a member's Markdown frontmatter, and labelKey is resolved against the consuming site's i18n files. The array order is the display, filter, and sort order; a filter bar appears automatically when there are 2+ categories, plus an All option. There are no built-in defaults — every consuming site declares its own categories. With none configured, the Members page simply lists everyone (no filter bar).

Icons

Markuxt does not bundle any icon library. The consuming site is responsible for registering Vue components globally and referencing them by name in configuration.

Example using @icon-park/vue-next:

plugins/icons.ts (project root, outside src/ to avoid Content scanning):

import Search from '@icon-park/vue-next/es/icons/Search'
import Robot from '@icon-puxt/vue-next/es/icons/Robot'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.component('IconSearch', Search)
  nuxtApp.vueApp.component('IconRobot', Robot)
})

nuxt.config.ts:

export default defineNuxtConfig({
  plugins: ['~~/plugins/icons.ts'],
  appConfig: {
    markuxt: {
      researchAreas: [
        { icon: 'IconSearch', titleKey: 'research.search', descKey: 'research.searchDesc' },
      ],
    },
  },
})

i18n

Markuxt expects consuming sites to provide translation files. Translation keys used by Markuxt's components (e.g. nav.home, footer.brand, members.staff) must be present in the site's locale JSON files.

Content Structure

Markuxt uses @nuxt/content v2. The consuming site configures the content source directory:

content: {
  sources: {
    content: {
      driver: 'fs',
      base: resolve(process.cwd(), 'src'),
    },
  },
},

Expected content directories under the base:

| Path | Content Type | |-----------------|---------------------------------| | members/ | Member profiles (Markdown) | | news/ | News articles (Markdown) | | publications/ | Publication entries (Markdown) | | projects/ | Project descriptions (Markdown) | | positions/ | Open positions (Markdown) |

Binary assets (images, videos) placed alongside Markdown files are automatically synced to public/_markuxt/ during build.

License

Apache-2.0