Skip to content

Commit fd10c85

Browse files
authored
Merge pull request #29 from objectstack-ai/copilot/adjust-example-architecture
2 parents 80cfa60 + 3ad7452 commit fd10c85

File tree

11 files changed

+189
-25
lines changed

11 files changed

+189
-25
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
# run: pnpm exec tsc --noEmit
4141

4242
- name: Build
43-
run: pnpm run build
43+
run: pnpm run build:site
4444
env:
4545
NODE_ENV: production
4646

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,7 @@ next-env.d.ts
3434

3535
# fumadocs
3636
.source
37-
.next
37+
.next
38+
39+
# objectdocs
40+
content/.objectdocs

README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,21 @@ Add the following scripts to your `package.json`:
8080
}
8181
```
8282

83-
### 3. Add content
83+
### 3. Initialize ObjectDocs
84+
85+
Run the init command to set up the site engine:
86+
87+
```bash
88+
pnpm objectdocs init
89+
```
90+
91+
This will:
92+
- Copy the site engine to `content/.objectdocs`
93+
- Install necessary dependencies
94+
- Automatically add `content/.objectdocs` to `.gitignore`
95+
- Prepare your project for development
96+
97+
### 4. Add content
8498

8599
Create the basic directory structure:
86100

@@ -109,7 +123,7 @@ Create `content/docs/meta.json`:
109123
}
110124
```
111125

112-
### 4. Start the server
126+
### 5. Start the server
113127

114128
```bash
115129
pnpm dev
@@ -124,6 +138,7 @@ ObjectDocs enforces a clear directory structure to ensure maintainability at sca
124138
```text
125139
.
126140
├── content/ # [Data Layer] Raw Content
141+
│ ├── .objectdocs/ # Site engine (auto-generated by init)
127142
│ ├── docs.site.json # Global settings (Nav, Logo, Branding)
128143
│ └── docs/
129144
│ ├── meta.json # Directory structure & sorting control

examples/starter/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,6 @@ pnpm-debug.log*
3434
# TypeScript
3535
*.tsbuildinfo
3636
next-env.d.ts
37+
38+
# ObjectDocs
39+
content/.objectdocs

examples/starter/README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ This starter template serves multiple purposes:
2323
```
2424
examples/starter/
2525
├── content/
26+
│ ├── .objectdocs/ # Site engine (created by init command)
2627
│ ├── docs.site.json # Global site configuration
2728
│ └── docs/
2829
│ ├── meta.json # Sidebar navigation structure
@@ -55,7 +56,18 @@ cd examples/starter
5556
pnpm install
5657
```
5758

58-
This will install `@objectdocs/cli` from the workspace, which in turn will use `@objectdocs/site` as a dependency.
59+
This will install `@objectdocs/cli` from the workspace.
60+
61+
3. Initialize ObjectDocs:
62+
63+
```bash
64+
pnpm objectdocs init
65+
```
66+
67+
This command will:
68+
- Copy the `@objectdocs/site` engine to `content/.objectdocs`
69+
- Install necessary dependencies
70+
- Prepare your project for development
5971

6072
### Development
6173

@@ -139,6 +151,7 @@ For more details on Vercel deployment, see [VERCEL.md](./VERCEL.md).
139151
Use this checklist to validate the starter works correctly:
140152

141153
- [ ] `pnpm install` completes without errors
154+
- [ ] `pnpm objectdocs init` initializes the site successfully
142155
- [ ] `pnpm dev` starts the development server
143156
- [ ] All pages load correctly in the browser
144157
- [ ] Navigation works (sidebar, header links)

packages/cli/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,21 @@ pnpm install
2323

2424
## Usage
2525

26+
### Initialize Site
27+
28+
Before using the development or build commands, you need to initialize the site:
29+
30+
```bash
31+
# Initialize ObjectDocs site in content/.objectdocs
32+
pnpm objectdocs init
33+
```
34+
35+
This command:
36+
- Copies the `@objectdocs/site` package to `content/.objectdocs`
37+
- Installs necessary dependencies
38+
- Automatically adds `content/.objectdocs` to `.gitignore`
39+
- Prepares your project for local development
40+
2641
### Site Management
2742

2843
The CLI can also be used to run the documentation site locally with a VitePress-like experience.

packages/cli/bin/cli.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@
99

1010
import { cac } from 'cac';
1111
import 'dotenv/config';
12+
import { registerInitCommand } from '../src/commands/init.mjs';
1213
import { registerTranslateCommand } from '../src/commands/translate.mjs';
1314
import { registerDevCommand } from '../src/commands/dev.mjs';
1415
import { registerBuildCommand } from '../src/commands/build.mjs';
1516
import { registerStartCommand } from '../src/commands/start.mjs';
1617

1718
const cli = cac('objectdocs');
1819

20+
registerInitCommand(cli);
1921
registerTranslateCommand(cli);
2022
registerDevCommand(cli);
2123
registerBuildCommand(cli);

