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

deskforge

v1.0.9

Published

Build everything. Own everything. Pay for nothing.

Readme

deskforge Framework Documentation

deskforge is a lightweight, component-oriented application framework for building screen-based UI trees and rendering them to images or other outputs. The current repository ships a small but practical foundation for:

  • building a declarative node tree
  • routing between screens
  • rendering a tree with the renderer package
  • exporting the output to PNG or other formats

The project is organized as a monorepo with separate packages for core rendering, routing, UI, state, theming, device integration, and more.

This documentation reflects the current implementation in this repository and focuses on the patterns demonstrated by the example app in examples/deskforge-app.


1. What deskforge is

deskforge is built around a simple idea:

  1. You describe your UI as a tree of nodes.
  2. Each node has a type, props, and children.
  3. A renderer walks that tree and draws it.
  4. A router lets you switch between screens.

This model is intentionally simple and close to the rendering pipeline used by many UI systems, but it is currently aimed at a desktop-style, image-rendering workflow rather than a full browser runtime.

Core principles

  • Declarative UI composition using node trees
  • Screen-based navigation with automatic route discovery
  • App.ts as the landing entry for the app shell and screen tree
  • Renderer-driven output for images and visual artifacts
  • Modular packages that can be used independently

2. Repository structure

A typical deskforge workspace contains:

packages/
  core/        # node tree, scheduler, component primitives
  renderer/    # rendering engine
  router/      # screen routing and navigation
  ui/          # built-in UI primitives
  state/       # state utilities
  theme/       # theme tokens and styling
  device/      # device integrations
  ...
examples/
  deskforge-app/   # full example app

Important packages

  • @deskforge/core: defines the underlying node model and factory helpers
  • @deskforge/renderer: renders the node tree to canvas-like output
  • @deskforge/router: handles route registration and navigation
  • @deskforge/ui: provides reusable UI building blocks

3. Installation

If you are using the monorepo directly, install dependencies from the repository root:

cd /path/to/deskforge
npm install

If you are building an app that depends on the published packages, install the relevant packages:

npm install @deskforge/core @deskforge/router @deskforge/renderer

You can also add the UI package:

npm install @deskforge/ui

Publishing packages

