Create a Blog

Build a Markdown-powered blog with vault publishing, custom domains, and local sync.

beginner12 min read

What You'll Build

In this guide you will set up a fully functional Markdown blog hosted on Lifestream Vault.

By the end you will have:

  • A dedicated blog vault that acts as your site's content store
  • A public profile that makes your vault browsable at a stable URL
  • Individual posts published with SEO metadata
  • An optional custom domain (e.g. blog.example.com) pointing to your vault
  • A local sync workflow so you can write in your favourite editor and push changes automatically

Everything is managed through the Lifestream Vault UI, the SDK, or the lsvault CLI — use whichever fits your workflow.

Prerequisites

  • A Lifestream Vault account
  • Pro tier or higher to enable vault publishing and per-post publish settings
  • Business tier to attach a custom domain
  • Node.js 18 + (for SDK / CLI usage)

Create a Blog Vault

A vault is an isolated container for documents. Each vault gets its own URL namespace and can be published independently, making it the right unit for a blog.

Via the UI: open Settings → Vaults → New Vault, enter a name (e.g. My Blog) and a URL-friendly slug (e.g. my-blog), then click Create.

Alternatively, use the SDK or CLI below.

typescript
import { LifestreamVaultClient } from '@lifestreamdynamics/vault-sdk';

const { client } = await LifestreamVaultClient.login(
  'https://vault.lifestreamdynamics.com',
  'you@example.com',
  'your-password',
);

// The slug is generated from the name — you do not pass it.
const vault = await client.vaults.create({
  name: 'My Blog',
});

console.log('Vault created:', vault.id, '— slug:', vault.slug);

Set Up Your Public Profile

Your profile slug becomes the first segment of every published URL. Set it once and it applies to all vaults you publish.

  1. Open Settings → Profile
  2. Enter a profile slug (e.g. jane) — lowercase letters, numbers, and hyphens only
  3. Click Save Profile

Your slug is also used on your public author page, which lists all published vaults.

Once publishing is enabled, your blog will be available at:

https://vault.lifestreamdynamics.com/{profileSlug}/{vaultSlug}

For example: https://vault.lifestreamdynamics.com/jane/my-blog

Write Your First Blog Post

Blog posts are standard Markdown files stored inside your vault. A posts/ folder keeps things organised, but any path works.

Lifestream Vault reads YAML frontmatter at the top of each file to populate metadata. The supported fields are:

FieldPurpose
titlePost title (overrides the first H1)
datePublication date (ISO 8601, e.g. 2026-03-01)
tagsArray of category tags
descriptionShort summary shown in listings and SEO

A minimal post looks like this:

---
title: Hello, World
date: 2026-03-01
tags: [intro, meta]
description: My first post on Lifestream Vault.
---

# Hello, World

Welcome to my new blog powered by Lifestream Vault!
typescript
const content = `---
title: Hello, World
date: 2026-03-01
tags: [intro, meta]
description: My first post on Lifestream Vault.
---

# Hello, World

Welcome to my new blog powered by Lifestream Vault!
`;

const doc = await client.documents.put(
  vault.id,
  'posts/hello-world.md',
  content,
);

console.log('Document created:', doc.id);

Publish Your Blog

Vault publishing makes the entire vault publicly browsable — visitors can navigate your posts, use the built-in search, and view your profile page.

Enabling vault publishing does not publish individual documents automatically; it makes the vault visible as a site. You control which posts appear in the listing by publishing them individually (see the next section).

Via the UI: open your vault, go to Settings → Publishing, and toggle Enable vault publishing.

When publishing your vault, you can customize the URL slug, add a site title and description, and configure a custom favicon. These options are available in Settings → Publish.

typescript
// publishVault.publish is positional: (vaultId, params). slug and title
// are required; the rest are optional site-configuration fields.
await client.publishVault.publish(vault.id, {
  slug: 'my-blog',
  title: 'My Blog',
});

console.log('Vault is now public!');

After enabling, your vault index is immediately accessible at:

https://vault.lifestreamdynamics.com/{profileSlug}/{vaultSlug}

No build step or deployment required.

Publish Individual Posts

Publishing a document gives it a canonical public URL and exposes optional SEO fields:

FieldPurpose
slugURL-friendly identifier (e.g. hello-world)
seoTitle<title> tag override
seoDescription<meta name="description"> value
ogImageOpen Graph image URL for social sharing

A published post becomes accessible at:

https://vault.lifestreamdynamics.com/{profileSlug}/{docSlug}

Via the UI: open the document, click the Publish button in the toolbar, fill in the SEO fields, and click Publish Now.

typescript
// publish.create is positional: (vaultId, documentPath, params)
const published = await client.publish.create(
  vault.id,
  'posts/hello-world.md',
  {
    slug: 'hello-world',
    seoTitle: 'Hello, World — My Blog',
    seoDescription: 'My first post on Lifestream Vault.',
    ogImage: 'https://cdn.example.com/hello-world-og.png',
  },
);

// The public URL is built from your profile slug and the post slug:
//   https://vault.lifestreamdynamics.com/{profileSlug}/{published.slug}
console.log('Published with slug:', published.slug);

Add a Custom Domain

Plan Required

Custom domains require a Business plan. Upgrade in Settings → Subscription.

Point blog.example.com (or any subdomain) to your vault with two DNS records:

Step 1 — TXT record for ownership verification:

TypeHostValue
TXT_lsv-verify.blog.example.comlsv-verify=<token>

The verification token is returned when you create the domain (see below).

Step 2 — CNAME to route traffic:

TypeHostValue
CNAMEblog.example.comvaults.lifestreamdynamics.com

DNS propagation typically takes 1–60 minutes. Once the TXT record resolves, verification runs automatically via the background domain-verification worker — no manual trigger is needed. Monitor domain status in Settings → Custom Domains or via the SDK/CLI.

typescript
// Step 1 — register the domain (returns verification token)
const domainRecord = await client.customDomains.create({
  domain: 'blog.example.com',
});

console.log('Add this TXT record:', domainRecord.verificationToken);
// Verification happens automatically via the background domain-verification worker.
// Poll the domain status to check progress — get(domainId) is positional:
const status = await client.customDomains.get(domainRecord.id);
console.log('Domain status:', status.status); // 'pending' → 'verified'

Sync from Your Local Editor

The lsvault sync commands let you write posts in any local editor (VS Code, Obsidian, Neovim, etc.) and push changes to your vault automatically.

Workflow options:

ModeBest for
pushOne-time bulk upload of a directory
watchInteractive session — pushes on file save
daemonBackground service — always-on sync

First, initialise sync for the vault by pointing it at a local directory:

bash
# Link your local ./blog directory to the vault.
# init prints a sync config ID — use it with push/watch below.
lsvault sync init <VAULT_ID> ./blog --mode push
bash
# <SYNC_ID> is the config ID printed by 'sync init'
lsvault sync push <SYNC_ID>

The daemon runs in the background using a PID file and restarts automatically on reboot when installed as a system service. Stop it with lsvault sync daemon stop.

Tips & Best Practices

Folder Structure

Keep posts under a posts/ directory and static assets (images, attachments) under assets/. A clean layout makes bulk operations easier:

my-blog/
├── posts/
│   ├── 2026-03-01-hello-world.md
│   └── 2026-03-15-second-post.md
└── assets/
    └── hello-world-og.png

Frontmatter Best Practices

  • Always include title, date, and description — they drive listing pages and SEO
  • Use ISO 8601 dates (YYYY-MM-DD) so sorting works correctly
  • Prefix filenames with the date for natural filesystem ordering

Tags as Categories

Tags are first-class citizens in Lifestream Vault. Visitors can filter the vault listing by tag, so use consistent, lowercase tags (e.g. typescript, tutorial, release-notes).

In Settings → Vault → Search, enable full-text indexing so visitors can search your posts instantly via the built-in search bar.

Webhooks for Build Triggers

If you run a static site generator alongside your vault, configure a webhook (Settings → Webhooks → New) on document.created and document.updated events to trigger an external build pipeline automatically.

Image Hosting

Lifestream Vault does not host binary assets. For images referenced in posts, use a CDN (Cloudflare R2, Cloudinary, or a public GitHub repo with raw.githubusercontent.com URLs).

What's Next

You now have a live Markdown blog backed by Lifestream Vault. Here are some places to go next:

  • SDK Publish Reference — full API surface for client.publish, client.publishVault, and client.customDomains
  • CLI Publish Commands — all lsvault publish-vault and lsvault publish flags
  • Custom domains are configured in Settings → Domains.
  • Automate Your Vault — fire outbound HTTP events on document publish, update, and delete
  • Sync with Cloud Storage — conflict resolution, .lsvaultignore patterns, and bidirectional sync
  • SEO metadata is configured in the vault's publish settings.