hazo_blog 0.1.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.
Files changed (93) hide show
  1. package/CHANGE_LOG.md +45 -0
  2. package/README.md +179 -0
  3. package/SETUP_CHECKLIST.md +54 -0
  4. package/db_setup_postgres.sql +71 -0
  5. package/db_setup_sqlite.sql +77 -0
  6. package/dist/components/admin/post-form.d.ts +18 -0
  7. package/dist/components/admin/post-form.d.ts.map +1 -0
  8. package/dist/components/admin/post-form.js +78 -0
  9. package/dist/components/author-bio.d.ts +7 -0
  10. package/dist/components/author-bio.d.ts.map +1 -0
  11. package/dist/components/author-bio.js +6 -0
  12. package/dist/components/blog-post-view-tracker.d.ts +10 -0
  13. package/dist/components/blog-post-view-tracker.d.ts.map +1 -0
  14. package/dist/components/blog-post-view-tracker.js +27 -0
  15. package/dist/components/blog-search.d.ts +9 -0
  16. package/dist/components/blog-search.d.ts.map +1 -0
  17. package/dist/components/blog-search.js +43 -0
  18. package/dist/components/faq-section.d.ts +9 -0
  19. package/dist/components/faq-section.d.ts.map +1 -0
  20. package/dist/components/faq-section.js +8 -0
  21. package/dist/components/index.d.ts +12 -0
  22. package/dist/components/index.d.ts.map +1 -0
  23. package/dist/components/index.js +13 -0
  24. package/dist/components/mdx/blog-image.d.ts +10 -0
  25. package/dist/components/mdx/blog-image.d.ts.map +1 -0
  26. package/dist/components/mdx/blog-image.js +7 -0
  27. package/dist/components/mdx/callout.d.ts +10 -0
  28. package/dist/components/mdx/callout.d.ts.map +1 -0
  29. package/dist/components/mdx/callout.js +17 -0
  30. package/dist/components/mdx/code-block.d.ts +8 -0
  31. package/dist/components/mdx/code-block.d.ts.map +1 -0
  32. package/dist/components/mdx/code-block.js +8 -0
  33. package/dist/components/mdx/index.d.ts +13 -0
  34. package/dist/components/mdx/index.d.ts.map +1 -0
  35. package/dist/components/mdx/index.js +13 -0
  36. package/dist/components/mdx/youtube.d.ts +8 -0
  37. package/dist/components/mdx/youtube.d.ts.map +1 -0
  38. package/dist/components/mdx/youtube.js +7 -0
  39. package/dist/components/post-card.d.ts +8 -0
  40. package/dist/components/post-card.d.ts.map +1 -0
  41. package/dist/components/post-card.js +10 -0
  42. package/dist/components/post-hero.d.ts +7 -0
  43. package/dist/components/post-hero.d.ts.map +1 -0
  44. package/dist/components/post-hero.js +17 -0
  45. package/dist/components/related-posts.d.ts +9 -0
  46. package/dist/components/related-posts.d.ts.map +1 -0
  47. package/dist/components/related-posts.js +8 -0
  48. package/dist/components/table-of-contents.d.ts +8 -0
  49. package/dist/components/table-of-contents.d.ts.map +1 -0
  50. package/dist/components/table-of-contents.js +7 -0
  51. package/dist/config/index.d.ts +3 -0
  52. package/dist/config/index.d.ts.map +1 -0
  53. package/dist/config/index.js +1 -0
  54. package/dist/index.client.d.ts +5 -0
  55. package/dist/index.client.d.ts.map +1 -0
  56. package/dist/index.client.js +8 -0
  57. package/dist/index.d.ts +7 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +15 -0
  60. package/dist/lib/analytics.d.ts +4 -0
  61. package/dist/lib/analytics.d.ts.map +1 -0
  62. package/dist/lib/analytics.js +14 -0
  63. package/dist/lib/index.d.ts +2 -0
  64. package/dist/lib/index.d.ts.map +1 -0
  65. package/dist/lib/index.js +2 -0
  66. package/dist/lib/text.d.ts +25 -0
  67. package/dist/lib/text.d.ts.map +1 -0
  68. package/dist/lib/text.js +69 -0
  69. package/dist/next/blog-content.d.ts +7 -0
  70. package/dist/next/blog-content.d.ts.map +1 -0
  71. package/dist/next/blog-content.js +10 -0
  72. package/dist/next/index.d.ts +5 -0
  73. package/dist/next/index.d.ts.map +1 -0
  74. package/dist/next/index.js +15 -0
  75. package/dist/next/pages.d.ts +52 -0
  76. package/dist/next/pages.d.ts.map +1 -0
  77. package/dist/next/pages.js +133 -0
  78. package/dist/next/routes.d.ts +42 -0
  79. package/dist/next/routes.d.ts.map +1 -0
  80. package/dist/next/routes.js +172 -0
  81. package/dist/repository/index.d.ts +34 -0
  82. package/dist/repository/index.d.ts.map +1 -0
  83. package/dist/repository/index.js +285 -0
  84. package/dist/seo/index.d.ts +44 -0
  85. package/dist/seo/index.d.ts.map +1 -0
  86. package/dist/seo/index.js +175 -0
  87. package/dist/service/index.d.ts +21 -0
  88. package/dist/service/index.d.ts.map +1 -0
  89. package/dist/service/index.js +110 -0
  90. package/dist/types/index.d.ts +141 -0
  91. package/dist/types/index.d.ts.map +1 -0
  92. package/dist/types/index.js +3 -0
  93. package/package.json +100 -0
