Publish an entity at your domain
Stand up an OLPN identity on a static host, a CMS, or a dynamic server.
This guide walks through publishing an entity document at a domain you control. The exact steps depend on your stack. All paths end up at the same place: https://{your-domain}/olpn.json returns a valid OLPN entity document with HTTP 200 and content-type application/json.
Prerequisites
- A domain you own.
- Ability to serve a static file at an arbitrary path or edit the HTML of a page at the domain root.
- An HTTPS certificate. Any modern host handles this automatically.
Option A. Static host
Netlify, Cloudflare Pages, GitHub Pages, S3 + CloudFront, Vercel, Deno Deploy, and similar hosts can serve a static JSON file at any path. This is the easiest setup.
- Create
olpn.jsonat the root of your site source. Use the minimum viable shape from the entity document reference. - Commit and deploy. Confirm
https://{your-domain}/olpn.jsonreturns the document in a plain fetch. - Verify: search for
§:entity:{your-domain}at olpn.org/search. You should see your profile with no credentials or properties yet.
Option B. WordPress
WordPress does not serve arbitrary JSON paths by default. Two reasonable paths:
B.1 File in the web root
Upload olpn.json directly to the WordPress install's web root (next to index.php). Most hosts expose this via FTP or a file manager. Apache and nginx will serve it directly without involving WordPress.
You will need to:
- Check your server's MIME type table sends
application/jsonfor.jsonfiles. Most do by default. - Bypass any caching plugin that strips or rewrites non-HTML paths.
B.2 REST endpoint in a mu-plugin
For finer control, write a small must-use plugin that registers a REST route:
<?php
// wp-content/mu-plugins/olpn.php
add_action('rest_api_init', function () {
register_rest_route('olpn/v1', '/entity', [
'methods' => 'GET',
'permission_callback' => '__return_true',
'callback' => function () {
return [
'version' => '0.9',
'network_id' => '§:entity:example.com',
'entity_type' => 'person',
'details' => [
'name' => get_bloginfo('name'),
'domain' => 'example.com',
],
'properties' => [],
'credentials' => [],
];
},
]);
});
add_action('init', function () {
add_rewrite_rule('^olpn\.json$', 'index.php?rest_route=/olpn/v1/entity', 'top');
});The rewrite maps /olpn.json at the domain root to the REST route. Flush permalinks after activating. You still need to handle the § character if your setup mangles multibyte URLs.
Option C. Ghost (HTML embed only)
Ghost does not serve arbitrary JSON paths. The only path is the HTML embed in your homepage:
- Open Settings → Code injection → Site Header in Ghost Admin.
- Paste a
<script id="olpn-hub" type="application/json">...</script>block. See HTML fallback. - Save. Confirm the embed appears in your homepage source by doing a view-source on the homepage.
- Verify at olpn.org/search.
Option D. Dynamic app (Express, Fastify, Astro, Next, etc.)
Add a single route that returns the entity JSON.
// Express
app.get('/olpn.json', (req, res) => {
res.type('application/json').send({
version: '0.9',
network_id: '§:entity:example.com',
entity_type: 'person',
details: { name: 'Example', domain: 'example.com' },
properties: [],
credentials: [],
});
});Same pattern in other frameworks. The document body can be static, computed, or pulled from a database. If computed, cache the response aggressively; recomputing an entity document per request is overkill.
After publishing
- Confirm the document is reachable in a plain
curl(curl -v https://{your-domain}/olpn.json). HTTP 200, content-typeapplication/json, parseable JSON. - Search at olpn.org/search and confirm the resolver can find it. Check the "Show Details" trace.
- Move on to Publish an ownership record to anchor your domain as a verified property.