create-noxion 0.1.1 → 0.2.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 (83) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +159 -5
  4. package/dist/index.js.map +1 -1
  5. package/dist/scaffold.d.ts +9 -1
  6. package/dist/scaffold.d.ts.map +1 -1
  7. package/dist/scaffold.js +20 -3
  8. package/dist/scaffold.js.map +1 -1
  9. package/dist/templates/docs/.env +8 -0
  10. package/dist/templates/docs/.env.example +9 -0
  11. package/dist/templates/docs/app/[slug]/page.tsx +49 -0
  12. package/dist/templates/docs/app/api/notion-webhook/route.ts +12 -0
  13. package/dist/templates/docs/app/api/revalidate/route.ts +12 -0
  14. package/dist/templates/docs/app/globals.css +31 -0
  15. package/dist/templates/docs/app/layout.tsx +35 -0
  16. package/dist/templates/docs/app/not-found.tsx +38 -0
  17. package/dist/templates/docs/app/page.tsx +45 -0
  18. package/dist/templates/docs/app/providers.tsx +45 -0
  19. package/dist/templates/docs/app/robots.ts +7 -0
  20. package/dist/templates/docs/app/sitemap.ts +9 -0
  21. package/dist/templates/docs/app/theme-script.tsx +16 -0
  22. package/dist/templates/docs/lib/config.ts +24 -0
  23. package/dist/templates/docs/lib/notion.ts +48 -0
  24. package/dist/templates/docs/next.config.ts +26 -0
  25. package/dist/templates/docs/noxion.config.ts +23 -0
  26. package/dist/templates/docs/package.json +25 -0
  27. package/dist/templates/docs/tsconfig.json +19 -0
  28. package/dist/templates/full/.env +10 -0
  29. package/dist/templates/full/.env.example +11 -0
  30. package/dist/templates/full/app/[slug]/page.tsx +55 -0
  31. package/dist/templates/full/app/api/notion-webhook/route.ts +12 -0
  32. package/dist/templates/full/app/api/revalidate/route.ts +12 -0
  33. package/dist/templates/full/app/globals.css +31 -0
  34. package/dist/templates/full/app/home-content.tsx +58 -0
  35. package/dist/templates/full/app/layout.tsx +35 -0
  36. package/dist/templates/full/app/not-found.tsx +38 -0
  37. package/dist/templates/full/app/page.tsx +50 -0
  38. package/dist/templates/full/app/providers.tsx +45 -0
  39. package/dist/templates/full/app/robots.ts +7 -0
  40. package/dist/templates/full/app/sitemap.ts +9 -0
  41. package/dist/templates/full/app/tag/[tag]/page.tsx +66 -0
  42. package/dist/templates/full/app/theme-script.tsx +16 -0
  43. package/dist/templates/full/lib/config.ts +24 -0
  44. package/dist/templates/full/lib/notion.ts +66 -0
  45. package/dist/templates/full/next.config.ts +26 -0
  46. package/dist/templates/full/noxion.config.ts +40 -0
  47. package/dist/templates/full/package.json +25 -0
  48. package/dist/templates/full/tsconfig.json +19 -0
  49. package/dist/templates/nextjs/.env.example +1 -0
  50. package/dist/templates/nextjs/app/api/notion-webhook/route.ts +12 -0
  51. package/dist/templates/nextjs/app/page.tsx +3 -3
  52. package/dist/templates/nextjs/app/tag/[tag]/page.tsx +4 -4
  53. package/dist/templates/nextjs/lib/config.ts +1 -0
  54. package/dist/templates/nextjs/lib/notion.ts +5 -5
  55. package/dist/templates/plugin/noxion-plugin.json +10 -0
  56. package/dist/templates/plugin/package.json +41 -0
  57. package/dist/templates/plugin/src/__tests__/plugin.test.ts +39 -0
  58. package/dist/templates/plugin/src/index.ts +20 -0
  59. package/dist/templates/plugin/tsconfig.json +20 -0
  60. package/dist/templates/portfolio/.env +8 -0
  61. package/dist/templates/portfolio/.env.example +9 -0
  62. package/dist/templates/portfolio/app/[slug]/page.tsx +48 -0
  63. package/dist/templates/portfolio/app/api/notion-webhook/route.ts +12 -0
  64. package/dist/templates/portfolio/app/api/revalidate/route.ts +12 -0
  65. package/dist/templates/portfolio/app/globals.css +31 -0
  66. package/dist/templates/portfolio/app/layout.tsx +35 -0
  67. package/dist/templates/portfolio/app/not-found.tsx +38 -0
  68. package/dist/templates/portfolio/app/page.tsx +70 -0
  69. package/dist/templates/portfolio/app/providers.tsx +45 -0
  70. package/dist/templates/portfolio/app/robots.ts +7 -0
  71. package/dist/templates/portfolio/app/sitemap.ts +9 -0
  72. package/dist/templates/portfolio/app/theme-script.tsx +16 -0
  73. package/dist/templates/portfolio/lib/config.ts +24 -0
  74. package/dist/templates/portfolio/lib/notion.ts +48 -0
  75. package/dist/templates/portfolio/next.config.ts +26 -0
  76. package/dist/templates/portfolio/noxion.config.ts +23 -0
  77. package/dist/templates/portfolio/package.json +25 -0
  78. package/dist/templates/portfolio/tsconfig.json +19 -0
  79. package/dist/templates/theme/package.json +42 -0
  80. package/dist/templates/theme/src/index.ts +40 -0
  81. package/dist/templates/theme/styles/theme.css +23 -0
  82. package/dist/templates/theme/tsconfig.json +20 -0
  83. package/package.json +1 -1
