Page type works fine, post type does not (404 on front end) and I feel like I'm going crazy

I've been learning Prismic for the last couple of weeks and decided to try to add a "post" type custom page to the demo project I've been learning on. Page type pages work fine. For context, I go through the end of this tutorial video (https://www.youtube.com/watch?v=nfZu56KsK_Q) and even with slice machine changes found it only minimally challenging.

Which is why this has me totally stumped.

Everything appears to be set up correctly in my type and my configuration is pushed. My dev and production routes work for everything up until this point... but posts 404. Let me share some code with you.

/app/[uid]/posts/post.tsx

import { Metadata } from "next";
import { notFound } from "next/navigation";
import { SliceZone } from "@prismicio/react";

import { createClient } from "@/prismicio";
import { components } from "@/slices";

type Params = { uid: string };

export default async function PostPage({ params }: { params: Params }) {
  const client = createClient();
  const post = await client
    .getByUID("post", params.uid)
    .catch(() => notFound());

  return <SliceZone slices={post.data.slices} components={components} />;
}

export async function generateMetadata({
  params,
}: {
  params: Params;
}): Promise<Metadata> {
  const client = createClient();
  const post = await client
    .getByUID("post", params.uid)
    .catch(() => notFound());

  return {
    title: post.data.meta_title,
    description: post.data.meta_description,
  };
}

export async function generateStaticParams() {
  const client = createClient();
  const posts = await client.getAllByType("post");

  return posts.map((post) => {
    return { uid: post.uid };
  });
}

prismicio.ts

import * as prismic from "@prismicio/client";
import * as prismicNext from "@prismicio/next";
import config from "./slicemachine.config.json";

/**
 * The project's Prismic repository name.
 */
export const repositoryName =
  process.env.NEXT_PUBLIC_PRISMIC_ENVIRONMENT || config.repositoryName;

/**
 * A list of Route Resolver objects that define how a document's `url` field is resolved.
 *
 * {@link https://prismic.io/docs/route-resolver#route-resolver}
 */

const routes: prismic.ClientConfig["routes"] = [
  {
    type: "homepage",
    path: "/",
  },
  {
    type: "page",
    path: "/:uid",
  },
  {
    type: "post",
    path: "/posts/:uid",
  },
];

/**
 * Creates a Prismic client for the project's repository. The client is used to
 * query content from the Prismic API.
 *
 * @param config - Configuration for the Prismic client.
 */
export const createClient = (config: prismicNext.CreateClientConfig = {}) => {
  const client = prismic.createClient(repositoryName, {
    routes,
    fetchOptions:
      process.env.NODE_ENV === "production"
        ? { next: { tags: ["prismic"] }, cache: "force-cache" }
        : { next: { revalidate: 5 } },
    ...config,
  });

  prismicNext.enableAutoPreviews({
    client,
    previewData: config.previewData,
    req: config.req,
  });

  return client;
};

The route successfully opens at http://localhost:3000/posts/making-a-blog-work and layout.tsx applies to the page... but damned if it isn't a 404 every time.

My assumption is that .getByUID("post", params.uid) is returning empty and causing .catch(() => notFound()); to trigger.

But neither me nor my IDE can figure out why. If it was a base configuration error the rest of the site wouldn't be working... but it does.

This works fine:

/app/[uid]/page.tsx

import { Metadata } from "next";
import { notFound } from "next/navigation";
import { SliceZone } from "@prismicio/react";

import { createClient } from "@/prismicio";
import { components } from "@/slices";

type Params = { uid: string };

export default async function Page({ params }: { params: Params }) {
  const client = createClient();
  const page = await client
    .getByUID("page", params.uid)
    .catch(() => notFound());

  return <SliceZone slices={page.data.slices} components={components} />;
}

export async function generateMetadata({
  params,
}: {
  params: Params;
}): Promise<Metadata> {
  const client = createClient();
  const page = await client
    .getByUID("page", params.uid)
    .catch(() => notFound());

  return {
    title: page.data.meta_title,
    description: page.data.meta_description,
  };
}

export async function generateStaticParams() {
  const client = createClient();
  const pages = await client.getAllByType("page");

  return pages.map((page) => {
    return { uid: page.uid };
  });
}

Impacted feature

Page Types

What steps have you taken to resolve this issue already?

Tearing it down and rebuilding it 3 times with the same issue

Errors

Literally none that I can identify

Your Role

Frustrated student and agency owner

Hosting provider

Localhost/Vercel (same error in both places)

Package.json file

{
  "name": "flowrise-prismic",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "slicemachine": "start-slicemachine"
  },
  "dependencies": {
    "@prismicio/client": "^7.7.3",
    "@prismicio/next": "^1.6.0",
    "@prismicio/react": "^2.8.0",
    "clsx": "^2.1.1",
    "next": "14.2.5",
    "react": "^18",
    "react-dom": "^18"
  },
  "devDependencies": {
    "@slicemachine/adapter-next": "^0.3.43",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "babel-plugin-module-resolver": "^5.0.2",
    "eslint": "^8",
    "eslint-config-next": "14.2.5",
    "postcss": "^8",
    "slice-machine-ui": "^2.3.0",
    "tailwindcss": "^3.4.1",
    "typescript": "^5"
  }
}

Steps to reproduce

Honestly I'll just share my git repo if it comes to that


I'm hoping somebody can tell me why the system sees the document but the front end doesn't.

Hi @ian6

Not an expert nor a Prismic employee here, but I wanted to offer my thoughts on this.

I believe the reason you're seeing a 404 is that you're using an unsupported file name inside the app router. There are reserved file names that we all must use in the app router. Even though you're creating a post, for all intents and purposes, it's a page in Next's "eyes." Typically, when I setup posts, my folders look as follows:

file tree from VS Code showing page.tsx inside of blog folder

So each route will likely have a page.tsx file inside of it (even if it's a "post").
Did that help?

1 Like

Resolved! Thank you! My mild dyscalculia sometimes kicks in when I'm learning new things and that, right there, was a perfect example.

1 Like