SERPHER: A GOPHER inspired information platform

This blog is not yet powered by SERVPHER. The article you are currently reading is still processed by Jekyll, transformed into a static website and presented using the So Simple theme. This setup has served METACODES.PRO reliably for many years.

Nevertheless, maintaining the machinery around the articles has gradually become more cumbersome than maintaining the articles themselves.

Ruby versions have to match. Gems need compatible versions. Themes evolve-or cease to evolve. Sass migrations appear. Plugins add dependencies. A seemingly harmless update can turn into an afternoon spent investigating why the website no longer builds or why the generated result suddenly looks different.

None of this makes Jekyll a bad tool.

On the contrary, it solved an important problem elegantly: Markdown documents can be transformed into a fast, portable website requiring no application server.

My own requirements, however, have gradually moved in another direction.

I want the content to remain accessible as information rather than disappear into a build artifact. I want to inspect it, enrich it, query it and represent it differently for different consumers. I want static documents and dynamically generated information to participate in the same model. Most importantly, I want the architecture surrounding my content to remain under my control.

The first idea was deceptively small:

What if I simply expose a directory containing Markdown documents through HTTP?

This idea became SERVPHER.

The project is still under active development. Its user interface is not finished, several capabilities required for replacing METACODES.PRO are still missing and much of the current Single Page Application (SPA) is intended for architectural exploration rather than for readers of a finished website.

However, SERVPHER is beginning to take shape.

More importantly, it no longer feels like an experimental file server. A coherent architecture has emerged-one that may eventually allow METACODES.PRO to leave its increasingly cumbersome Jekyll machinery behind.

SERVPHER is not finished, but its architectural identity is becoming visible.

Gopher as a source of inspiration

Long before today’s web applications accumulated client-side frameworks, build pipelines, package managers and layers of content transformation, the Gopher protocol offered a remarkably simple way of navigating information on the Internet.

A Gopher client requested a selector from a server.

The server responded either with a resource or with a menu containing references to further resources. These menus formed what appeared to the user as a virtual hierarchical filesystem.

Conceptually, a Gopher space resembled something like this:

ROOT
│
├── Documentation
│   ├── Introduction
│   ├── Installation
│   └── Configuration
│
├── Articles
│   ├── Computing
│   ├── Software architecture
│   └── Computer archaeology
│
└── Downloads
    ├── Source code
    └── Documents

This model was deliberately modest.

A resource could be a document, a submenu, a search service or another supported type of information. Navigation emerged from menus returned by servers. Clients did not need to understand the internal storage structure behind those menus, nor did servers prescribe a complex presentation layer.

Gopher was eventually overshadowed by the World Wide Web, whose hypertext model and visual possibilities were considerably more flexible. I do not intend to recreate Gopher, nor is SERVPHER an implementation of the Gopher protocol.

Still, several of Gopher’s ideas remained fascinating to me:

  • Information is organized into navigable structures
  • Resources are identified independently of their presentation
  • A server exposes information rather than application screens
  • Clients remain consumers of a shared information space
  • A hierarchy can provide useful navigation without requiring a database-backed content model
  • Simple resources can form surprisingly expressive systems

The inspiration is therefore conceptual rather than protocol-specific.

Gopher begins with a hierarchy of resources.

SERVPHER begins with a graph of information.

Gopher menus describe where a user may continue navigating.

SERVPHER nodes describe information, relationships, metadata and optional content.

Gopher clients interpret resource types.

SERVPHER clients request projections of the same underlying information.

One might describe SERVPHER as an exploration of what some of Gopher’s appealing simplicity could look like when combined with modern content negotiation, semantic metadata, dynamic information and transport-independent representations.

Gopher
    │
    ▼
Hierarchical resources
    │
    ▼
Navigable information space
    │
    ▼
SERVPHER
    │
    ▼
Semantic node graph
    │
    ▼
Multiple projections and clients

Gopher provided the inspiration to think of a server as an entrance into an information space rather than as a collection of application endpoints.

The motivation behind SERVPHER

The content of METACODES.PRO is already stored in a mostly sensible form.

Articles are Markdown documents. Images and downloadable resources are files. Metadata such as titles, publication dates, categories and tags accompanies the content. Directories provide a degree of organization.

Why should publishing such information require reconstructing an entire website?

Why must a document first be transformed into generated files before a web server can expose it?

Why should navigation, metadata, content and presentation become intertwined with a particular generator, templating system and theme?

A static site generator answers these questions by producing the final website ahead of time. The generated result is simple to deploy and efficient to serve.

My requirements increasingly point toward an information system that remains alive at runtime.