@@ -0,0 +1,70 @@
1
+ import Link from "next/link";
2
+ import { getAllProjects } from "../lib/notion";
3
+
4
+ export const revalidate = 3600;
5
+
6
+ export default async function HomePage() {
7
+ const projects = await getAllProjects();
8
+
9
+ return (
10
+ <div>
11
+ <h1 style={{ fontSize: "1.5rem", fontWeight: 700, marginBottom: "2rem" }}>
12
+ Projects
13
+ </h1>
14
+ <div
15
+ style={{
16
+ display: "grid",
17
+ gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))",
18
+ gap: "1.5rem",
19
+ }}
20
+ >
21
+ {projects.map((project) => (
22
+ <Link
23
+ key={project.id}
24
+ href={`/${project.slug}`}
25
+ style={{
26
+ display: "block",
27
+ padding: "1.5rem",
28
+ borderRadius: "var(--noxion-border-radius, 0.5rem)",
29
+ border: "1px solid var(--noxion-border, #e5e7eb)",
30
+ transition: "border-color 0.2s",
31
+ }}
32
+ >
33
+ {project.coverImage && (
34
+ <img
35
+ src={project.coverImage}
36
+ alt={project.title}
37
+ style={{ width: "100%", borderRadius: "0.25rem", marginBottom: "0.75rem" }}
38
+ />
39
+ )}
40
+ <h3 style={{ fontSize: "1.125rem", fontWeight: 600, marginBottom: "0.5rem" }}>
41
+ {project.title}
42
+ </h3>
43
+ {project.description && (
44
+ <p style={{ fontSize: "0.875rem", color: "var(--noxion-mutedForeground, #737373)" }}>
45
+ {project.description}
46
+ </p>
47
+ )}
48
+ {Array.isArray(project.metadata.technologies) && (
49
+ <div style={{ display: "flex", gap: "0.5rem", flexWrap: "wrap", marginTop: "0.75rem" }}>
50
+ {(project.metadata.technologies as string[]).map((tech) => (
51
+ <span
52
+ key={tech}
53
+ style={{
54
+ fontSize: "0.75rem",
55
+ padding: "0.125rem 0.5rem",
56
+ borderRadius: "9999px",
57
+ backgroundColor: "var(--noxion-muted, #f5f5f5)",
58
+ }}
59
+ >
60
+ {tech}
61
+ </span>
62
+ ))}
63
+ </div>
64
+ )}
65
+ </Link>
66
+ ))}
67
+ </div>
68
+ </div>
69
+ );
70
+ }
@@ -0,0 +1,45 @@
1
+ "use client";
2
+
3
+ import { NoxionThemeProvider, defaultTheme, Header, Footer } from "@noxion/renderer";
4
+
5
+ interface ProvidersProps {
6
+ siteName: string;
7
+ author: string;
8
+ children: React.ReactNode;
9
+ }
10
+
11
+ export function Providers({ siteName, author, children }: ProvidersProps) {
12
+ return (
13
+ <NoxionThemeProvider theme={defaultTheme}>
14
+ <div
15
+ style={{
16
+ display: "flex",
17
+ flexDirection: "column",
18
+ minHeight: "100vh",
19
+ }}
20
+ >
21
+ <Header
22
+ siteName={siteName}
23
+ navigation={[
24
+ { label: "Home", href: "/" },
25
+ ]}
26
+ />
27
+ <main
28
+ style={{
29
+ flex: 1,
30
+ width: "100%",
31
+ maxWidth: "var(--noxion-content-width, 720px)",
32
+ margin: "0 auto",
33
+ padding: "2rem 1.5rem",
34
+ }}
35
+ >
36
+ {children}
37
+ </main>
38
+ <Footer
39
+ siteName={siteName}
40
+ author={author}
41
+ />
42
+ </div>
43
+ </NoxionThemeProvider>
44
+ );
45
+ }
@@ -0,0 +1,7 @@
1
+ import type { MetadataRoute } from "next";
2
+ import { generateNoxionRobots } from "@noxion/adapter-nextjs";
3
+ import { siteConfig } from "../lib/config";
4
+
5
+ export default function robots(): MetadataRoute.Robots {
6
+ return generateNoxionRobots(siteConfig);
7
+ }
@@ -0,0 +1,9 @@
1
+ import type { MetadataRoute } from "next";
2
+ import { generateNoxionSitemap } from "@noxion/adapter-nextjs";
3
+ import { getAllPosts } from "../lib/notion";
4
+ import { siteConfig } from "../lib/config";
5
+
6
+ export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
7
+ const posts = await getAllPosts();
8
+ return generateNoxionSitemap(posts, siteConfig);
9
+ }
@@ -0,0 +1,16 @@
1
+ export function ThemeScript() {
2
+ const script = `
3
+ (function() {
4
+ try {
5
+ var stored = localStorage.getItem('noxion-theme');
6
+ var theme = stored || 'system';
7
+ if (theme === 'system') {
8
+ theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
9
+ }
10
+ document.documentElement.dataset.theme = theme;
11
+ } catch (e) {}
12
+ })();
13
+ `;
14
+
15
+ return <script dangerouslySetInnerHTML={{ __html: script }} />;
16
+ }
@@ -0,0 +1,24 @@
1
+ import { loadConfig } from "@noxion/core";
2
+ import type { NoxionConfig } from "@noxion/core";
3
+ import noxionConfigInput from "../noxion.config";
4
+
5
+ function createConfig(): NoxionConfig {
6
+ try {
7
+ return loadConfig(noxionConfigInput);
8
+ } catch {
9
+ return {
10
+ name: noxionConfigInput.name ?? "{{SITE_NAME}}",
11
+ domain: noxionConfigInput.domain ?? "{{DOMAIN}}",
12
+ author: noxionConfigInput.author ?? "{{AUTHOR}}",
13
+ description: noxionConfigInput.description ?? "{{SITE_DESCRIPTION}}",
14
+ language: noxionConfigInput.language ?? "en",
15
+ defaultTheme: noxionConfigInput.defaultTheme ?? "system",
16
+ defaultPageType: "portfolio",
17
+ revalidate: noxionConfigInput.revalidate ?? 3600,
18
+ plugins: noxionConfigInput.plugins,
19
+ collections: noxionConfigInput.collections,
20
+ };
21
+ }
22
+ }
23
+
24
+ export const siteConfig = createConfig();
@@ -0,0 +1,48 @@
1
+ import { createNotionClient, fetchCollection, fetchPage, downloadImages, mapImages } from "@noxion/core";
2
+ import type { NoxionPage, ExtendedRecordMap } from "@noxion/core";
3
+ import { join } from "node:path";
4
+ import { siteConfig } from "./config";
5
+
6
+ const notion = createNotionClient({
7
+ authToken: process.env.NOTION_TOKEN || undefined,
8
+ });
9
+
10
+ export async function getAllProjects(): Promise<NoxionPage[]> {
11
+ const collections = siteConfig.collections ?? [];
12
+ if (collections.length === 0) return [];
13
+
14
+ try {
15
+ const results = await Promise.all(
16
+ collections.map((col) => fetchCollection(notion, col))
17
+ );
18
+ return results.flat();
19
+ } catch (error) {
20
+ console.error("Failed to fetch projects:", error);
21
+ return [];
22
+ }
23
+ }
24
+
25
+ export async function getProjectBySlug(slug: string): Promise<NoxionPage | undefined> {
26
+ const projects = await getAllProjects();
27
+ return projects.find((p) => p.slug === slug);
28
+ }
29
+
30
+ export async function getPageRecordMap(pageId: string): Promise<ExtendedRecordMap> {
31
+ const recordMap = await fetchPage(notion, pageId);
32
+
33
+ if (process.env.NODE_ENV === "production") {
34
+ try {
35
+ const outputDir = join(process.cwd(), "public");
36
+ const urlMap = await downloadImages(recordMap, outputDir, { concurrency: 5 });
37
+ const localUrlMap: Record<string, string> = {};
38
+ for (const [originalUrl, localPath] of Object.entries(urlMap)) {
39
+ localUrlMap[originalUrl] = `/images/${localPath.split("/images/").pop()}`;
40
+ }
41
+ return mapImages(recordMap, localUrlMap);
42
+ } catch (error) {
43
+ console.error("Image download failed, using original URLs:", error);
44
+ }
45
+ }
46
+
47
+ return recordMap;
48
+ }
@@ -0,0 +1,26 @@
1
+ import type { NextConfig } from "next";
2
+
3
+ const nextConfig: NextConfig = {
4
+ output: "standalone",
5
+ transpilePackages: [
6
+ "@noxion/core",
7
+ "@noxion/renderer",
8
+ "@noxion/adapter-nextjs",
9
+ "@noxion/notion-renderer",
10
+ "notion-client",
11
+ "notion-types",
12
+ "notion-utils",
13
+ ],
14
+ images: {
15
+ remotePatterns: [
16
+ { protocol: "https", hostname: "www.notion.so" },
17
+ { protocol: "https", hostname: "notion.so" },
18
+ { protocol: "https", hostname: "images.unsplash.com" },
19
+ { protocol: "https", hostname: "s3.us-west-2.amazonaws.com" },
20
+ { protocol: "https", hostname: "prod-files-secure.s3.us-west-2.amazonaws.com" },
21
+ ],
22
+ },
23
+ staticPageGenerationTimeout: 300,
24
+ };
25
+
26
+ export default nextConfig;
@@ -0,0 +1,23 @@
1
+ import { defineConfig } from "@noxion/core";
2
+
3
+ const config = defineConfig({
4
+ name: process.env.SITE_NAME ?? "{{SITE_NAME}}",
5
+ domain: process.env.SITE_DOMAIN ?? "{{DOMAIN}}",
6
+ author: process.env.SITE_AUTHOR ?? "{{AUTHOR}}",
7
+ description: process.env.SITE_DESCRIPTION ?? "{{SITE_DESCRIPTION}}",
8
+ language: "en",
9
+ defaultTheme: "system",
10
+ defaultPageType: "portfolio",
11
+ revalidate: 3600,
12
+ revalidateSecret: process.env.REVALIDATE_SECRET,
13
+ collections: [
14
+ {
15
+ name: "portfolio",
16
+ databaseId: process.env.NOTION_PAGE_ID!,
17
+ pageType: "portfolio",
18
+ pathPrefix: "/projects",
19
+ },
20
+ ],
21
+ });
22
+
23
+ export default config;
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start"
9
+ },
10
+ "dependencies": {
11
+ "@noxion/core": "^0.0.2",
12
+ "@noxion/renderer": "^0.0.2",
13
+ "@noxion/adapter-nextjs": "^0.0.2",
14
+ "next": "^16.1.6",
15
+ "react": "^19.1.0",
16
+ "react-dom": "^19.1.0",
17
+ "notion-client": "^7.8.2"
18
+ },
19
+ "devDependencies": {
20
+ "@types/node": "^22.0.0",
21
+ "@types/react": "^19.2.14",
22
+ "@types/react-dom": "^19.2.3",
23
+ "typescript": "^5.7.0"
24
+ }
25
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "jsx": "react-jsx",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "plugins": [{ "name": "next" }],
15
+ "outDir": "./dist"
16
+ },
17
+ "include": ["**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
18
+ "exclude": ["node_modules", ".next", "out", "dist"]
19
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "noxion-theme-{{THEME_NAME}}",
3
+ "version": "0.1.0",
4
+ "description": "A custom Noxion theme",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ },
14
+ "./styles": "./styles/theme.css"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "styles"
19
+ ],
20
+ "sideEffects": [
21
+ "styles/**/*.css"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsc",
25
+ "prepublishOnly": "bun run build"
26
+ },
27
+ "keywords": [
28
+ "notion",
29
+ "noxion",
30
+ "noxion-theme"
31
+ ],
32
+ "peerDependencies": {
33
+ "@noxion/renderer": ">=0.2.0",
34
+ "react": ">=18.0.0"
35
+ },
36
+ "devDependencies": {
37
+ "@noxion/renderer": "^0.2.0",
38
+ "@types/react": "^19.2.14",
39
+ "react": "^19.2.4",
40
+ "typescript": "^5.7.0"
41
+ }
42
+ }
@@ -0,0 +1,40 @@
1
+ import { extendTheme } from "@noxion/renderer";
2
+ import type { NoxionThemePackage } from "@noxion/renderer";
3
+
4
+ const baseTheme: NoxionThemePackage = {
5
+ name: "noxion-theme-{{THEME_NAME}}",
6
+ tokens: {
7
+ colors: {
8
+ light: {
9
+ primary: "#2563eb",
10
+ primaryForeground: "#ffffff",
11
+ background: "#ffffff",
12
+ foreground: "#0a0a0a",
13
+ muted: "#f5f5f5",
14
+ mutedForeground: "#737373",
15
+ border: "#e5e7eb",
16
+ accent: "#f0f9ff",
17
+ accentForeground: "#1e40af",
18
+ },
19
+ dark: {
20
+ primary: "#3b82f6",
21
+ primaryForeground: "#ffffff",
22
+ background: "#0a0a0a",
23
+ foreground: "#fafafa",
24
+ muted: "#262626",
25
+ mutedForeground: "#a3a3a3",
26
+ border: "#404040",
27
+ accent: "#1e3a5f",
28
+ accentForeground: "#93c5fd",
29
+ },
30
+ },
31
+ fonts: {
32
+ sans: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
33
+ mono: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace',
34
+ },
35
+ },
36
+ supports: ["blog", "docs", "portfolio"],
37
+ };
38
+
39
+ export const theme = baseTheme;
40
+ export default theme;
@@ -0,0 +1,23 @@
1
+ :root {
2
+ --noxion-primary: #2563eb;
3
+ --noxion-primaryForeground: #ffffff;
4
+ --noxion-background: #ffffff;
5
+ --noxion-foreground: #0a0a0a;
6
+ --noxion-muted: #f5f5f5;
7
+ --noxion-mutedForeground: #737373;
8
+ --noxion-border: #e5e7eb;
9
+ --noxion-accent: #f0f9ff;
10
+ --noxion-accentForeground: #1e40af;
11
+ }
12
+
13
+ [data-theme="dark"] {
14
+ --noxion-primary: #3b82f6;
15
+ --noxion-primaryForeground: #ffffff;
16
+ --noxion-background: #0a0a0a;
17
+ --noxion-foreground: #fafafa;
18
+ --noxion-muted: #262626;
19
+ --noxion-mutedForeground: #a3a3a3;
20
+ --noxion-border: #404040;
21
+ --noxion-accent: #1e3a5f;
22
+ --noxion-accentForeground: #93c5fd;
23
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "sourceMap": true,
9
+ "outDir": "./dist",
10
+ "rootDir": "./src",
11
+ "strict": true,
12
+ "esModuleInterop": true,
13
+ "skipLibCheck": true,
14
+ "forceConsistentCasingInFileNames": true,
15
+ "isolatedModules": true,
16
+ "jsx": "react-jsx"
17
+ },
18
+ "include": ["src/**/*.ts", "src/**/*.tsx"],
19
+ "exclude": ["node_modules", "dist"]
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-noxion",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "CLI scaffolding tool for Noxion projects",
5
5
  "license": "MIT",
6
6
  "type": "module",