CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-gatsby-plugin-page-creator

Gatsby plugin that automatically creates pages from React components in specified directories

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

file-system-routes.mddocs/

File System Routes

Advanced routing patterns for creating data-driven pages and client-side routes using special file naming conventions. The File System Route API enables automatic page generation from GraphQL data sources.

Capabilities

Collection Routes

Create pages programmatically from GraphQL data using {Model.field} syntax in file names.

/**
 * Collection route syntax: {NodeType.field}
 * File: /blog/{MarkdownRemark.frontmatter__slug}.js
 * Creates: /blog/my-post/, /blog/another-post/, etc.
 * 
 * @param NodeType - GraphQL node type (e.g. MarkdownRemark, File, ContentfulBlogPost)
 * @param field - Node field path using __ for nested fields (e.g. frontmatter__slug)
 */

Usage Examples:

// File: src/pages/blog/{MarkdownRemark.frontmatter__slug}.js
// Creates pages like: /blog/my-first-post/, /blog/getting-started/
import React from "react";
import { graphql } from "gatsby";

export default function BlogPost({ data }) {
  const { markdownRemark } = data;
  return (
    <div>
      <h1>{markdownRemark.frontmatter.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: markdownRemark.html }} />
    </div>
  );
}

export const query = graphql`
  query($id: String!) {
    markdownRemark(id: { eq: $id }) {
      html
      frontmatter {
        title
        slug
      }
    }
  }
`;
// File: src/pages/products/{ShopifyProduct.handle}.js  
// Creates pages like: /products/t-shirt/, /products/sneakers/
import React from "react";
import { graphql } from "gatsby";

export default function Product({ data }) {
  const { shopifyProduct } = data;
  return (
    <div>
      <h1>{shopifyProduct.title}</h1>
      <p>${shopifyProduct.priceRange.minVariantPrice.amount}</p>
    </div>
  );
}

export const query = graphql`
  query($id: String!) {
    shopifyProduct(id: { eq: $id }) {
      title
      handle
      priceRange {
        minVariantPrice {
          amount
        }
      }
    }
  }
`;

Nested Collection Routes

Create nested URL structures using multiple collection segments.

/**
 * Nested collection route syntax
 * File: /blog/{MarkdownRemark.frontmatter__category}/{MarkdownRemark.frontmatter__slug}.js
 * Creates: /blog/tutorials/getting-started/, /blog/news/announcement/
 */

Usage Example:

// File: src/pages/blog/{MarkdownRemark.frontmatter__category}/{MarkdownRemark.frontmatter__slug}.js
import React from "react";
import { graphql } from "gatsby";

export default function CategorizedPost({ data, params }) {
  const { markdownRemark } = data;
  const { category, slug } = params; // Available via context
  
  return (
    <div>
      <nav>Category: {category}</nav>
      <h1>{markdownRemark.frontmatter.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: markdownRemark.html }} />
    </div>
  );
}

Union Type Routes

Handle GraphQL union types in collection routes using (UnionType) syntax.

/**
 * Union type collection route syntax
 * File: /content/{ContentfulBlogPost.slug__(ContentfulBlogPost)__category}.js
 * Handles: ContentfulBlogPost union types with specific field access
 */

Client-Only Routes

Create client-side routes that bypass Gatsby's static generation using [param] syntax.

/**
 * Client-only route syntax: [param] or [...]
 * File: /app/[...].js -> /app/* (catch-all client route)
 * File: /user/[id].js -> /user/:id (parameterized client route)
 * 
 * @param param - Parameter name for React Router-style routing
 * @param ... - Catch-all parameter for wildcard routes
 */

Usage Examples:

// File: src/pages/app/[...].js
// Handles all routes under /app/* on the client
import React from "react";
import { Router } from "@reach/router";
import Dashboard from "../components/Dashboard";
import Profile from "../components/Profile";

export default function App() {
  return (
    <Router basepath="/app">
      <Dashboard path="/" />
      <Profile path="/profile" />
    </Router>
  );
}
// File: src/pages/user/[id].js  
// Handles routes like /user/123, /user/abc on the client
import React from "react";
import { useParams } from "@reach/router";

export default function UserProfile() {
  const { id } = useParams();
  return <h1>User Profile: {id}</h1>;
}

GatsbyPath GraphQL Field

Programmatically generate paths for collection routes using the gatsbyPath field.

/**
 * GatsbyPath GraphQL field - automatically added to node types with collection routes
 * @param filePath - Collection route template path
 * @returns Generated URL path for the node
 */
interface NodeWithGatsbyPath {
  gatsbyPath(filePath: String!): String;
}

Usage Examples:

// Query example
export const query = graphql`
  query {
    allMarkdownRemark {
      nodes {
        id
        frontmatter {
          title
        }
        # Generate path using collection route template
        gatsbyPath(filePath: "/blog/{MarkdownRemark.frontmatter__slug}")
      }
    }
  }
`;
// Component usage
import React from "react";
import { Link, graphql } from "gatsby";

export default function BlogIndex({ data }) {
  return (
    <div>
      <h1>Blog Posts</h1>
      {data.allMarkdownRemark.nodes.map((post) => (
        <div key={post.id}>
          <Link to={post.gatsbyPath}>
            {post.frontmatter.title}
          </Link>
        </div>
      ))}
    </div>
  );
}

Route Processing

Path Derivation

How collection route paths are generated from node data.

/**
 * Main path derivation function for converting collection routes to URLs
 * @param filePath - Template file path with {Model.field} syntax
 * @param nodeData - GraphQL node data containing field values
 * @param reporter - Gatsby reporter for logging errors
 * @param slugifyOptions - URL slugification options
 * @param getFieldValue - Optional field value accessor for GraphQL context
 * @returns Object with generated path and error count
 */
function derivePath(
  filePath: string,
  nodeData: Record<string, any>,
  reporter: Reporter,
  slugifyOptions?: ISlugifyOptions,
  getFieldValue?: (node: Record<string, any>, fieldPath: string) => any
): Promise<{ derivedPath: string; errors: number }>;

Path Generation Process:

  1. Remove file extension from template path
  2. Extract collection segments using {Model.field} pattern
  3. For each segment, resolve the field value from node data
  4. Apply slugification to field values for URL-safe paths
  5. Replace template segments with actual values
  6. Clean up double slashes and handle index routes

Field Access Patterns

How to access nested fields in collection routes.

/**
 * Field access patterns
 * - Simple field: {Model.field}
 * - Nested field: {Model.parent__child}  
 * - Array access: {Model.tags[0]}
 * - Union type: {Model.field__(UnionType)__subfield}
 */

Examples:

// Simple field access
// File: {MarkdownRemark.frontmatter__slug}.js
// Accesses: node.frontmatter.slug

// Nested field access  
// File: {File.parent__(MarkdownRemark)__frontmatter__title}.js
// Accesses: node.parent.frontmatter.title (with union type check)

// Complex nested access
// File: {ContentfulBlogPost.author__profile__slug}.js  
// Accesses: node.author.profile.slug

Route Validation

The plugin validates route templates and reports errors for invalid patterns.

/**
 * Route validation errors
 */
enum RouteValidationErrors {
  /** Invalid collection route GraphQL syntax */
  CollectionGraphQL = "12102",
  /** Invalid collection route structure */
  CollectionBuilder = "12103", 
  /** Path generation failed */
  GeneratePath = "12104",
  /** Invalid collection path format */
  CollectionPath = "12105"
}

docs

advanced-usage.md

configuration.md

file-system-routes.md

index.md

tile.json