@@ -0,0 +1,141 @@
1
+ import type { ComponentType } from "react";
2
+ /** Publication state. A post is "live" when published, or scheduled and due. */
3
+ export type PostStatus = "draft" | "published" | "scheduled";
4
+ /** A FAQ question/answer pair (drives the visible FAQ + FAQPage JSON-LD). */
5
+ export interface FaqItem {
6
+ question: string;
7
+ answer: string;
8
+ }
9
+ /** A blog category (single per post). */
10
+ export interface BlogCategory {
11
+ id: string;
12
+ scope_id?: string | null;
13
+ slug: string;
14
+ name: string;
15
+ description: string;
16
+ colour: string;
17
+ created_at?: string;
18
+ updated_at?: string;
19
+ }
20
+ /** A free-form tag (many-to-many with posts). */
21
+ export interface BlogTag {
22
+ id: string;
23
+ scope_id?: string | null;
24
+ slug: string;
25
+ name: string;
26
+ created_at?: string;
27
+ updated_at?: string;
28
+ }
29
+ /** A blog post row. `content` is raw MDX; `content_html` is an optional cache. */
30
+ export interface BlogPost {
31
+ id: string;
32
+ scope_id?: string | null;
33
+ slug: string;
34
+ title: string;
35
+ content: string;
36
+ content_html?: string | null;
37
+ excerpt?: string | null;
38
+ category_id?: string | null;
39
+ author_id?: string | null;
40
+ meta_title: string;
41
+ meta_description: string;
42
+ canonical_url?: string | null;
43
+ og_image?: string | null;
44
+ featured_image?: string | null;
45
+ image_ref?: string | null;
46
+ faq_json: string;
47
+ reading_time: number;
48
+ status: PostStatus;
49
+ publish_date?: string | null;
50
+ created_at: string;
51
+ updated_at: string;
52
+ }
53
+ /** A post joined with its category + resolved tags + parsed FAQ. */
54
+ export interface BlogPostWithRelations extends BlogPost {
55
+ category?: BlogCategory | null;
56
+ tags: BlogTag[];
57
+ faq: FaqItem[];
58
+ }
59
+ /** Resolved author info (feeds <AuthorBio> + JSON-LD Person). */
60
+ export interface AuthorInfo {
61
+ name: string;
62
+ url: string;
63
+ bio?: string;
64
+ avatar?: string;
65
+ }
66
+ /** Input for creating/updating a post (upsert by slug). */
67
+ export interface UpsertPostInput {
68
+ slug: string;
69
+ title: string;
70
+ content: string;
71
+ category_id?: string | null;
72
+ category_name?: string | null;
73
+ author_id?: string | null;
74
+ meta_title?: string;
75
+ meta_description?: string;
76
+ canonical_url?: string | null;
77
+ og_image?: string | null;
78
+ featured_image?: string | null;
79
+ image_ref?: string | null;
80
+ faq?: FaqItem[];
81
+ tags?: string[];
82
+ status?: PostStatus;
83
+ publish_date?: string | null;
84
+ }
85
+ /** Options for listing posts. */
86
+ export interface ListPostsOptions {
87
+ page?: number;
88
+ perPage?: number;
89
+ categorySlug?: string;
90
+ tagSlug?: string;
91
+ /** Include drafts + future-scheduled (admin views). Default false. */
92
+ includeUnpublished?: boolean;
93
+ }
94
+ /** Paginated list result. */
95
+ export interface PaginatedPosts {
96
+ posts: BlogPostWithRelations[];
97
+ total: number;
98
+ page: number;
99
+ perPage: number;
100
+ totalPages: number;
101
+ }
102
+ /** Analytics event names emitted by the blog. */
103
+ export type BlogAnalyticsEvent = "blog_post_view" | "blog_read_complete" | "blog_search" | "blog_share";
104
+ /**
105
+ * The host-supplied configuration that parameterizes the whole package.
106
+ * This is the central contract between hazo_blog and its consumer.
107
+ */
108
+ export interface BlogConfig {
109
+ /** Brand name used in titles + JSON-LD publisher. */
110
+ siteName: string;
111
+ /** Absolute site origin, e.g. "https://gotimer.org" (no trailing slash). */
112
+ baseUrl: string;
113
+ /** Blog base path. Default "/blog". */
114
+ basePath?: string;
115
+ /** Absolute logo URL (JSON-LD publisher logo). */
116
+ logoUrl: string;
117
+ /** Absolute fallback OG image URL. */
118
+ defaultOgImage: string;
119
+ /** Default site author (used when a post has no author_id). */
120
+ author: AuthorInfo;
121
+ /** Resolve a per-post author (e.g. from hazo_auth users). */
122
+ getAuthor?: (id: string) => AuthorInfo | Promise<AuthorInfo>;
123
+ /** Return a hazo_connect adapter (never imported at module top-level). */
124
+ getHazoConnect: () => Promise<unknown> | unknown;
125
+ /** Admin guard — host wires this to a hazo_auth permission check. */
126
+ authorize: (req: Request) => boolean | Promise<boolean>;
127
+ /** Optional tenant/scope resolver for multi-tenant consumers. */
128
+ resolveScope?: (req: Request) => string | null;
129
+ /** Host-injected/overridden MDX components (e.g. TimerEmbed). */
130
+ mdxComponents?: Record<string, ComponentType<unknown>>;
131
+ /** Analytics sink; falls back to window.gtag/dataLayer when omitted. */
132
+ onAnalyticsEvent?: (name: BlogAnalyticsEvent, params: Record<string, unknown>) => void;
133
+ /** ISR revalidate window in seconds. Default 3600. */
134
+ revalidateSeconds?: number;
135
+ }
136
+ /** Resolved config with defaults applied. */
137
+ export interface ResolvedBlogConfig extends BlogConfig {
138
+ basePath: string;
139
+ revalidateSeconds: number;
140
+ }
141
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ // hazo_blog — domain types and the BlogConfig contract.
2
+ // This module is server/client neutral (pure types + interfaces only).
3
+ export {};
package/package.json ADDED
@@ -0,0 +1,100 @@
1
+ {
2
+ "name": "hazo_blog",
3
+ "version": "0.1.0",
4
+ "description": "SEO-optimized blogging package: posts, categories, tags, MDX content, and GA4/GSC/Bing-ready SEO.",
5
+ "type": "module",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./client": {
14
+ "types": "./dist/index.client.d.ts",
15
+ "import": "./dist/index.client.js"
16
+ },
17
+ "./seo": {
18
+ "types": "./dist/seo/index.d.ts",
19
+ "import": "./dist/seo/index.js"
20
+ },
21
+ "./next": {
22
+ "types": "./dist/next/index.d.ts",
23
+ "import": "./dist/next/index.js"
24
+ },
25
+ "./config": {
26
+ "types": "./dist/config/index.d.ts",
27
+ "import": "./dist/config/index.js"
28
+ },
29
+ "./package.json": "./package.json"
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "db_setup_postgres.sql",
34
+ "db_setup_sqlite.sql",
35
+ "README.md",
36
+ "CHANGE_LOG.md",
37
+ "SETUP_CHECKLIST.md"
38
+ ],
39
+ "scripts": {
40
+ "build": "tsc -p tsconfig.build.json",
41
+ "type-check": "tsc --noEmit",
42
+ "test": "node --experimental-vm-modules ../node_modules/jest/bin/jest.js --config jest.config.cjs"
43
+ },
44
+ "peerDependencies": {
45
+ "hazo_core": "^1.0.1",
46
+ "hazo_connect": "^3.0.0",
47
+ "hazo_api": "^2.1.1",
48
+ "hazo_files": "^3.0.0",
49
+ "hazo_ui": "^3.2.0",
50
+ "hazo_images": "^1.2.0",
51
+ "hazo_jobs": "^0.12.0",
52
+ "hazo_auth": "^9.0.1",
53
+ "react": "^18.0.0 || ^19.0.0",
54
+ "react-dom": "^18.0.0 || ^19.0.0",
55
+ "next": "^14.0.0 || ^16.0.0"
56
+ },
57
+ "peerDependenciesMeta": {
58
+ "hazo_images": { "optional": true },
59
+ "hazo_jobs": { "optional": true },
60
+ "hazo_auth": { "optional": true }
61
+ },
62
+ "dependencies": {
63
+ "next-mdx-remote": "^6.0.0",
64
+ "remark-gfm": "^4.0.1"
65
+ },
66
+ "devDependencies": {
67
+ "typescript": "^5.7.2",
68
+ "jest": "^30.2.0",
69
+ "ts-jest": "^29.4.5",
70
+ "@types/jest": "^30.0.0",
71
+ "jest-environment-node": "^30.2.0",
72
+ "@types/node": "^22.10.0",
73
+ "@types/react": "^19.0.0",
74
+ "@types/react-dom": "^19.0.0",
75
+ "react": "^19.0.0",
76
+ "react-dom": "^19.0.0",
77
+ "next": "^16.0.10",
78
+ "hazo_core": "^1.0.1",
79
+ "hazo_connect": "^3.0.0",
80
+ "hazo_api": "^2.1.1",
81
+ "hazo_files": "^3.0.0",
82
+ "hazo_ui": "^3.2.0",
83
+ "tailwindcss": "^4.2.4",
84
+ "@tailwindcss/postcss": "^4.2.4",
85
+ "postcss": "^8.4.49"
86
+ },
87
+ "keywords": [
88
+ "blog",
89
+ "blogging",
90
+ "cms",
91
+ "mdx",
92
+ "seo",
93
+ "ga4",
94
+ "sitemap",
95
+ "rss",
96
+ "hazo"
97
+ ],
98
+ "author": "Pubs Abayasiri",
99
+ "license": "MIT"
100
+ }