I want to be able to:

  • Inspect the available information
  • Request different representations
  • Enrich documents through processors
  • Add virtual or generated content
  • Develop a user interface independently of the content model
  • Introduce new information sources without rewriting the presentation
  • Preserve the original Markdown documents as portable content

The immediate objective is practical:

SERVPHER is intended eventually to replace the Jekyll-driven METACODES.PRO website.

A broader architectural objective emerged while working toward it:

Content should be modelled independently of storage, representation, transport and presentation.

The first objective gives SERVPHER a genuine application and a measurable destination.

The second prevents it from degenerating into a collection of shortcuts tailored exclusively to my current blog.

Beginning with files

The first versions of SERVPHER were intentionally centered around files.

Given a directory such as

content/
├── index.md
├── about.md
├── blog/
│   ├── first-article.md
│   └── second-article.md
└── assets/
    ├── style.css
    └── logo.png

the server should discover its resources and expose them through HTTP.

This already eliminates a surprising amount of application code.

No controller needs to be implemented for each document. No Data Transfer Object (DTO) has to reproduce the directory structure. No route table needs to be synchronized manually with the available articles.

The filesystem already contains information:

  • Directories establish a hierarchy
  • Filenames identify resources
  • File extensions suggest media types
  • An index.md document naturally represents its surrounding directory
  • Numeric prefixes can define ordering
  • Dot-prefixed names can identify hidden resources

It initially seemed reasonable to make this filesystem hierarchy the central model.

That assumption did not survive for long.

Classpath resources had to participate as well, particularly the JavaScript, Cascading Style Sheets (CSS) and HyperText Markup Language (HTML) resources belonging to the bundled SPA.

Directories obtained their own content through index resources. Metadata began to originate from filenames, Markdown front matter and sidecar documents. Dynamically generated information was supposed to behave like stored information.

The filesystem remained important, but it was no longer sufficient as the domain model.

A more general abstraction was required.

From files to nodes

The central abstraction that emerged is the Node.

A node represents an identifiable piece of information.

It is deliberately not defined as a file, directory, web page or REST resource.

Depending upon its origin and purpose, a node may represent:

  • A filesystem resource
  • A directory
  • A classpath resource
  • A Markdown document
  • An image
  • Generated content
  • A virtual resource
  • A remote information source
  • A capability capable of producing information

Every node participates in the same domain model and may expose:

  • Identity
  • A logical location
  • A name
  • Metadata
  • Relationships
  • Optional content

The content is optional because not every node has to contain readable bytes.

A directory may primarily organize other nodes. A virtual node may describe a capability. A dynamically handled node may produce content only when it is invoked.

A node represents information rather than the mechanism storing that information.

This distinction allows the architecture to model what information means without coupling that meaning to the mechanism currently providing it.

A Markdown document, a generated report and an image loaded from remote storage may originate from completely different technologies. Once they have entered the node graph, however, they participate in identical navigation, metadata, querying and projection semantics.

The node graph as the single source of truth

Nodes do not exist in isolation.

Together they form the Node Graph, the canonical information model of SERVPHER.

The graph establishes relationships such as:

  • Parent
  • Children
  • Siblings
  • Previous
  • Next
  • Root
  • Breadcrumb
  • Self

Navigation therefore does not have to be recreated independently for each representation. It emerges from the relationships already contained within the graph.

ROOT
│
├── Documentation
│   ├── Introduction
│   ├── Installation
│   └── Configuration
│
├── Assets
│   ├── Stylesheets
│   ├── JavaScript
│   └── Images
│
└── Blog
    ├── Article 1
    └── Article 2

This resembles the hierarchical navigation that made Gopher so approachable, but the SERVPHER model deliberately extends beyond a tree of menu entries.

Nodes can expose rich metadata. Relationships can become more semantic. Queries may select particular views. Different projections can represent the same node differently. Dynamic and virtual nodes can participate without pretending to be stored files.

The graph also abstracts away the physical origins of its nodes.

One subtree may have been discovered from the filesystem, another from the application classpath and a third may consist entirely of dynamically produced nodes. A client navigating the graph does not need to know these implementation details.

This provides one canonical model from which every representation can be derived.

                         Node Graph
                             │
              ┌──────────────┼──────────────┐
              │              │              │
              ▼              ▼              ▼
           JSON           Markdown      Binary content
              │              │              │
              └──────────────┼──────────────┘
                             │
                       Future projections

Without a canonical graph, different outputs tend to develop independent interpretations of the same content. A browser may construct one navigation model, a REST interface another and a future command-line application yet another. Visibility, ordering and metadata gradually become inconsistent.

