Repository: atomicdata-dev/atomic-server (language: rust)

Issue:
create-template gives the wrong error when drive is not public
If the given drive is not public, create-template will fail. The error message it gives suggests something else to the user:

> The website template does not exist on your drive. To get the template go to the Create Resource page and select the website template

It should give a clear error like: 'The given drive is not public so @tomic/create-template can't fetch it' 


Discussion / hints:

Fix patch:
diff --git a/browser/CHANGELOG.md b/browser/CHANGELOG.md
index cd92052a0..97cd05a6f 100644
--- a/browser/CHANGELOG.md
+++ b/browser/CHANGELOG.md
@@ -54,6 +54,7 @@ This changelog covers all five packages, as they are (for now) updated as a whol
 
 - [#700](https://github.com/atomicdata-dev/atomic-server/issues/700) Update SvelteKit-site template to Svelte 5 and the new @tomic/svelte.
 - [#966](https://github.com/atomicdata-dev/atomic-server/issues/966) Add NextJS template.
+- [#1036](https://github.com/atomicdata-dev/atomic-server/issues/1036) Provide clearer errors when resources couldn't be fetched.
 - [#993](https://github.com/atomicdata-dev/atomic-server/issues/993) Fix template not working when the drive subject has a path after the origin.
 
 ## [v0.40.0] - 2024-10-07
diff --git a/browser/create-template/src/postprocess.ts b/browser/create-template/src/postprocess.ts
index 8094d732d..9596078ee 100644
--- a/browser/create-template/src/postprocess.ts
+++ b/browser/create-template/src/postprocess.ts
@@ -1,6 +1,6 @@
 import path from 'node:path';
 import fs from 'node:fs';
-import { Store, type Resource } from '@tomic/lib';
+import { ErrorType, isAtomicError, Store, type Resource } from '@tomic/lib';
 import {
   type ExecutionContext,
   type TemplateKey,
@@ -31,9 +31,30 @@ export async function postProcess(context: PostProcessContext) {
   const ontology = await store.getResource(ontologySubject);
 
   if (ontology.error) {
-    console.error(
-      `\nThe ${baseTemplate.name} template does not exist on your drive. To get the template go to the Create Resource page and select the ${baseTemplate.name} template`,
-    );
+    if (isAtomicError(ontology.error)) {
+      switch (ontology.error.type) {
+        case ErrorType.NotFound:
+          console.error(
+            `\nThe ${baseTemplate.name} template does not exist on your drive. To get the template go to the Create Resource page and select the ${baseTemplate.name} template`,
+          );
+          break;
+        case ErrorType.Unauthorized:
+          console.error(
+            '\nSome of the template resources could not be accessed. Make sure the resources are public.',
+          );
+          break;
+        case ErrorType.Server:
+          console.error(
+            '\nServer Error: Something went wrong while fetching the template.',
+          );
+          break;
+        default:
+          console.error('\nAn error occurred while fetching the template.');
+      }
+    } else {
+      console.error(ontology.error.message);
+    }
+
     process.exit(1);
   }
 
diff --git a/browser/create-template/templates/nextjs-site/src/components/MarkdownContent.tsx b/browser/create-template/templates/nextjs-site/src/components/MarkdownContent.tsx
index 398ec92e5..44a4a81ae 100644
--- a/browser/create-template/templates/nextjs-site/src/components/MarkdownContent.tsx
+++ b/browser/create-template/templates/nextjs-site/src/components/MarkdownContent.tsx
@@ -13,21 +13,23 @@ import styles from '@/views/Block/TextBlock.module.css';
  */
 export const MarkdownContent = ({
   subject,
-  initialContent,
+  initialValue,
 }: {
   subject: string;
-  initialContent: string | TrustedHTML;
+  initialValue: string;
 }) => {
   const resource = useResource<TextBlock>(subject);
 
-  const matterResult = matter(resource.props.description ?? '');
+  const matterResult = matter(
+    resource.loading ? initialValue : resource.props.description,
+  );
   const processed = remark().use(html).processSync(matterResult.content);
 
   return (
     <div
       className={styles.wrapper}
       dangerouslySetInnerHTML={{
-        __html: resource.loading ? initialContent : processed.toString(),
+        __html: processed.toString(),
       }}
     />
   );
diff --git a/browser/create-template/templates/nextjs-site/src/views/Block/TextBlock.tsx b/browser/create-template/templates/nextjs-site/src/views/Block/TextBlock.tsx
index 989854715..2322f3117 100644
--- a/browser/create-template/templates/nextjs-site/src/views/Block/TextBlock.tsx
+++ b/browser/create-template/templates/nextjs-site/src/views/Block/TextBlock.tsx
@@ -1,19 +1,12 @@
 import { Resource } from '@tomic/react';
-import { remark } from 'remark';
-import html from 'remark-html';
-import matter from 'gray-matter';
 import { MarkdownContent } from '@/components/MarkdownContent';
+import type { TextBlock as TextBlockType } from '@/ontologies/website';
 
-const TextBlock = ({ resource }: { resource: Resource }) => {
-  const matterResult = matter(resource.props.description);
-
-  const processed = remark().use(html).processSync(matterResult.content);
-
-  const initialContent = processed.toString();
+const TextBlock = ({ resource }: { resource: Resource<TextBlockType> }) => {
   return (
     <MarkdownContent
       subject={resource.subject}
-      initialContent={initialContent}
+      initialValue={resource.props.description}
     />
   );
 };
diff --git a/browser/create-template/templates/nextjs-site/src/views/FullPage/BlogpostFullPage.tsx b/browser/create-template/templates/nextjs-site/src/views/FullPage/BlogpostFullPage.tsx
index 66a787104..2bf48dd38 100644
--- a/browser/create-template/templates/nextjs-site/src/views/FullPage/BlogpostFullPage.tsx
+++ b/browser/create-template/templates/nextjs-site/src/views/FullPage/BlogpostFullPage.tsx
@@ -1,11 +1,8 @@
 import Container from '@/components/Layout/Container';
-import { Blogpost } from '@/ontologies/website';
+import type { Blogpost } from '@/ontologies/website';
 import { Resource } from '@tomic/lib';
 import styles from './BlogpostFullPage.module.css';
 import { Image } from '@/components/Image';
-import matter from 'gray-matter';
-import html from 'remark-html';
-import { remark } from 'remark';
 import { MarkdownContent } from '@/components/MarkdownContent';
 
 const formatter = new Intl.DateTimeFormat('default', {
@@ -16,9 +13,6 @@ const formatter = new Intl.DateTimeFormat('default', {
 
 const BlogpostFullPage = ({ resource }: { resource: Resource<Blogpost> }) => {
   const date = formatter.format(new Date(resource.props.publishedAt));
-  const matterResult = matter(resource.props.description);
-  const processed = remark().use(html).processSync(matterResult.content);
-  const initialContent = processed.toString();
 
   return (
     <Container>
@@ -31,7 +25,7 @@ const BlogpostFullPage = ({ resource }: { resource: Resource<Blogpost> }) => {
           <p className={styles.publishDate}>{date}</p>
           <MarkdownContent
             subject={resource.subject}
-            initialContent={initialContent}
+            initialValue={resource.props.description}
           />
         </div>
       </div>


Test patch: