# Editorial Calendar Screen

> Adds a Posts > Calendar screen showing a month grid of published, scheduled and draft posts on their dates, with links to edit each one and arrows to move between months.

- Type: PHP
- Runs: Admin only
- Category: [Content](https://wpide.com/library/category/content/)
- Tags: editorial, calendar, scheduling
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/content-editorial-calendar/

## Code

```php
add_action( 'admin_menu', function () {
    add_posts_page( 'Editorial Calendar', 'Calendar', 'edit_posts', 'wpide-calendar', function () {
        $month = isset( $_GET['month'] ) && preg_match( '/^\d{4}-\d{2}$/', $_GET['month'] ) ? sanitize_text_field( wp_unslash( $_GET['month'] ) ) : wp_date( 'Y-m' );
        $first = new DateTimeImmutable( $month . '-01', wp_timezone() );
        $last  = $first->modify( 'last day of this month' );

        $posts = get_posts( array(
            'post_type'      => 'post',
            'post_status'    => array( 'publish', 'future', 'draft', 'pending' ),
            'posts_per_page' => 300,
            'no_found_rows'  => true,
            'date_query'     => array( array( 'after' => $first->format( 'Y-m-d 00:00:00' ), 'before' => $last->format( 'Y-m-d 23:59:59' ), 'inclusive' => true ) ),
        ) );

        $by_day = array();
        foreach ( $posts as $post ) {
            $by_day[ (int) mysql2date( 'j', $post->post_date ) ][] = $post;
        }

        $colors = array( 'publish' => '#00a32a', 'future' => '#2271b1', 'draft' => '#8c8f94', 'pending' => '#dba617' );
        $nav    = function ( $offset, $label ) use ( $first ) {
            return sprintf( '<a class="button" href="%s">%s</a>', esc_url( add_query_arg( array( 'page' => 'wpide-calendar', 'month' => $first->modify( $offset . ' month' )->format( 'Y-m' ) ), admin_url( 'edit.php' ) ) ), esc_html( $label ) );
        };

        echo '<div class="wrap"><h1>Editorial Calendar</h1>';
        printf( '<p style="display:flex;gap:8px;align-items:center">%s <strong style="font-size:16px">%s</strong> %s</p>', $nav( -1, '&larr; Previous' ), esc_html( wp_date( 'F Y', $first->getTimestamp() ) ), $nav( 1, 'Next &rarr;' ) );
        echo '<div style="display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:4px">';

        $start_of_week = (int) get_option( 'start_of_week', 1 );
        for ( $i = 0; $i < 7; $i++ ) {
            printf( '<div style="font-weight:600;padding:4px">%s</div>', esc_html( $GLOBALS['wp_locale']->get_weekday_abbrev( $GLOBALS['wp_locale']->get_weekday( ( $start_of_week + $i ) % 7 ) ) ) );
        }
        $blank = ( (int) $first->format( 'w' ) - $start_of_week + 7 ) % 7;
        echo str_repeat( '<div></div>', $blank );

        for ( $day = 1; $day <= (int) $last->format( 'j' ); $day++ ) {
            echo '<div style="background:#fff;border:1px solid #dcdcde;min-height:90px;padding:4px;overflow:hidden"><div style="color:#646970">' . (int) $day . '</div>';
            foreach ( $by_day[ $day ] ?? array() as $post ) {
                printf(
                    '<a href="%s" style="display:block;font-size:12px;margin-top:3px;padding:2px 4px;border-left:3px solid %s;text-decoration:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis" title="%s">%s</a>',
                    esc_url( get_edit_post_link( $post ) ),
                    esc_attr( $colors[ $post->post_status ] ?? '#8c8f94' ),
                    esc_attr( get_the_title( $post ) . ' (' . $post->post_status . ')' ),
                    esc_html( get_the_title( $post ) ? get_the_title( $post ) : '(no title)' )
                );
            }
            echo '</div>';
        }
        echo '</div></div>';
    } );
} );
```

## Notes

Drafts appear on their last modified date in grey; scheduled posts in blue.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Editorial Calendar Screen" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