packages/cli/src/commands/build.mjs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ export function registerBuildCommand(cli) {
2323
// 1. Resolve user's docs directory
2424
const docsDir = dir ? path.resolve(process.cwd(), dir) : path.resolve(process.cwd(), 'content/docs');
2525

26-
// 2. Resolve the Next.js App directory
27-
let nextAppDir;
28-
try {
29-
nextAppDir = path.dirname(require.resolve('@objectdocs/site/package.json'));
30-
} catch (e) {
31-
// Fallback for local development
32-
nextAppDir = path.resolve(__dirname, '../../../site');
26+
// 2. Resolve the Next.js App directory - use local .objectdocs first
27+
let nextAppDir = path.resolve(process.cwd(), 'content/.objectdocs');
28+
29+
if (!fs.existsSync(nextAppDir)) {
30+
console.log('⚠️ ObjectDocs site not found at content/.objectdocs');
31+
console.log(' Run "objectdocs init" first to initialize the site.\n');
32+
process.exit(1);
3333
}
3434

3535
// Copy user config and assets to nextAppDir

packages/cli/src/commands/dev.mjs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ export function registerDevCommand(cli) {
2424
// 1. Resolve user's docs directory (Absolute path)
2525
const docsDir = dir ? path.resolve(process.cwd(), dir) : path.resolve(process.cwd(), 'content/docs');
2626

27-
// 2. Resolve the Next.js App directory
28-
let nextAppDir;
29-
try {
30-
nextAppDir = path.dirname(require.resolve('@objectdocs/site/package.json'));
31-
} catch (e) {
32-
// Fallback for local development
33-
nextAppDir = path.resolve(__dirname, '../../../site');
27+
// 2. Resolve the Next.js App directory - use local .objectdocs first
28+
let nextAppDir = path.resolve(process.cwd(), 'content/.objectdocs');
29+
30+
if (!fs.existsSync(nextAppDir)) {
31+
console.log('⚠️ ObjectDocs site not found at content/.objectdocs');
32+
console.log(' Run "objectdocs init" first to initialize the site.\n');
33+
process.exit(1);
3434
}
3535

3636
console.log(`Starting docs server...`);

packages/cli/src/commands/init.mjs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/**
2+
* ObjectDocs
3+
* Copyright (c) 2026-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
import { spawn } from 'child_process';
10+
import path from 'path';
11+
import fs from 'fs';
12+
import { fileURLToPath } from 'url';
13+
import { createRequire } from 'module';
14+
15+
const __filename = fileURLToPath(import.meta.url);
16+
const __dirname = path.dirname(__filename);
17+
const require = createRequire(import.meta.url);
18+
19+
export function registerInitCommand(cli) {
20+
cli
21+
.command('init', 'Initialize ObjectDocs site in content/.objectdocs')
22+
.action(async (options) => {
23+
console.log('Initializing ObjectDocs...\n');
24+
25+
const targetDir = path.resolve(process.cwd(), 'content/.objectdocs');
26+
27+
// Check if already initialized
28+
if (fs.existsSync(targetDir)) {
29+
console.log(`⚠️ ObjectDocs already initialized at ${targetDir}`);
30+
console.log(' Delete the directory if you want to reinitialize.\n');
31+
return;
32+
}
33+
34+
// Resolve the site package directory
35+
let siteDir;
36+
try {
37+
siteDir = path.dirname(require.resolve('@objectdocs/site/package.json'));
38+
} catch (e) {
39+
// Fallback for local development
40+
siteDir = path.resolve(__dirname, '../../../site');
41+
}
42+
43+
console.log(`📦 Copying site from: ${siteDir}`);
44+
console.log(`📁 Target directory: ${targetDir}\n`);
45+
46+
// Create target directory
47+
fs.mkdirSync(targetDir, { recursive: true });
48+
49+
// Copy site files to target directory
50+
fs.cpSync(siteDir, targetDir, {
51+
recursive: true,
52+
filter: (source) => {
53+
const basename = path.basename(source);
54+
// Skip node_modules, .next, and other build artifacts
55+
if (basename === 'node_modules' ||
56+
basename === '.next' ||
57+
basename === 'out' ||
58+
basename === '.turbo' ||
59+
basename === 'dist') {
60+
return false;
61+
}
62+
return true;
63+
}
64+
});
65+
66+
console.log('✅ ObjectDocs site copied successfully!\n');
67+
68+
// Add to .gitignore
69+
const gitignorePath = path.resolve(process.cwd(), '.gitignore');
70+
const gitignoreEntry = 'content/.objectdocs';
71+
72+
try {
73+
let gitignoreContent = '';
74+
if (fs.existsSync(gitignorePath)) {
75+
gitignoreContent = fs.readFileSync(gitignorePath, 'utf-8');
76+
}
77+
78+
// Check if the entry already exists (as a complete line)
79+
const lines = gitignoreContent.split('\n').map(line => line.trim());
80+
if (!lines.includes(gitignoreEntry)) {
81+
// Add the entry with a comment
82+
const separator = gitignoreContent.trim() ? '\n\n' : '';
83+
const newContent = `${gitignoreContent.trim()}${separator}# ObjectDocs\n${gitignoreEntry}\n`;
84+
fs.writeFileSync(gitignorePath, newContent);
85+
console.log('📝 Added content/.objectdocs to .gitignore\n');
86+
}
87+
} catch (e) {
88+
console.warn('⚠️ Could not update .gitignore:', e.message);
89+
}
90+
91+
// Install dependencies in the target directory
92+
console.log('📦 Installing dependencies...\n');
93+
94+
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
95+
const installProcess = spawn(npmCmd, ['install', '--legacy-peer-deps'], {
96+
cwd: targetDir,
97+
stdio: 'inherit'
98+
});
99+
100+
installProcess.on('close', (code) => {
101+
if (code === 0) {
102+
console.log('\n✅ Dependencies installed successfully!');
103+
console.log('\n🎉 ObjectDocs initialized! You can now run:');
104+
console.log(' pnpm dev - Start development server');
105+
console.log(' pnpm build - Build for production\n');
106+
} else {
107+
console.error('\n❌ Failed to install dependencies');
108+
process.exit(code);
109+
}
110+
});
111+
});
112+
}

0 commit comments

Comments
 (0)