The repository includes a package publish workflow for packages/*.

npm install
npm run publish:packages

This builds all workspace packages and publishes each non-private package with public access.

To rebuild and publish with one command:

npm run build && npm publish --access public

To scaffold a new app from the published CLI:

npx create-deskforge-app my-app
cd my-app
npm install
npm dfcli start

4. Current authoring syntax

The current deskforge examples use a functional, no-JSX authoring style. Components are written as pure functions that return a DFNode tree created with helpers such as createNode and the built-in UI primitives.

import {
  View,
  Text,
  StyleSheet,
  Button,
  SwiftUI,
  AndroidUI,
} from '@deskforge/ui/src'
import { State } from '@deskforge/state/src'

const styles = StyleSheet.create({
  container: { flex: 1, padding: 24, justifyContent: 'center' },
  title: { fontSize: 24, fontWeight: '600', marginBottom: 12 },
})

export function CounterScreen() {
  const state = State({ count: 0 })

  return View(styles.container, [
    Text(`Count: ${state.count}`, styles.title),
    Button('Increment', { padding: 12 }, {
      onPress: () => {
        state.count += 1
      },
    }),
  ])
}

Key patterns in the current codebase:

  • No JSX or HTML-style tags are used.
  • UI is composed with functional helpers such as View, Text, Pressable, ScrollView, TextInput and Modal.
  • State is created with State(...) and updated directly.
  • Styling is declared with StyleSheet.create(...) using React Native-style objects.
  • Theme usage is imported from @deskforge/theme/src and applied with Theme.apply(...).

5. Packages and what they are for

deskforge is organized as a set of focused packages. Each package can be used independently, and they work together through the core node-tree model.

Core packages

  • @deskforge/core
    • Core node model, createNode, diff engine, scheduler, and component primitives.
    • Use this when you want to build a UI tree or define custom components.
import { createNode } from '@deskforge/core'

const node = createNode('view', { style: { padding: 16 } }, [])
  • @deskforge/renderer
    • Renders node trees to a canvas-style surface and exports to image/buffer output.
    • Use this to display or export your UI.
import { Renderer } from '@deskforge/renderer'

const renderer = new Renderer({ width: 800, height: 600, backgroundColor: '#fff' })
renderer.renderNode(node)
await renderer.saveAs('./dist/output.png')
  • @deskforge/router
    • Screen routing, navigation helpers, and automatic file-based route discovery.
    • Use this when your app needs multiple screens and navigation.
import { Router } from '@deskforge/router'

// routes are discovered from the file structure automatically
Router.start()
  • @deskforge/ui
    • A modern set of functional UI primitives for layout, text, input, lists, overlays, feedback, and platform-aware controls.
    • The current examples use the monorepo entry point with /src imports, including View, Text, Pressable, Button, TouchableOpacity, Image, TextInput, ScrollView, FlatList, SectionList, SafeAreaView, KeyboardAvoidingView, Modal, ActivityIndicator, Switch, Slider, CheckBox, StatusBar, Platform, SwiftUI, and AndroidUI.
import {
  View,
  Text,
  ScrollView,
  Modal,
  StyleSheet,
  SwiftUI,
  AndroidUI,
  LiquidGlass,
} from '@deskforge/ui/src'

State and styling packages

  • @deskforge/state
    • Reactive state helpers for local app state and component state.
import { State } from '@deskforge/state'

const state = State({ count: 0 })
  • @deskforge/theme
    • Theme tokens, color palettes, spacing, animation helpers, and a simple Theme API for switching modes and applying theme preferences.
import { Theme } from '@deskforge/theme/src'

Theme.apply({ isDark: true })

Device and platform integrations

  • @deskforge/device
    • Device APIs such as camera, contacts, sensors, and media helpers.
import { Camera, Contacts } from '@deskforge/device'
  • @deskforge/file
    • File system helpers for reading and writing files.
import { readFile, writeFile } from '@deskforge/file'
  • @deskforge/network
    • Peer-to-peer networking helpers, mDNS discovery, and TCP transfer utilities.
import { discoverPeers } from '@deskforge/network'
  • @deskforge/notifications
    • Toasts, push notifications, SMS, email, and notification helpers.
import { Notify } from '@deskforge/notifications'
  • @deskforge/security
    • Biometric helpers and encryption utilities.
import { encrypt } from '@deskforge/security'

AI, data, and app platform packages

  • @deskforge/ai
    • Local AI helpers and brain-style node creation for on-device reasoning.
import { createBrain } from '@deskforge/ai'
  • @deskforge/db
    • Database adapters for SQLite, Postgres, MySQL, and MongoDB.
import { connect } from '@deskforge/db'
  • @deskforge/background
    • Background tasks and scheduling helpers.
import { BackgroundTask } from '@deskforge/background'
  • @deskforge/updater
    • Self-hosted automatic update helpers.
import { Updater } from '@deskforge/updater'
  • @deskforge/payments
    • Unified payment wrapper with failover support for common providers.
import { Pay } from '@deskforge/payments'
  • @deskforge/i18n
    • Localization helpers with African language support.
import { t } from '@deskforge/i18n'
  • @deskforge/logger
    • Structured logging helpers for the framework and app code.
import { logger } from '@deskforge/logger'
  • @deskforge/bridge
    • Language bridge for calling code written in Python, Go, Rust, PHP, C, Kotlin, or Swift.
import { callPython } from '@deskforge/bridge'
  • @deskforge/cli
    • Command-line tools for scaffolding and app management.
npx create-deskforge-app my-app
npm dfcli start

5. Quick start: File-based routing

deskforge now includes a file-based router similar to Expo Router and Next.js. Routes are discovered automatically from your screen files, so you do not manually register them. Your App.ts file acts as the landing page and app shell for the discovered screens:

import { FileRouter, ManifestBuilder, Screen } from '@deskforge/router'

const HomeRoute = Screen(() => createNode('view', {}, []), {
  title: 'Home',
  layout: 'app',
})

const routes = new ManifestBuilder()
  .add('index.ts', HomeRoute.component)
  .add('about.ts', AboutScreen)
  .add('note/[id].ts', NoteScreen)
  .build()

const router = new FileRouter(routes)

router.navigate('/')
router.navigate('/note/123')

const node = router.render()
renderer.renderNode(node)

See FILE_BASED_ROUTER.md for detailed documentation and examples.


5. Core concepts

5.1 The node tree

The building block of deskforge is a node. Every UI element is represented by a node with:

  • type: the component type, such as text, view, or a custom component
  • props: properties that describe how the node should appear or behave
  • children: nested nodes

The core package exposes createNode to construct nodes.

import { createNode } from '@deskforge/core'

const node = createNode('view', {
  style: { background: '#ffffff', padding: 16 },
}, [])

A more realistic example looks like this:

import { createNode } from '@deskforge/core'

const title = createNode('text', {
  text: 'Hello deskforge',
  color: '#111827',
  font: '24px sans-serif',
})

const layout = createNode('view', {
  style: { padding: 24 },
}, [title])

5.2 The renderer

The renderer walks the node tree and produces visual output. In the current example app, the rendering flow is:

  1. create or compose a node tree
  2. pass it to the renderer
  3. save or display the result
import { Renderer } from '@deskforge/renderer'

const renderer = new Renderer({
  width: 800,
  height: 600,
  backgroundColor: '#f7f8fb',
})

renderer.renderNode(layout)
await renderer.saveAs('./dist/output.png')

5.3 Screens and routes

deskforge uses automatic route discovery from a screen folder structure. A screen is simply a function that returns a node tree, and it can also carry metadata such as a title and layout. The App.ts entry file becomes the landing page that hosts the app shell and initial screen.

import { Screen } from '@deskforge/router'

function HomeScreen() {
  return createNode('view', {
    style: { padding: 24 },
  }, [])
}

const HomeRoute = Screen(HomeScreen, { title: 'Home', layout: 'app' })

The router discovers screens automatically from the file structure:

import { Router } from '@deskforge/router'

Router.start()

And navigate with:

Router.go('home')

6. Building an app in deskforge

The simplest app has three parts:

  1. an entry point file, usually App.ts, which acts as the landing page and app shell
  2. one or more screen files discovered automatically by the router
  3. a small UI helper layer for creating views and text blocks

The example app in examples/deskforge-app follows this pattern.

6.1 Create the app entry point

A basic entry file looks like this:

import * as fs from 'fs'
import { Renderer } from '@deskforge/renderer'
import { Router } from '@deskforge/router'
import { HomeScreen } from './src/screens'

Router.start()

function createRoot() {
  return createNode('view', {
    style: { background: '#f7f8fb', padding: 24 },
  }, [])
}

async function main() {
  fs.mkdirSync('./dist', { recursive: true })

  const renderer = new Renderer({
    width: 800,
    height: 600,
    backgroundColor: '#f7f8fb',
  })

  Router.go('home')
  renderer.renderNode(createRoot())
  await renderer.saveAs('./dist/app.png')
}

main().catch(console.error)

6.2 Create screen files

A screen is a function that returns a node tree. The example uses a simple Screen helper to create a container.

import type { ScreenParams } from '@deskforge/router'
import { Screen, Text, View } from '../ui/Responsive'

export default function HomeScreen(params: ScreenParams = {}) {
  return Screen({ style: { background: '#f8fafc', padding: 24 } })
    .add(
      View({ style: { background: '#ffffff', borderRadius: 24, padding: 24 } }),
      Text('Home Screen', { style: { fontSize: 28, fontWeight: '700' } }),
      Text('Welcome to deskforge.', { style: { color: '#4b5563', fontSize: 16 } }),
    )
    .build()
}

6.3 App entry and automatic screen discovery

The App.ts entry file serves as the landing page and initial app shell. Screen files under the app structure are discovered automatically and exposed by the router.

import { Router } from '@deskforge/router'

Router.start()

6.4 Navigate between screens

Router.go('details', { noteId: 'A1' })

The current router stores navigation history and exposes helpers such as:

  • Router.go(name, params)
  • Router.back()
  • Router.forward()
  • Router.params()
  • Router.currentRoute()
  • Router.start()

For a React Navigation-like experience, deskforge also supports a stack-style navigation model with screen components, route params, and a shared app shell defined in App.ts.


6. Using the example app

The repository includes an example app in examples/deskforge-app. It demonstrates how to build a basic screen-based app.

Run the example

cd examples/deskforge-app
npm install
npm run build
npm dfcli start

This example renders images for the home and details screens into the dist folder.

Example layout

examples/deskforge-app/
  App.ts
  src/
    screens/
      Home.ts
      Details.ts
      index.ts
    ui/
      Responsive.ts

7. Creating your own UI layers

Because deskforge is still evolving, the most practical way to build UI is to define your own lightweight helper functions on top of the core node API.

Example: simple text and view helpers

import { createNode } from '@deskforge/core'

function Text(value: string, props: Record<string, unknown> = {}) {
  return createNode('text', {
    text: value,
    ...props,
  })
}

function View(props: Record<string, unknown> = {}, children: any[] = []) {
  return createNode('view', props, children)
}

This pattern keeps your app code readable while staying close to the underlying node tree model.


8. Styling and layout

The current implementation uses inline style objects and passes them through as node props. A simple screen might look like this:

const card = createNode('view', {
  style: {
    background: '#ffffff',
    borderRadius: 24,
    padding: 24,
    boxShadow: '0 10px 20px rgba(0,0,0,0.08)',
  },
}, [
  createNode('text', { text: 'Card title', font: '700 24px sans-serif' }),
])

Best practices

  • keep styles in a single place when the app grows
  • use small helper components for repeated layout patterns
  • keep screen logic separate from presentation
  • treat each screen as a pure function that returns a node tree

9. Rendering pipeline

deskforge follows a straightforward pipeline:

Screen function -> Node tree -> Renderer -> PNG / buffer / output

What happens internally

  1. A screen returns a node tree.
  2. The node tree is composed of parent and child nodes.
  3. The renderer visits each node.
  4. The renderer converts node props into drawing commands.
  5. The output is saved or displayed.

This makes it easy to reason about your app as a tree of visual elements.


10. How to structure a real project

A practical project structure may look like this:

my-app/
  package.json
  tsconfig.json
  src/
    App.ts
    screens/
      Home.ts
      Details.ts
      Settings.ts
    ui/
      Responsive.ts
      components/
        Card.ts
        Button.ts

Suggested workflow

  1. Create a main App.ts file as the landing page and app shell.
  2. Create one file per screen.
  3. Create helper modules for common UI primitives.
  4. Let the router discover screens automatically.
  5. Render the current screen through the renderer.

11. Extending deskforge

The framework is modular, so you can extend it in several ways:

Add custom components

Create a new node type and teach the renderer how to paint it. This is the most direct way to introduce custom visuals.

Add custom painters

The renderer package supports custom painters. If you need a new visual primitive, register a painter for it.

Add new packages

The monorepo already includes packages for state, theme, device support, notifications, and more. You can build on those modules to grow the framework into a bigger app platform.


12. Building a complete app example

Here is a complete example that follows the patterns already used in the repository.

import * as fs from 'fs'
import { Renderer } from '@deskforge/renderer'
import { Router, Screen } from '@deskforge/router'
import { Text, View, Window } from './src/ui/Responsive'

Router.start()

function createRoot() {
  return Window({ style: { background: '#f7f8fb', padding: 24 } })
    .add(
      View({ style: { background: '#ffffff', borderRadius: 32, padding: 24 } }),
      Text('My App Shell', { style: { fontSize: 24, fontWeight: '700' } }),
      Router.render() ?? Text('No screen selected.', { style: { color: '#6b7280', fontSize: 16 } }),
    )
    .build()
}

async function main() {
  fs.mkdirSync('./dist', { recursive: true })

  const renderer = new Renderer({
    width: 900,
    height: 700,
    backgroundColor: '#f7f8fb',
  })

  Router.go('home')
  renderer.renderNode(createRoot())
  await renderer.saveAs('./dist/demo.png')
}

main().catch(console.error)

13. Tips and best practices

  • Keep screens focused on one responsibility.
  • Compose small building blocks instead of writing large monolithic screens.
  • Use helper functions to hide repetitive node creation.
  • Keep route names stable and descriptive.
  • Keep rendering logic separate from navigation logic.
  • Use App.ts as the shared landing page and shell for the app.
  • Let the router discover screens automatically instead of manually registering them.
  • Use dist/ for generated assets so your source stays clean.

14. Current limitations and roadmap

The current repository is a solid foundation, but it is still early-stage. Some areas are intentionally simple and may evolve over time:

  • the renderer is focused on practical visual output
  • the router is lightweight and screen-based
  • custom components and advanced layout systems are still being expanded
  • additional package features may be added as the framework grows

That said, the architecture is already good enough for building small, structured apps and rendering them in a controlled pipeline.


15. Summary

deskforge is best understood as a small, modular framework for building UI trees and rendering them as visual output. The core workflow is:

  1. define a node tree
  2. compose screens
  3. register routes
  4. render the active screen
  5. export the result

If you follow the structure used by the example app, you can build a simple and maintainable app very quickly.


16. Next steps

To continue learning the framework:

  • read the example app in examples/deskforge-app
  • inspect the core packages in packages/core, packages/router, and packages/renderer
  • start with a single screen and build outward from there
  • add custom helpers for text, cards, buttons, and layouts as your app grows