All posts

From PHP to TypeScript: Rebuilding Wiki|Docs

What changed in a full-stack rewrite focused on type safety, maintainability, and developer experience.

Why I rewrote it?

Wiki|Docs started as a PHP project: a small, databaseless wiki built around a simple idea: your knowledge should live in files you can keep, move, and understand without depending on a database. That idea is still the heart of the project, but the original implementation had reached the point where evolving it across web and desktop experiences was becoming harder than it needed to be.

I wanted a codebase with stronger type safety, clearer boundaries, and a better day-to-day developer experience. Just as importantly, I wanted one language for the entire product instead of maintaining separate technological worlds for the frontend, backend, and desktop application.

Keeping the part that mattered

This was a rewrite of the application, not a change in philosophy. Wiki|Docs remains a flat-file wiki: configuration and metadata are JSON, pages are Markdown files with YAML frontmatter, and attachments are regular files on disk. No database is required.

That model keeps the data portable and makes self-hosting straightforward. Whether Wiki|Docs runs in a container, on a server, or on a desktop machine, the dataset remains a directory rather than an opaque service dependency.

One stack, three surfaces

The new version is written in TypeScript end to end. The shared language made it possible to define contracts once and use the same vocabulary across every layer, while still giving each part of the application a focused responsibility.

NestJS API

The backend validates requests, handles authentication and authorization, exposes the HTTP API, and works directly with the file-backed dataset.

Angular frontend

The web client is a standalone single-page application for browsing, editing, managing documents, and working with the API.

Electron desktop application

The desktop app packages the same frontend and launches the backend locally, adding native configuration and filesystem-aware desktop behaviour without exposing Node.js APIs to the renderer.

The Angular frontend is where that model becomes practical day to day: a focused workspace for navigating a wiki, opening documents, and keeping frequently used pages close at hand. It presents the file-backed knowledge base as an application without hiding its simple structure.

Wiki|Docs web interface showing document navigation and a wiki page
The web application provides a familiar workspace for browsing and reading a file-backed wiki.

Behind that interface, the NestJS API makes the application boundary explicit. Its documented endpoints cover the health and lifecycle of the service as well as authentication, settings, accounts, and document operations, so clients can rely on a visible contract rather than implementation details.

Swagger documentation listing Wiki|Docs API endpoints
The NestJS API exposes a documented contract for the service and its clients.

Shared TypeScript contracts sit between these layers. This reduces duplicated assumptions and makes a change to an API payload visible wherever it matters.

Desktop and remote sync

The desktop application is fully standalone: it packages the frontend, launches the backend locally, and works entirely with a local dataset. A self-hosted remote instance is optional. When configured, the app compares the active document tree in the local dataset with that instance, then coordinates the exchange of changed documents. The backend stays focused on serving and applying changes; Electron owns the synchronization flow.

On the desktop, the same editor is packaged with the application so a new Markdown document can be created and managed locally, even without a remote connection. Native actions sit alongside the familiar writing workspace, keeping the experience close to the web client while giving Electron control of local files and optional synchronization.

Wiki|Docs desktop application editing a new Markdown document
The Electron application brings the Wiki|Docs editor and local document actions to the desktop.

The scope is intentionally narrow: document content and attachments travel between locations, while settings, accounts, pinned documents, and trash remain local to their respective datasets.

What changed and and what did not

The rewrite replaces the PHP implementation with a maintainable TypeScript platform that can grow across browser, self-hosted, and desktop use cases. What did not change is the reason Wiki|Docs exists: a lightweight wiki whose content remains yours, as files.

Explore now Wiki|Docs on GitHub or the original PHP implementation.