@founderhq/next-blog 0.9.0
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 +169 -0
- package/dist/cli/core.d.ts +61 -0
- package/dist/cli/core.d.ts.map +1 -0
- package/dist/cli/core.js +1983 -0
- package/dist/cli/core.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +390 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/components.d.ts +57 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +281 -0
- package/dist/components.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/registry.d.ts +6 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +29 -0
- package/dist/registry.js.map +1 -0
- package/dist/server.d.ts +159 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +681 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +21 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +56 -0
- package/dist/utils.js.map +1 -0
- package/package.json +88 -0
- package/src/styles.css +264 -0
- package/src/templates/blog-components.tsx.txt +603 -0
- package/src/templates/blog.css.txt +264 -0
package/README.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# @founderhq/next-blog
|
|
2
|
+
|
|
3
|
+
Next.js App Router SEO helpers, editable blog templates, and installer for
|
|
4
|
+
FounderHQ-compatible Payload blogs.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npx @founderhq/next-blog@next init
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The installer is conservative:
|
|
13
|
+
|
|
14
|
+
- dry-run preview first, then asks whether to apply
|
|
15
|
+
- supports `--dry-run` for preview-only runs
|
|
16
|
+
- supports `--yes` for non-interactive apply after plan generation
|
|
17
|
+
- supports `--env-mode write|print` to choose runtime env handling
|
|
18
|
+
- refuses dirty git by default
|
|
19
|
+
- prints a diff preview before writing
|
|
20
|
+
- uses dedicated Payload env vars
|
|
21
|
+
- asks for database and site env values
|
|
22
|
+
- supports Next App Router automatically and non-Next projects with a
|
|
23
|
+
framework-neutral manual integration plan
|
|
24
|
+
- always writes safe examples to `.env.example` on apply
|
|
25
|
+
- lets you either write runtime env values to `.env` and `.env.local`, or
|
|
26
|
+
print them for copy-paste into your own env setup
|
|
27
|
+
- installs only the selected Payload database and storage adapters
|
|
28
|
+
- asks before running migrations and validates env first
|
|
29
|
+
- aborts with manual instructions for unsupported project shapes, existing
|
|
30
|
+
Payload configs, unsupported Next config filenames, and generated file path
|
|
31
|
+
collisions
|
|
32
|
+
- copies editable blog UI into your app instead of forcing package-owned visual
|
|
33
|
+
components
|
|
34
|
+
|
|
35
|
+
Supported v1 databases:
|
|
36
|
+
|
|
37
|
+
- Postgres through `@payloadcms/db-postgres`
|
|
38
|
+
- local SQLite through `@payloadcms/db-sqlite`
|
|
39
|
+
- Turso/libSQL through `@payloadcms/db-sqlite`
|
|
40
|
+
|
|
41
|
+
MongoDB is intentionally manual/advanced in v1.
|
|
42
|
+
|
|
43
|
+
Supported installer storage choices:
|
|
44
|
+
|
|
45
|
+
- local
|
|
46
|
+
- S3
|
|
47
|
+
- R2
|
|
48
|
+
- Vercel Blob
|
|
49
|
+
- Azure Blob
|
|
50
|
+
- Google Cloud Storage
|
|
51
|
+
- UploadThing
|
|
52
|
+
- custom/manual
|
|
53
|
+
|
|
54
|
+
The custom/manual choice generates a no-op `founderhq-blog.storage.ts` so
|
|
55
|
+
migrations and the admin app can boot before the customer adds their adapter.
|
|
56
|
+
Edit that file before production uploads.
|
|
57
|
+
|
|
58
|
+
Payload uses dedicated env vars and never reuses an app `DATABASE_URL`
|
|
59
|
+
silently:
|
|
60
|
+
|
|
61
|
+
- `PAYLOAD_DATABASE_URL`
|
|
62
|
+
- `PAYLOAD_DATABASE_AUTH_TOKEN`
|
|
63
|
+
- `PAYLOAD_SECRET`
|
|
64
|
+
- `NEXT_PUBLIC_SITE_NAME`
|
|
65
|
+
- `NEXT_PUBLIC_SITE_URL`
|
|
66
|
+
- `NEXT_PUBLIC_BLOG_ROUTE_PREFIX`
|
|
67
|
+
|
|
68
|
+
The v1 installer requires a non-root blog route prefix such as `/blog` or
|
|
69
|
+
`/insights`. Root-mounted blogs can be wired manually after install if a client
|
|
70
|
+
needs the blog to own `/`.
|
|
71
|
+
|
|
72
|
+
## Install model
|
|
73
|
+
|
|
74
|
+
The package uses a hybrid model:
|
|
75
|
+
|
|
76
|
+
- `@founderhq/payload-cms-kit` owns Payload collections, fields, blocks, hooks,
|
|
77
|
+
and rich text behavior.
|
|
78
|
+
- `@founderhq/next-blog/server` owns portable server helpers for fetching,
|
|
79
|
+
normalization, metadata, JSON-LD, RSS, sitemaps, redirects, and search.
|
|
80
|
+
- `npx @founderhq/next-blog init` copies editable UI templates into the target
|
|
81
|
+
project, similar to the shadcn open-code model.
|
|
82
|
+
|
|
83
|
+
Fresh installs generate files like:
|
|
84
|
+
|
|
85
|
+
- `src/components/blog/blog-components.tsx`
|
|
86
|
+
- `src/components/blog/blog.css`
|
|
87
|
+
- `src/app/blog/page.tsx`
|
|
88
|
+
- `src/app/blog/page/[page]/page.tsx`
|
|
89
|
+
- `src/app/blog/[slug]/page.tsx`
|
|
90
|
+
- `src/app/blog/search/page.tsx`
|
|
91
|
+
- `src/app/blog/authors/page.tsx`
|
|
92
|
+
- `src/app/blog/authors/[slug]/page.tsx`
|
|
93
|
+
- `src/app/blog/authors/[slug]/page/[page]/page.tsx`
|
|
94
|
+
- `src/app/blog/categories/page.tsx`
|
|
95
|
+
- `src/app/blog/categories/[slug]/page.tsx`
|
|
96
|
+
- `src/app/blog/categories/[slug]/page/[page]/page.tsx`
|
|
97
|
+
- `src/app/blog/tags/page.tsx`
|
|
98
|
+
- `src/app/blog/tags/[slug]/page.tsx`
|
|
99
|
+
- `src/app/blog/tags/[slug]/page/[page]/page.tsx`
|
|
100
|
+
- `src/app/blog/rss.xml/route.ts`
|
|
101
|
+
- `src/app/sitemaps/blog-posts.xml/route.ts`
|
|
102
|
+
- `src/app/sitemaps/blog-authors.xml/route.ts`
|
|
103
|
+
- `src/app/sitemaps/blog-categories.xml/route.ts`
|
|
104
|
+
- `src/app/sitemaps/blog-tags.xml/route.ts`
|
|
105
|
+
- `src/app/sitemap.xml/route.ts` when no root sitemap exists
|
|
106
|
+
- `src/app/robots.ts` when no robots route/file exists
|
|
107
|
+
|
|
108
|
+
Customers should edit the generated component and CSS files to match their
|
|
109
|
+
site. The package remains the maintained source for CMS and SEO primitives.
|
|
110
|
+
|
|
111
|
+
If a project already has `payload.config.*`, the v1 installer refuses to
|
|
112
|
+
overwrite it. Add `@founderhq/payload-cms-kit` manually through
|
|
113
|
+
`founderHQBlogPlugin()` or the collection/global factories so existing Payload
|
|
114
|
+
collections, plugins, access rules, and storage settings stay intact.
|
|
115
|
+
|
|
116
|
+
For non-Next projects, the CLI does not generate public framework routes. It
|
|
117
|
+
creates `payload.config.ts`, storage config, framework-neutral blog data
|
|
118
|
+
helpers, env/scripts, and `FOUNDERHQ_BLOG_INTEGRATION.md` with the exact route,
|
|
119
|
+
RSS, robots, and sitemap contract to implement in that framework.
|
|
120
|
+
|
|
121
|
+
## Sitemaps
|
|
122
|
+
|
|
123
|
+
Fresh installs create this structure:
|
|
124
|
+
|
|
125
|
+
- `/sitemap.xml` as a sitemap index
|
|
126
|
+
- `/sitemaps/blog-posts.xml` for blog index pagination and article URLs
|
|
127
|
+
- `/sitemaps/blog-authors.xml` for the author directory, author pages, and
|
|
128
|
+
author archive pagination
|
|
129
|
+
- `/sitemaps/blog-categories.xml` for the category directory, category pages,
|
|
130
|
+
and category archive pagination
|
|
131
|
+
- `/sitemaps/blog-tags.xml` for the tag directory, tag pages, and tag archive
|
|
132
|
+
pagination
|
|
133
|
+
|
|
134
|
+
If the target app already has a simple `app/sitemap.ts`, the installer patches
|
|
135
|
+
that metadata sitemap to include indexable blog URLs directly, because Next
|
|
136
|
+
metadata sitemaps emit URL sets rather than sitemap indexes. If the target has
|
|
137
|
+
a static `public/sitemap.xml` that is already a sitemap index, the installer
|
|
138
|
+
adds the blog child sitemap links. If the existing sitemap is a custom route
|
|
139
|
+
handler or a static URL set that cannot be patched safely, the installer still
|
|
140
|
+
creates `/sitemaps/blog-*.xml` routes and prints manual merge instructions.
|
|
141
|
+
|
|
142
|
+
The generated blog sitemap excludes posts marked `noindex` and posts with an
|
|
143
|
+
external canonical URL.
|
|
144
|
+
|
|
145
|
+
## Other SEO Routes
|
|
146
|
+
|
|
147
|
+
Fresh installs generate a `robots.ts` route pointing crawlers at `/sitemap.xml`.
|
|
148
|
+
If a project already has static `public/robots.txt`, the installer appends a
|
|
149
|
+
missing `Sitemap:` line. Existing app robots metadata routes are not force
|
|
150
|
+
patched; the installer warns if one does not appear to include a sitemap.
|
|
151
|
+
|
|
152
|
+
Generated blog routes include canonical metadata for the blog index, `noindex`
|
|
153
|
+
metadata for search results, JSON-LD for articles, RSS, manual redirect support,
|
|
154
|
+
previous-slug redirects from Payload slug history, and canonical metadata for
|
|
155
|
+
author, category, tag, and paginated archive routes.
|
|
156
|
+
|
|
157
|
+
## Runtime helpers
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import { buildArticleJsonLd, buildRssXml } from "@founderhq/next-blog/server";
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The server helpers normalize Payload REST documents into renderable articles,
|
|
164
|
+
including stored Lexical HTML, heading IDs, TOC items, JSON-LD, RSS, sitemap
|
|
165
|
+
entries, robots config, redirects, and adapter-neutral search.
|
|
166
|
+
|
|
167
|
+
The package still exports `@founderhq/next-blog/components` and
|
|
168
|
+
`@founderhq/next-blog/styles.css` for compatibility, but new installs use local
|
|
169
|
+
editable templates.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export type DbChoice = "postgres" | "sqlite-local" | "turso";
|
|
2
|
+
export type StorageChoice = "local" | "s3" | "r2" | "vercel-blob" | "azure" | "gcs" | "uploadthing" | "custom";
|
|
3
|
+
export type MigrationChoice = "skip" | "scripts" | "run";
|
|
4
|
+
export type InitOptions = {
|
|
5
|
+
projectRoot: string;
|
|
6
|
+
db: DbChoice;
|
|
7
|
+
storage: StorageChoice;
|
|
8
|
+
adminPath?: string;
|
|
9
|
+
routePrefix?: string;
|
|
10
|
+
postgresSchema?: string;
|
|
11
|
+
migration?: MigrationChoice;
|
|
12
|
+
env?: Partial<Record<string, string>>;
|
|
13
|
+
};
|
|
14
|
+
export type FileChange = {
|
|
15
|
+
path: string;
|
|
16
|
+
kind: "create" | "update";
|
|
17
|
+
content: string;
|
|
18
|
+
};
|
|
19
|
+
export type InstallPlan = {
|
|
20
|
+
appDir: string;
|
|
21
|
+
dependencies: Record<string, string>;
|
|
22
|
+
devDependencies: Record<string, string>;
|
|
23
|
+
env: Record<string, string>;
|
|
24
|
+
changes: FileChange[];
|
|
25
|
+
scripts: Record<string, string>;
|
|
26
|
+
installCommand: string | null;
|
|
27
|
+
migrationCommand: string | null;
|
|
28
|
+
warnings: string[];
|
|
29
|
+
};
|
|
30
|
+
export type PackageJsonDependencyShape = Record<string, unknown> & {
|
|
31
|
+
dependencies?: Record<string, string>;
|
|
32
|
+
devDependencies?: Record<string, string>;
|
|
33
|
+
};
|
|
34
|
+
export declare function choiceFromValue<const T extends readonly string[]>(value: string | undefined, name: string, choices: T): T[number] | undefined;
|
|
35
|
+
export declare const STORAGE_DEPENDENCIES: {
|
|
36
|
+
local: {};
|
|
37
|
+
s3: {
|
|
38
|
+
"@payloadcms/storage-s3": string;
|
|
39
|
+
};
|
|
40
|
+
r2: {
|
|
41
|
+
"@payloadcms/storage-r2": string;
|
|
42
|
+
};
|
|
43
|
+
"vercel-blob": {
|
|
44
|
+
"@payloadcms/storage-vercel-blob": string;
|
|
45
|
+
};
|
|
46
|
+
azure: {
|
|
47
|
+
"@payloadcms/storage-azure": string;
|
|
48
|
+
};
|
|
49
|
+
gcs: {
|
|
50
|
+
"@payloadcms/storage-gcs": string;
|
|
51
|
+
};
|
|
52
|
+
uploadthing: {
|
|
53
|
+
"@payloadcms/storage-uploadthing": string;
|
|
54
|
+
};
|
|
55
|
+
custom: {};
|
|
56
|
+
};
|
|
57
|
+
export declare function mergeMissingPackageEntries(pkg: PackageJsonDependencyShape, dependencies: Record<string, string>, devDependencies: Record<string, string>): PackageJsonDependencyShape;
|
|
58
|
+
export declare function missingMigrationEnv(plan: Pick<InstallPlan, "env">, env?: NodeJS.ProcessEnv): string[];
|
|
59
|
+
export declare function detectAppDir(projectRoot: string): string | null;
|
|
60
|
+
export declare function createInstallPlan(options: InitOptions): InstallPlan;
|
|
61
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/cli/core.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,cAAc,GAAG,OAAO,CAAC;AAC7D,MAAM,MAAM,aAAa,GACrB,OAAO,GACP,IAAI,GACJ,IAAI,GACJ,aAAa,GACb,OAAO,GACP,KAAK,GACL,aAAa,GACb,QAAQ,CAAC;AACb,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC;AAEzD,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,QAAQ,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,GAAG,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,EAC/D,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,yBAKX;AAiED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;CASwB,CAAC;AA4E1D,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,0BAA0B,EAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,8BA2BxC;AAaD,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,EAC9B,GAAG,GAAE,MAAM,CAAC,UAAwB,YAKrC;AAED,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,iBAM/C;AAqjDD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,CAgfnE"}
|