Skip to content

Commit

Permalink
preview mode, done only for prod, dev shows drafts always
Browse files Browse the repository at this point in the history
  • Loading branch information
nemanjam committed Jun 22, 2024
1 parent 5d73c52 commit d3d5207
Show file tree
Hide file tree
Showing 18 changed files with 347 additions and 49 deletions.
5 changes: 5 additions & 0 deletions .env.development.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
# SSG - ALL env vars are BUILD time ONLY

# must have https:// or http://
SITE_URL=http://localhost:3000

# always true in development, set only on prod build
# PREVIEW_MODE=
9 changes: 7 additions & 2 deletions .env.production.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# build time only, not needed at runtime
# SSG - ALL env vars are BUILD time ONLY

# with https://
# https://nemanjamitic.com | https://nemanjam.github.io
SITE_URL=https://nemanjam.github.io
SITE_URL=https://nemanjam.github.io

# see draft posts and projects, true | false | empty
# optional, default false, set only on prod build
# PREVIEW_MODE=
3 changes: 2 additions & 1 deletion docs/todo3.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ share
code blocks responsive fonts 14, 16px, md or lg?
pagination 3 items
styleguide
sitemap
sitemap
transistor favicon
rewrite env vars with new types and import.meta instead of process.env
```
2 changes: 2 additions & 0 deletions env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@ declare namespace NodeJS {
interface ProcessEnv {
NODE_ENV: 'development' | 'production' | 'test';
SITE_URL: string;
/** Optional in .env file but always defined in type. Default: false. */
PREVIEW_MODE: boolean;
}
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
"private": true,
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"start": "serve ./dist",
"preview": "astro preview",
"build": "astro build",
"build:nginx": "SITE_URL='https://nemanjamitic.com' astro build",
"build:nginx:local": "SITE_URL='https://blog.local.nemanjamitic.com' astro build",
"preview": "astro preview",
"astro": "astro",
"sync": "astro sync",
"lint": "eslint --ext .astro,.tsx,.ts,.js,.mdx src",
Expand Down Expand Up @@ -74,6 +74,7 @@
"eslint-plugin-tailwindcss": "^3.17.3",
"prettier": "^3.3.2",
"prettier-plugin-astro": "^0.14.0",
"serve": "^14.2.3",
"shiki": "^1.7.0",
"tailwindcss": "^3.4.4",
"typescript": "^5.4.5"
Expand Down
3 changes: 2 additions & 1 deletion src/components/PostCard.astro
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getPublishedOrUpdatedDate } from '@/modules/common';
import { getCategoryProps } from '@/modules/post/category';
import Link from '@/components/Link.astro';
import TagList from '@/components/TagList.astro';
import { draftText } from '@/constants/data';
import { ROUTES } from '@/constants/routes';
import { formatDate, formatDateIso } from '@/utils/datetime';
import { cn } from '@/utils/styles';
Expand Down Expand Up @@ -89,7 +90,7 @@ const { lastAccessDate, isUpdatedDate } = getPublishedOrUpdatedDate({
<h2 class="text-2xl font-bold break-words md:line-clamp-2 mt-0 mb-2">
<Link href={`${ROUTES.BLOG}${slug}`} variant="link-heading">
{title}
{draft && <sup class="text-sm text-red-400">(draft)</sup>}
{draft && <sup class="text-sm text-red-500 ml-1">{draftText}</sup>}
</Link>
</h2>

Expand Down
4 changes: 3 additions & 1 deletion src/components/PostCardMore.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { Image } from 'astro:assets';
import Link from '@/components/Link.astro';
import { draftText } from '@/constants/data';
import { ROUTES } from '@/constants/routes';
import type { Post } from '@/types/post';
Expand All @@ -12,7 +13,7 @@ export interface Props {
const { post } = Astro.props;
const { data, slug } = post;
const { title, heroImage, heroAlt, description } = data;
const { title, heroImage, heroAlt, description, draft } = data;
---

<div>
Expand All @@ -26,6 +27,7 @@ const { title, heroImage, heroAlt, description } = data;
<h4 class="break-words line-clamp-2 mt-3 mb-2">
<Link variant="link-heading" href={`${ROUTES.BLOG}${slug}`}>
{title}
{draft && <sup class="text-sm text-red-500 ml-1">{draftText}</sup>}
</Link>
</h4>
{description && <p class="text-base text-captions line-clamp-2">{description}</p>}
Expand Down
6 changes: 4 additions & 2 deletions src/components/PostCardSmall.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Image } from 'astro:assets';
import { getPublishedOrUpdatedDate } from '@/modules/common';
import Link from '@/components/Link.astro';
import { draftText } from '@/constants/data';
import { ROUTES } from '@/constants/routes';
import { formatDate, formatDateIso } from '@/utils/datetime';
import { cn } from '@/utils/styles';
Expand All @@ -17,7 +18,7 @@ export interface Props extends HTMLAttributes<'article'> {
const { post, class: className } = Astro.props;
const { data, slug } = post;
const { title, heroImage, heroAlt, description, publishDate, updatedDate, tags } = data;
const { title, heroImage, heroAlt, description, publishDate, updatedDate, draft } = data;
const { lastAccessDate, isUpdatedDate } = getPublishedOrUpdatedDate({
publishDate,
Expand All @@ -41,8 +42,9 @@ const { lastAccessDate, isUpdatedDate } = getPublishedOrUpdatedDate({
class="object-cover rounded-box hidden xs:block"
/>
<div>
<h4 class="text-xl line-clamp-1 leading-none mb-1">
<h4 class="text-xl leading-none line-clamp-1 mb-1">
<Link variant="link-heading" href={`${ROUTES.BLOG}${slug}`}>
{draft && <sup class="text-sm text-red-500 mr-1">{draftText}</sup>}
{title}
</Link>
</h4>
Expand Down
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ dotenv.config({ path: envFileName });

/*-------------------- configData -------------------*/

/** SSG - all env vars are build time only. */
const configData: ConfigType = {
NODE_ENV: process.env.NODE_ENV,
PREVIEW_MODE: process.env.PREVIEW_MODE,
/** without '/' */
SITE_URL: process.env.SITE_URL,
SITE_TITLE: 'Nemanja Mitic',
Expand Down
1 change: 1 addition & 0 deletions src/constants/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const draftText = '(draft)';
1 change: 1 addition & 0 deletions src/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const ROUTES = {
EXPLORE: '/blog/explore/',
EXPLORE_TAGS: '/blog/explore/tags/',
EXPLORE_CATEGORIES: '/blog/explore/categories/',
/** maybe in future */
DRAFTS: '/drafts/',
_404: '/404/',
_500: '/500/',
Expand Down
1 change: 1 addition & 0 deletions src/content/post/2024-01-21-example-article-5.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ tags:
- react
category: video
toc: true
draft: true
---

import { Icon } from 'astro-icon/components';
Expand Down
5 changes: 4 additions & 1 deletion src/libs/api/feed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getAllPosts } from '@/modules/post/common';
import { ROUTES } from '@/constants/routes';
import { CONFIG } from '@/config';
import { renderMarkdown } from '@/utils/markdown';
import { isPreviewMode } from '@/utils/preview';

import type { Item } from 'feed';

Expand Down Expand Up @@ -42,8 +43,10 @@ export const getFeed = async (): Promise<Feed> => {
const { data, body, slug } = post;
const { title, description, publishDate, heroImage, noHero, draft } = data;

const includeDrafts = isPreviewMode() && draft;

// omit drafts
if (draft) continue;
if (!includeDrafts) continue;

const url = `${SITE_URL}${ROUTES.BLOG}${slug}/`;
const { code: content } = await renderMarkdown(body);
Expand Down
8 changes: 6 additions & 2 deletions src/modules/common.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { getCollection } from 'astro:content';

import { isPreviewMode } from '@/utils/preview';

import type { CollectionEntry, CollectionKey } from 'astro:content';

/*-------------------------------- all entries ------------------------------*/
Expand All @@ -11,13 +13,15 @@ export interface GetAllEntriesOptions {

/**
* Sorts by publishDate desc by default. Newest on top.
* Omits drafts by default.
* Omits drafts by default - set by PREVIEW_MODE env var.
*
* ONLY place to filter draft posts and projects.
*/
export const getAllEntries = async <T extends CollectionKey>(
collectionName: T,
options?: GetAllEntriesOptions
): Promise<CollectionEntry<T>[]> => {
const { skipSort = false, includeDrafts = false } = options ?? {};
const { skipSort = false, includeDrafts = isPreviewMode() } = options ?? {};

const entries = await getCollection<T>(collectionName, ({ data }) => {
const isProdAndDraft = import.meta.env.PROD && data.draft;
Expand Down
3 changes: 2 additions & 1 deletion src/pages/blog/[slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import PostMeta from '@/components/PostMeta.astro';
import SharePost from '@/components/SharePost.astro';
import TagList from '@/components/TagList.astro';
import TocWidget from '@/components/TocWidget.astro';
import { draftText } from '@/constants/data';
import { getOpenGraphImagePath } from '@/utils/open-graph-image';
import type { Metadata } from '@/types/common';
Expand Down Expand Up @@ -88,7 +89,7 @@ const metadata: Metadata = { title, description, image };
{/* title */}
<h1>
{title}
{draft && <sup class="text-red-400">(draft)</sup>}
{draft && <sup class="text-red-500 ml-1">{draftText}</sup>}
</h1>

{/* description */}
Expand Down
7 changes: 6 additions & 1 deletion src/schemas/config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { z } from 'zod';

export const nodeEnvValues = ['development', 'test', 'production'] as const;
export const booleanValues = ['true', 'false', ''] as const;

export const configSchema = z.object({
NODE_ENV: z.enum(nodeEnvValues),
PREVIEW_MODE: z
.enum(booleanValues)
.transform((value) => value === 'true')
.default('false'),
// ensure no trailing slash
SITE_URL: z.string().url().regex(/[^/]$/, 'SITE_URL should not end with a slash'),
SITE_URL: z.string().url().regex(/[^/]$/, 'SITE_URL should not end with a slash "/"'),
SITE_TITLE: z.string().min(1),
SITE_DESCRIPTION: z.string().min(1),
PAGE_SIZE: z.object({
Expand Down
4 changes: 4 additions & 0 deletions src/utils/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { CONFIG } from '@/config';

/** independent from prod or dev */
export const isPreviewMode = () => CONFIG.PREVIEW_MODE === true;
Loading

0 comments on commit d3d5207

Please sign in to comment.