@fullstackdatasolutions/articles 0.2.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +99 -5
- package/dist/index.cjs +379 -106
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -1
- package/dist/index.d.ts +29 -1
- package/dist/index.js +371 -101
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +2 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +2 -1
- package/dist/server.js.map +1 -1
- package/package.json +8 -7
- package/src/ArticleCategoryGrid.tsx +1 -8
- package/src/ArticleDetailHero.tsx +122 -0
- package/src/ArticleNavigation.tsx +56 -0
- package/src/ArticleSocialShare.tsx +96 -0
- package/src/CategoryArticlesPage.tsx +21 -4
- package/src/__tests__/ArticleCategoryGrid.test.tsx +40 -1
- package/src/__tests__/ArticleDetailHero.test.tsx +134 -0
- package/src/__tests__/ArticleNavigation.test.tsx +127 -0
- package/src/__tests__/ArticleSocialShare.test.tsx +187 -0
- package/src/__tests__/ArticlesPage.test.tsx +147 -1
- package/src/__tests__/CommentItem.test.tsx +110 -0
- package/src/__tests__/seoUtils.test.ts +35 -0
- package/src/index.ts +4 -0
- package/src/seoUtils.ts +7 -1
package/README.md
CHANGED
|
@@ -171,6 +171,79 @@ hero: {
|
|
|
171
171
|
|
|
172
172
|
---
|
|
173
173
|
|
|
174
|
+
## ArticleDetailHero
|
|
175
|
+
|
|
176
|
+
`ArticleDetailHero` renders the article's featured image full-width behind the title, category tags, and metadata (date, read time, author). Use it in your `app/articles/[slug]/page.tsx` instead of building a custom hero.
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
import { ArticleDetailHero } from '@fullstackdatasolutions/articles'
|
|
180
|
+
|
|
181
|
+
<ArticleDetailHero
|
|
182
|
+
article={article}
|
|
183
|
+
categoryBasePath="/articles/category"
|
|
184
|
+
/>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
| Prop | Type | Required | Description |
|
|
188
|
+
|---|---|---|---|
|
|
189
|
+
| `article` | `Article` | yes | Article object returned by `getArticleMetadata` |
|
|
190
|
+
| `categoryBasePath` | `string` | no | Base path for category links. Defaults to `"/articles/category"`. Pass `""` to render categories as plain text. |
|
|
191
|
+
| `showDate` | `boolean` | no | Show the article date. Defaults to `false` (hidden). |
|
|
192
|
+
|
|
193
|
+
- Category tags are capped at 4. When an article has more than 4 categories, only the first 4 are shown.
|
|
194
|
+
- The date field is hidden by default. Pass `showDate={true}` to display it.
|
|
195
|
+
- All layout styles are inline so the component renders correctly regardless of whether `@source` is configured for the package.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## ArticleSocialShare
|
|
200
|
+
|
|
201
|
+
`ArticleSocialShare` renders a row of sharing buttons (LinkedIn, Facebook, Twitter, Reddit, WhatsApp, Telegram, Email, Copy Link). Use it below the article body in your `app/articles/[slug]/page.tsx`.
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
import { ArticleSocialShare } from '@fullstackdatasolutions/articles'
|
|
205
|
+
|
|
206
|
+
<ArticleSocialShare
|
|
207
|
+
title={article.title}
|
|
208
|
+
url={articleUrl}
|
|
209
|
+
excerpt={article.excerpt}
|
|
210
|
+
shareMessage="Optional footer note shown below the buttons."
|
|
211
|
+
/>
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
| Prop | Type | Required | Description |
|
|
215
|
+
|---|---|---|---|
|
|
216
|
+
| `title` | `string` | yes | Article title - used in share text |
|
|
217
|
+
| `url` | `string` | yes | Canonical URL to share |
|
|
218
|
+
| `excerpt` | `string` | no | Used as email body pre-fill |
|
|
219
|
+
| `shareMessage` | `string` | no | Optional paragraph rendered below the share buttons |
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## ArticleNavigation
|
|
224
|
+
|
|
225
|
+
`ArticleNavigation` renders previous/next article links at the bottom of an article. Returns `null` when both `previous` and `next` are absent (no output, no wrapper element). Use `getAdjacentArticles` from the server entry to fetch the data.
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
import { ArticleNavigation } from '@fullstackdatasolutions/articles'
|
|
229
|
+
import { getAdjacentArticles } from '@fullstackdatasolutions/articles/server'
|
|
230
|
+
|
|
231
|
+
const { previous, next } = await getAdjacentArticles(slug)
|
|
232
|
+
|
|
233
|
+
<ArticleNavigation previous={previous} next={next} basePath="/articles" />
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
| Prop | Type | Required | Description |
|
|
237
|
+
|---|---|---|---|
|
|
238
|
+
| `previous` | `{ slug: string; title: string } \| null` | yes | Previous article, or `null` |
|
|
239
|
+
| `next` | `{ slug: string; title: string } \| null` | yes | Next article, or `null` |
|
|
240
|
+
| `basePath` | `string` | yes | Route prefix (e.g. `"/articles"`) prepended to each slug |
|
|
241
|
+
|
|
242
|
+
- Titles longer than 60 characters are truncated with an ellipsis.
|
|
243
|
+
- No output is rendered when both `previous` and `next` are `null`.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
174
247
|
## Comments setup
|
|
175
248
|
|
|
176
249
|
### 1. Enable in config
|
|
@@ -203,6 +276,8 @@ app/api/articles/[slug]/comments/[commentId]/route.ts ← DELETE (soft)
|
|
|
203
276
|
|
|
204
277
|
## SEO utilities
|
|
205
278
|
|
|
279
|
+
### Article and category metadata
|
|
280
|
+
|
|
206
281
|
```ts
|
|
207
282
|
// app/articles/[slug]/page.tsx
|
|
208
283
|
import { generateArticleMetadata } from '@fullstackdatasolutions/articles/server'
|
|
@@ -214,15 +289,31 @@ export const generateMetadata = ({ params }) =>
|
|
|
214
289
|
import { generateCategoryMetadata } from '@fullstackdatasolutions/articles/server'
|
|
215
290
|
export const generateMetadata = ({ params }) =>
|
|
216
291
|
generateCategoryMetadata(params.category, siteConfig)
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Sitemaps
|
|
217
295
|
|
|
296
|
+
Use `getArticleSitemapEntries` to generate article and category sitemap entries. Pass your `ArticlesConfig` object (preferred) or a plain URL string.
|
|
297
|
+
|
|
298
|
+
```ts
|
|
218
299
|
// app/sitemap.ts
|
|
219
300
|
import { getArticleSitemapEntries } from '@fullstackdatasolutions/articles/server'
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
301
|
+
import { siteConfig } from '@/config/articles'
|
|
302
|
+
import type { MetadataRoute } from 'next'
|
|
303
|
+
|
|
304
|
+
const staticPages: MetadataRoute.Sitemap = [
|
|
305
|
+
{ url: 'https://yoursite.com', changeFrequency: 'weekly', priority: 1.0 },
|
|
306
|
+
{ url: 'https://yoursite.com/about', changeFrequency: 'monthly', priority: 0.8 },
|
|
307
|
+
]
|
|
308
|
+
|
|
309
|
+
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
|
310
|
+
const articleEntries = await getArticleSitemapEntries(siteConfig)
|
|
311
|
+
return [...staticPages, ...articleEntries]
|
|
223
312
|
}
|
|
224
313
|
```
|
|
225
314
|
|
|
315
|
+
Returns article entries (priority 0.8, changeFrequency 'weekly') and category entries (priority 0.7, changeFrequency 'weekly'). Alternative: pass a plain URL string instead of `siteConfig`: `getArticleSitemapEntries('https://yoursite.com')`.
|
|
316
|
+
|
|
226
317
|
JSON-LD structured data (`ArticleSchema`, `BreadcrumbSchema`, `CollectionPageSchema`) is rendered automatically inside the library components — no extra wiring required.
|
|
227
318
|
|
|
228
319
|
---
|
|
@@ -234,7 +325,7 @@ JSON-LD structured data (`ArticleSchema`, `BreadcrumbSchema`, `CollectionPageSch
|
|
|
234
325
|
| `title` | `string` | yes | Article title |
|
|
235
326
|
| `excerpt` | `string` | yes | One-sentence summary for cards and meta |
|
|
236
327
|
| `author` | `string` | no | Defaults to `'Andrew Blase'` |
|
|
237
|
-
| `tags` | `string[]` | no | Used as categories. First tag = primary category. |
|
|
328
|
+
| `tags` | `string[]` | no | Used as categories. First tag = primary category. ArticleDetailHero displays at most 4 category tags; articles with more than 4 show only the first 4 in the hero. |
|
|
238
329
|
| `date` | `YYYY-MM-DD` | no | Omit to publish immediately. Future dates hide until that date. |
|
|
239
330
|
| `featuredImage` | `string` | no | Filename relative to the article directory. Auto-detected if omitted. |
|
|
240
331
|
|
|
@@ -307,7 +398,10 @@ This app uses `@fullstackdatasolutions/articles` for the articles section.
|
|
|
307
398
|
The package ships its source TypeScript files so Tailwind can scan them.
|
|
308
399
|
`app/globals.css` contains:
|
|
309
400
|
@source "./node_modules/@fullstackdatasolutions/articles/src";
|
|
310
|
-
If this line is missing, most component classes will not render correctly. Note: `ArticleCategoryGrid` image
|
|
401
|
+
If this line is missing, most component classes will not render correctly. Note: `ArticleCategoryGrid` images, `CategoryArticlesPage` hero, and `ArticleDetailHero` image use inline styles for critical layout so they render correctly without this line. All other styling still requires it.
|
|
402
|
+
|
|
403
|
+
### Server utilities
|
|
404
|
+
For sitemaps and metadata: `import { getArticleSitemapEntries, generateArticleMetadata, generateCategoryMetadata } from '@fullstackdatasolutions/articles/server'`. See README for usage examples.
|
|
311
405
|
|
|
312
406
|
### Rules
|
|
313
407
|
- Change `config/articles.ts` first; only edit library source if config cannot express the need.
|