By establishing the node graph as the single source of truth, SERVPHER attempts to prevent this duplication.

Information is modelled once and represented many times.

The filesystem as a declarative language

Although the filesystem is no longer the domain model, it remains a convenient way of constructing parts of the graph.

During development, several lightweight filename semantics have emerged.

An ordered collection can be expressed as follows:

10--Introduction.md
20--Installation.md
30--Configuration.md

The numeric prefixes become ordering metadata, while the logical node names remain:

Introduction.md
Installation.md
Configuration.md

A leading dot marks a node as hidden:

.draft.md
.internal/

A bookmark identifier can provide a stable reference independent of the node’s current location:

Installation [INSTALL].md

An index resource turns its surrounding directory into a content-bearing node:

documentation/
├── index.md
├── introduction.md
└── installation.md

Clients may then address /documentation without knowing that the directory obtains its content from index.md.

Additional metadata may accompany an article using a sidecar document:

article.md
article.md.yml

Markdown front matter provides another source:

---
title: Exploring SERVPHER
category: Software Architecture
tags:
  - SERVPHER
  - Java
---

# Exploring SERVPHER

Taken individually, these conventions are small conveniences.

Together, they turn the filesystem into a lightweight Domain-Specific Language (DSL) describing an information graph.

20--Documentation [DOC]/
├── index.md
├── 10--Introduction.md
├── 20--Installation.md
└── .draft.md

Without opening a single document, SERVPHER can already derive:

  • The node hierarchy
  • The navigation order
  • A stable bookmark
  • The directory’s index content
  • The hidden state of the draft

The filesystem is not merely storage-it is one possible declarative language for constructing the node graph.

This is particularly attractive for the eventual migration of METACODES.PRO. The articles should remain ordinary, portable documents rather than records trapped within an application-specific database.

Discovering and understanding information

As more semantics were introduced, another architectural separation became necessary.

Discovering information is not the same as understanding it.

SERVPHER therefore distinguishes between scanners and processors.

A scanner discovers nodes:

Filesystem ──► Filesystem Scanner ──┐
                                    │
Classpath  ──► Classpath Scanner ───┼──► Node Graph
                                    │
Future Source ─► Future Scanner ────┘

A processor enriches nodes that have already been discovered.

Processors may extract Markdown metadata, merge sidecar metadata, resolve placeholders or derive future semantic relationships.

Initial Node Graph
        │
        ▼
Sidecar Processor
        │
        ▼
Markdown Processor
        │
        ▼
Future Processors
        │
        ▼
Enriched Node Graph

This distinction keeps scanners focused.

A filesystem scanner should discover that a Markdown document exists, establish its position in the graph and attach immediately available structural metadata.

It should not simultaneously become a Markdown parser, taxonomy generator, search indexer and publication workflow.

Each processor contributes one additional aspect of understanding.

Scanners discover information; processors progressively understand it.

The processing model has started to become one of the strongest aspects of SERVPHER. New behavior can be introduced as another stage in the pipeline rather than by continuously enlarging one central component.

Projection is not serialization

Exposing the graph through HTTP initially suggested an obvious implementation: Serialize the nodes as JSON.

This works-until it does not.

Serialization converts an object structure into another format. It commonly exposes the structure of an implementation rather than deliberately describing the information required by a particular client.

One client may require only a single node.

Another may need its immediate children. A debugging client may request metadata, relationships and embedded content. A browser may prefer Markdown, HTML or an image. Hidden nodes may need to be excluded. Large subtrees may have to remain collapsed.

These are not merely serialization concerns.

They are projection concerns.

A projection creates a particular view of the node graph.

A client expresses its intended observation through a ProjectionQuery, including concepts such as:

  • Depth
  • Visibility
  • Included fields
  • Excluded fields
  • Accepted media types

The graph itself remains unchanged.

                     Node Graph
                         │
          ┌──────────────┼──────────────┐
          │              │              │
          ▼              ▼              ▼
 application/        Markdown       Binary
 servpher+json      projection    pass-through

Two projections may differ substantially while still describing the same underlying node.

Serialization exposes an object; projection creates a view of information.

The result of a projection is a transport-independent ProjectionRepresentation. It encapsulates the media type, content stream and optional content length-but it does not own HTTP status codes, response headers or Spring-specific response objects.

A transport adapter determines how the representation is delivered.

This may appear elaborate for serving a blog article, but it protects the content model from the technology currently carrying it.

Today, that transport is primarily HTTP.

The architecture should not depend upon this remaining true forever.

Static and dynamic content become equal

Traditional web architectures often treat static and dynamic content through completely different mechanisms.

A web server delivers files. Controllers generate responses. Templates render pages. Each mechanism may have its own routing, metadata and error handling.

SERVPHER attempts to avoid this division.

It distinguishes only between:

  • Information that already exists
  • Information that can be produced

Handlers contribute behavior to nodes and may generate content upon invocation. The node continues to own its identity, relationships and metadata, while the handler provides runtime behavior.

From the perspective of projection, the resulting content remains an ordinary stream.

This permits nodes with no corresponding physical resource.

A future graph might contain nodes such as:

/system/status
/reports/monthly
/database/statistics
/search/results

These nodes are not simulated files.

They are virtual information-bearing elements within the same graph.

This capability is not yet central to replacing METACODES.PRO, but it demonstrates that the emerging architecture is no longer constrained to reproducing a static website.

Dynamic content is not a special extension of the model-it is a natural consequence of modelling information independently of storage.

The SPA as an architectural test

SERVPHER currently includes a bundled Single Page Application.

Its present form primarily serves as a debugging and exploration interface. It visualizes nodes, metadata, links, child relationships and embedded content. Binary content embedded within the canonical application/servpher+json representation is encoded deterministically using Base64 and can be decoded by the client.

This is useful during development, but it is not yet the finished interface intended to replace METACODES.PRO.

The long-term direction separates two concerns:

┌─────────────────────────────────────────┐
│                                         │
│          End-user presentation          │
│                                         │
├─────────────────────────────────────────┤
│ ▼ Optional diagnostic information       │
│   Metadata                              │
│   Relationships                         │
│   Projection                            │
│   Raw representation                    │
└─────────────────────────────────────────┘

The actual content should become primary.

Diagnostic details should remain available through an optional developer overlay.

Most importantly, the SPA is deliberately not privileged. It communicates exclusively through the same public interface available to any other client.

This provides a useful architectural test.

Whenever the SPA needs information that is unavailable through the public projection model, the preferred solution is not to introduce a private frontend endpoint. Instead, the public representation should be reconsidered.

Only when the reference client works without architectural shortcuts can the public interface be considered sufficiently expressive.

Eventually, a reader-oriented renderer and theme should present blog articles, navigation, archives, tags and other website structures. The current debugging client supplies the groundwork and exposes weaknesses before they disappear behind a polished interface.

Where SERVPHER stands today

SERVPHER remains a work in progress.

It is not yet ready to replace this website.

Nevertheless, several fundamental parts now cooperate:

  • Filesystem and classpath resources contribute to one graph
  • Filename semantics define ordering, visibility, bookmarks and index roles
  • Sidecars and Markdown front matter enrich metadata
  • Projection queries shape representations
  • Multiple strategies represent structured and raw content
  • Binary and textual resources share a stream-oriented abstraction
  • Dynamic handlers participate in the same domain model
  • Transport-independent representations separate projections from HTTP
  • The bundled SPA explores the graph through the public interface

The architecture has reached a stage at which new requirements increasingly find a natural home instead of demanding a redesign.

That is an encouraging milestone, but it is not a declaration that the project is finished.

The next steps are more visible to end users:

  • A richer, content-oriented SPA
  • Markdown rendering suitable for articles
  • A theme and layout system
  • Blog navigation
  • Archives, categories and tags
  • Search
  • Production-ready diagnostics
  • Migration support for existing METACODES.PRO content
  • Caching and conditional requests

The existing website is therefore both the motivation and the proving ground.

A replacement will only be convincing when it handles the real articles, images, downloads, metadata and navigation accumulated over many years without forcing that content into another cumbersome machinery.

The goal is not to replace Jekyll merely with another generator-the goal is to make the generator unnecessary.

Growing a platform instead of hard-coding a blog

One temptation would be to tailor SERVPHER directly around the present structure of METACODES.PRO.

That might produce a replacement more quickly.

It would also risk embedding today’s website decisions into tomorrow’s architecture.

Instead, SERVPHER is intended to become a platform that applications tailor through explicit extension points:

  • Scanners discover additional information sources
  • Processors enrich the graph
  • Handlers generate information
  • Projection strategies introduce new views
  • Metadata describes application-specific semantics
  • SPA renderers present additional media types
  • Themes customize the appearance

The blog should become one application of the platform-not the hidden shape governing every architectural decision.

This approach takes more time.

It also produces more architectural discussions and occasionally replaces implementations that previously appeared complete. Yet the resulting concepts have repeatedly become simpler and more general.

Directories becoming content-bearing nodes solved more than blog landing pages.

Handlers solved more than generated files.

Projection representations solved more than HTTP response construction.

