Spaceship
#tutorial#blogging#spaceship

How to Publish Posts in Spaceship

Complete guide to creating and publishing blog posts, including frontmatter options, image handling, and advanced features.

This guide covers everything you need to know about creating and publishing blog posts in Spaceship.

#Creating a New Post

Posts are stored in site/content/posts/ as Markdown (.md) or MDX (.mdx) files.

#File Naming

  • Use kebab-case: my-awesome-post.md
  • File name becomes the URL slug: /posts/my-awesome-post
  • Files starting with _ are ignored

#Basic Post Structure

---
title: 'Your Post Title'
description: 'A brief description for SEO and previews'
pubDate: 2026-02-01
tags: ['astro', 'svelte', 'tutorial']
---

Your content goes here in Markdown or MDX format.

#Frontmatter Options

#Required Fields

  • title: Post title (string)
  • description: Brief description for SEO and social sharing (string)
  • pubDate: Publication date (YYYY-MM-DD format)

#Optional Fields

  • tags: Array of tags (default: ["others"])

    tags: ['astro', 'svelte', 'tutorial']
  • featured: Mark post as featured on homepage (boolean, default: false)

    featured: true
  • draft: Mark post as draft (boolean, default: false)

    draft: true

    Draft posts behavior:

    • Development: Visible with a “DRAFT” badge
    • Production: Hidden completely
  • updatedDate: Last update date (YYYY-MM-DD format)

    updatedDate: 2026-02-05
  • ogImage: Custom Open Graph image path (string)

    ogImage: '/images/custom-og.png'
  • canonicalURL: Canonical URL for cross-posted content (string)

    canonicalURL: 'https://example.com/original-post'
  • showCTA: Show/hide CTA block (boolean, default: true)

    showCTA: false
  • showComments: Show/hide comments section (boolean, default: true)

    showComments: false
  • series: Group posts into a series (object)

    series:
      id: 'astro-guide'
      order: 1

#Draft Posts & Publication Date Filtering

Spaceship supports two ways to control post visibility:

#Draft Mode

Mark posts as drafts to hide them in production:

draft: true

Behavior:

  • Development (pnpm dev): Draft posts are visible with a yellow “DRAFT” badge
  • Production (pnpm build): Draft posts are completely hidden

Perfect for:

  • Work-in-progress posts
  • Posts awaiting review
  • Unfinished content

#Future-Dated Posts

Posts with future publication dates behave differently based on environment:

pubDate: 2026-03-15 # Future date

Behavior:

  • Development (pnpm dev): All posts visible, regardless of date
  • Production (pnpm build): Only posts with pubDate <= today are shown

Perfect for:

  • Scheduling posts for future publication
  • Planning content calendar
  • Time-sensitive announcements

#Combined Approach

You can use both approaches together:

draft: true # Hide in production
pubDate: 2026-03-15 # Schedule for future

This post will:

  • Show in development with “DRAFT” badge
  • Remain hidden in production until March 15, 2026
  • Automatically publish on that date (if draft: false is set)

#Working with Images

#Local Images

Store images in src/assets/ and import them:

---
title: 'Post with Images'
---

import myImage from '@/assets/my-image.png';
import { Image } from 'astro:assets';

<Image src={myImage} alt="Description" />

#Public Images

Place images in public/images/ and reference directly:

![Alt text](/images/my-image.png)

#Remote Images

![Alt text](https://example.com/image.png)

#Image Optimization Tips

  1. Use WebP or AVIF for better compression
  2. Optimize before upload - use tools like ImageOptim or Squoosh
  3. Use descriptive alt text for accessibility and SEO
  4. Consider lazy loading for performance

#Working with Files

#Downloadable Files

Place files in public/files/ and link to them:

[Download PDF](/files/my-document.pdf)

#Code Files

For syntax-highlighted code snippets:

```javascript
function hello() {
  console.log('Hello, World!');
}
```

Or import and display code files using MDX.

#Series Posts

Create a series of related posts:

---
title: 'Getting Started with Astro - Part 1'
series:
  id: 'astro-guide'
  order: 1
---
---
title: 'Getting Started with Astro - Part 2'
series:
  id: 'astro-guide'
  order: 2
---

All posts in the same series will show navigation links to other posts.

#Advanced Features

#MDX Support

Use .mdx extension to import components:

---
title: 'Interactive Post'
---

import MyComponent from '@/components/MyComponent.svelte';

<MyComponent client:load />

#Custom CTA

The CTA (Call-to-Action) block at the end of posts is customizable via site/cta.md. To disable it for a specific post:

showCTA: false

#Comments

Comments (via Giscus) can be disabled per post:

showComments: false

#SEO Best Practices

  1. Write descriptive titles (50-60 characters)
  2. Craft compelling descriptions (150-160 characters)
  3. Use relevant tags (3-5 tags per post)
  4. Add alt text to images
  5. Use heading hierarchy (H1 → H2 → H3)
  6. Include internal links to related posts
  7. Set canonical URLs for cross-posted content

#Publishing Workflow

  1. Create post in site/content/posts/
  2. Add frontmatter with required fields
  3. Write content in Markdown/MDX
  4. Test locally with pnpm dev
  5. Preview at http://localhost:4321/posts/your-post-slug
  6. Commit and push to deploy

#Quick Reference

#Minimal Post

---
title: 'Hello World'
description: 'My first post'
pubDate: 2026-02-01
---

Hello, World!

#Full-Featured Post

---
title: 'Complete Guide to Astro'
description: 'Everything you need to know about Astro framework'
pubDate: 2026-02-01
updatedDate: 2026-02-05
tags: ['astro', 'tutorial', 'web-development']
featured: true
ogImage: '/images/astro-guide-og.png'
series:
  id: 'astro-series'
  order: 1
---

Content here...

Pro Tip: Use the VSCode frontmatter snippet to quickly create post templates!

Share this post