Skip to main content

post

The post schematic (also available as add-post) creates a new markdown file for blog posts or other content with frontmatter metadata.

Usage

Basic Usage

ng generate @scullyio/init:post --name="My Post Title"

Short Form

ng g @scullyio/init:post --name="My First Post"

Using Alias

ng g @scullyio/init:add-post --name="My Post"

Interactive Mode

If you don’t provide the name option, you’ll be prompted:
ng g @scullyio/init:post
? What title do you want to use for the post? My Post Title
? What's the target folder for this post? blog

Options

--name (required)

  • Type: string
  • Default: "blog-X"
  • Description: The title of the blog post
  • Prompt: “What title do you want to use for the post?”
This becomes both the post title in the frontmatter and part of the filename (dasherized).
ng g @scullyio/init:post --name="Getting Started with Scully"
Creates: blog/getting-started-with-scully.md

--target

  • Type: string
  • Default: "blog"
  • Description: The target directory where the post file will be created
  • Prompt: “What’s the target folder for this post?”
Specify a different content folder:
ng g @scullyio/init:post --name="My Post" --target="articles"
Creates: articles/my-post.md

--extension

  • Type: string
  • Default: "md"
  • Description: The file extension for the post file
Create a markdown file with a different extension:
ng g @scullyio/init:post --name="My Post" --extension="mdx"
Creates: blog/my-post.mdx Supported extensions:
  • md - Standard Markdown
  • mdx - MDX (Markdown with JSX)
  • Any alphanumeric extension

--metaDataFile

  • Type: string
  • Default: "" (empty)
  • Description: Path to a YAML or JSON file with metadata template to include in the post frontmatter
Use a custom metadata template:
ng g @scullyio/init:post --name="My Post" --metaDataFile="./templates/post-template.yml"
The metadata file can contain additional frontmatter fields like author, tags, category, etc.

What Gets Created

The post schematic creates a single markdown file with YAML frontmatter.

Default Post Structure

File: blog/[dasherized-title].md For example, running:
ng g @scullyio/init:post --name="My First Post"
Creates: blog/my-first-post.md Content:
---
title: My First Post
description: blog description
published: false
---

# My First Post

Frontmatter Fields

The default frontmatter includes:
  • title - The post title (from --name option)
  • description - Default placeholder description
  • published - Boolean flag set to false by default
Scully only processes routes with published: true, so remember to update this before building.

Using Custom Metadata Template

Create a template file with additional metadata: File: templates/post-meta.yml
author: John Doe
tags:
  - angular
  - scully
category: tutorial
image: /assets/default-post.jpg
published: false
Then create a post using this template:
ng g @scullyio/init:post --name="Advanced Routing" --metaDataFile="./templates/post-meta.yml"
Result: blog/advanced-routing.md
---
title: Advanced Routing
author: John Doe
tags:
  - angular
  - scully
category: tutorial
image: /assets/default-post.jpg
published: false
---

# Advanced Routing
Note: The title field from --name will override any title in the metadata file.

Filename Generation

The schematic generates filenames by:
  1. Dasherizing the post name (converting to kebab-case)
  2. Removing invalid characters
  3. Adding the specified extension
Examples:
NameTargetExtensionFilename
”My First Post”blogmdblog/my-first-post.md
”Getting Started!“articlesmdarticles/getting-started.md
”Angular & Scully”blogmdxblog/angular-scully.mdx
”Post #1”tutorialsmdtutorials/post-1.md

Validation

File Extension Validation

The schematic validates that the extension contains only alphanumeric characters:
ng g @scullyio/init:post --name="Test" --extension="md!"
# Error: md! is not a valid file extension

Duplicate Post Check

If a file with the same name already exists, the schematic will throw an error:
ng g @scullyio/init:post --name="My Post"
# Error: my-post exist in your blog folder

Examples

Simple Blog Post

ng g @scullyio/init:post --name="Introduction to Scully"
Output:
✅️ Blog ./blog/introduction-to-scully.md file created
CREATE blog/introduction-to-scully.md (85 bytes)

Post in Custom Folder

ng g @scullyio/init:post --name="API Overview" --target="documentation"
Output:
✅️ Blog ./documentation/api-overview.md file created
CREATE documentation/api-overview.md (79 bytes)

MDX Post with Custom Metadata

ng g @scullyio/init:post \
  --name="React Components in Angular" \
  --extension="mdx" \
  --metaDataFile="./templates/advanced-meta.yml"

Multiple Posts

Create multiple posts quickly:
ng g @scullyio/init:post --name="Post 1"
ng g @scullyio/init:post --name="Post 2"
ng g @scullyio/init:post --name="Post 3"

Writing Your Post

After creating a post, edit the markdown file:
  1. Update the frontmatter:
    ---
    title: My First Post
    description: Learn how to use Scully with Angular
    published: true  # Set to true when ready
    author: Your Name
    date: 2024-03-15
    ---
    
  2. Write your content:
    # My First Post
    
    Welcome to my blog post about Scully!
    
    ## Getting Started
    
    Here's what you need to know...
    
  3. Build and preview:
    ng build
    npm run scully
    npm run scully:serve
    

Frontmatter Best Practices

Required Fields

While Scully is flexible, consider these essential fields:
---
title: "Your Post Title"
description: "SEO-friendly description"
published: true
date: 2024-03-15
author: "Your Name"
---

Optional Fields

Extend your posts with additional metadata:
---
title: "Advanced Scully Features"
description: "Deep dive into Scully plugins"
published: true
date: 2024-03-15
author: "Jane Doe"
tags:
  - scully
  - angular
  - plugins
category: "tutorial"
image: "/assets/blog/scully-plugins.jpg"
readingTime: 10
---

Accessing Metadata in Components

Access post metadata in your Angular components:
import { ScullyRoutesService, ScullyRoute } from '@scullyio/ng-lib';

export class BlogComponent {
  constructor(private scully: ScullyRoutesService) {
    this.scully.getCurrent().subscribe((route: ScullyRoute) => {
      console.log('Title:', route.title);
      console.log('Published:', route.published);
      console.log('Custom:', route.customField);
    });
  }
}

Target Directory Structure

The target directory must exist or be configured in your Scully config: Scully config:
routes: {
  '/blog/:slug': {
    type: 'contentFolder',
    slug: { folder: './blog' }
  },
  '/articles/:slug': {
    type: 'contentFolder',
    slug: { folder: './articles' }
  }
}
Now you can create posts in either folder:
ng g @scullyio/init:post --name="Blog Post" --target="blog"
ng g @scullyio/init:post --name="Article" --target="articles"

See Also

Build docs developers (and LLMs) love