The node graph solved more than filesystem navigation.

A sound abstraction should enable the immediate use case without being defined solely by it.

From Gopherspace to an information graph

The relationship between Gopher and SERVPHER becomes clearest when comparing their respective centers.

Gopher organizes access around resources and hierarchical menus.

SERVPHER organizes information around nodes and relationships.

Gopher lets a client traverse a distributed information space.

SERVPHER aims to let clients observe and project a semantic information graph.

Gopher’s radical simplicity came partly from everything it refused to make part of the protocol. Presentation remained largely a client concern. Servers exposed resources and menus. Clients decided how to display them.

SERVPHER follows a related instinct:

  • Storage should not define presentation
  • Presentation should not define the domain
  • HTTP should not define information
  • The reference frontend should not receive privileged access
  • A resource should remain meaningful independently of its current representation

The implementations are separated by decades of technological development and solve different problems. Nevertheless, the architectural sympathy is recognizable.

Gopher menu
    │
    ▼
Navigable resource hierarchy
    │
    ▼
SERVPHER node graph
    │
    ▼
Queryable information model
    │
    ▼
Transport-independent projections

Where Gopher exposed a remarkably coherent resource space, SERVPHER attempts to expose a coherent information space.

This is the idea I hope to preserve while adding the capabilities required by a modern content platform.

Replacing METACODES.PRO

The intended destination remains concrete.

At some point, this page should no longer be generated by Jekyll.

Its Markdown source should be discovered by SERVPHER, enriched with metadata, placed within the node graph and projected into a representation appropriate for the reader.

The website should become a tailored view of that information rather than a build artifact produced by a tightly coupled toolchain.

Conceptually, the future flow may resemble:

Markdown articles
        │
        ▼
Filesystem scanner
        │
        ▼
Metadata processors
        │
        ▼
Node graph
        │
        ▼
Projection query
        │
        ▼
Blog representation
        │
        ▼
METACODES.PRO theme
        │
        ▼
Reader

The same article may remain simultaneously accessible as:

  • Raw Markdown
  • Canonical SERVPHER JSON
  • Rendered HTML
  • A simplified representation for another client
  • A future machine-readable projection

None of these representations owns the article.

They are merely different observations of the same node.

This is where the initial inspiration from Gopher and the current architecture of SERVPHER meet.

Gopher demonstrated how compelling a navigable information space could be when resources and hierarchy were treated as primary concepts.

SERVPHER asks how far this principle can be carried when nodes may originate from files, generated content, remote services or entirely virtual capabilities-and when every consumer may request an appropriate projection of the same graph.

An ongoing architectural experiment

SERVPHER is not an announcement of a completed product.

It is an account of a project beginning to find its shape.

Several details will change. Classes will be renamed. Interfaces will evolve. Some implementations will be replaced. New requirements arising from the migration of METACODES.PRO will undoubtedly expose concepts that are currently still missing.

The important milestone is not that all features are available.

It is that the project now has an architectural direction against which new decisions can be evaluated:

Information Sources
        │
        ▼
     Scanning
        │
        ▼
    Processing
        │
        ▼
    Node Graph
        │
        ▼
 Projection Query
        │
        ▼
    Projection
        │
        ▼
 Representation
        │
        ▼
     Transport
        │
        ▼
      Client

Each stage answers a different question:

  • What information exists?
  • What does the information mean?
  • How is it related?
  • How should a client observe it?
  • How should that observation be represented?
  • How should the representation be delivered?

The architecture has repeatedly improved not by accumulating larger components, but by discovering more precise concepts.

This has led to a recurring question during development:

Have we discovered another domain concept?

As long as SERVPHER continues asking that question, I expect it to remain an interesting project-even before it finally serves this blog.

Conclusion

SERVPHER began as an attempt to serve Markdown documents from a directory.

Gopher supplied part of the inspiration: A server may expose a simple, navigable information space without owning its final presentation.

Jekyll supplied the concrete problem: My existing blog works, but maintaining the machinery that generates it has become increasingly cumbersome.

Between these two starting points, another idea has emerged.

Content need not be organized around generated pages, framework controllers or storage technologies. It can be modelled once as a graph of information and projected differently for every consumer.

SERVPHER is still some distance away from replacing METACODES.PRO.

The architecture is beginning to suggest, however, that such a replacement will not merely exchange one website generator for another. Instead, the blog may become one projection of a broader information platform.

Perhaps one day this article will be delivered by the very project it introduces.

Until then, it remains a report from an ongoing architectural experiment:

From Gopherspace, through a Jekyll-driven blog, toward a projectable graph of information.