|
| 1 | +# Book Mode Conference Note Generator |
| 2 | + |
| 3 | +This example demonstrates how to create a "book mode" conference note system using the HackMD API. Book mode is a Markdown note that contains organized links to each session note page, making it easy for conference attendees to navigate between different session notes. |
| 4 | + |
| 5 | +## What This Example Does |
| 6 | + |
| 7 | +The script performs the following actions: |
| 8 | + |
| 9 | +1. **Loads Session Data**: Reads conference session information from `sessions.json` |
| 10 | +2. **Creates Individual Session Notes**: For each session, creates a dedicated HackMD note with: |
| 11 | + - Session title and speaker information |
| 12 | + - Embedded announcement note |
| 13 | + - Sections for notes, discussion, and related links |
| 14 | + - Appropriate tags and permissions |
| 15 | +3. **Generates Main Book Note**: Creates a master note that: |
| 16 | + - Contains welcome information and useful links |
| 17 | + - Organizes all session notes by day and time |
| 18 | + - Provides easy navigation to all sessions |
| 19 | + - Serves as a central hub for the conference |
| 20 | + |
| 21 | +## Features |
| 22 | + |
| 23 | +- **TypeScript Implementation**: Written in TypeScript with full type safety |
| 24 | +- **Configurable Constants**: All configuration is centralized at the top of the file |
| 25 | +- **Comprehensive Comments**: Well-documented code explaining each section |
| 26 | +- **Error Handling**: Graceful handling of API failures |
| 27 | +- **tsx Support**: Can be run directly without compilation using tsx |
| 28 | +- **Modular Design**: Functions are exportable for potential reuse |
| 29 | +- **Flexible Session Data**: Supports various session types and multilingual content |
| 30 | + |
| 31 | +## Setup |
| 32 | + |
| 33 | +### Prerequisites |
| 34 | + |
| 35 | +- Node.js (version 16 or higher) |
| 36 | +- A HackMD account with API access |
| 37 | +- Access to a HackMD team (for creating team notes) |
| 38 | + |
| 39 | +### Installation |
| 40 | + |
| 41 | +1. **Build the main HackMD API package** (if not already done): |
| 42 | + ```bash |
| 43 | + cd ../../nodejs |
| 44 | + npm install |
| 45 | + npm run build |
| 46 | + cd ../examples/book-mode-conference |
| 47 | + ``` |
| 48 | + |
| 49 | +2. **Install dependencies**: |
| 50 | + ```bash |
| 51 | + npm install |
| 52 | + ``` |
| 53 | + |
| 54 | +3. **Configure your HackMD access token**: |
| 55 | + |
| 56 | + **Option A: Environment Variable** |
| 57 | + ```bash |
| 58 | + # For Unix/Linux/macOS |
| 59 | + export HACKMD_ACCESS_TOKEN=your_access_token_here |
| 60 | + |
| 61 | + # For Windows PowerShell |
| 62 | + $env:HACKMD_ACCESS_TOKEN="your_access_token_here" |
| 63 | + ``` |
| 64 | + |
| 65 | + **Option B: .env File** |
| 66 | + ```bash |
| 67 | + cp .env.example .env |
| 68 | + # Edit .env and add your access token |
| 69 | + ``` |
| 70 | + |
| 71 | + You can get your access token from the [HackMD API documentation](https://hackmd.io/@hackmd-api/developer-portal). |
| 72 | + |
| 73 | +### Configuration |
| 74 | + |
| 75 | +Before running the script, you may want to customize the configuration constants at the top of `index.ts`: |
| 76 | + |
| 77 | +#### Essential Configuration |
| 78 | + |
| 79 | +```typescript |
| 80 | +// HackMD announcement note to embed in each session note |
| 81 | +const ANNOUNCEMENT_NOTE = '@DevOpsDay/rkO2jyLMlg' |
| 82 | + |
| 83 | +// Team path where notes will be created |
| 84 | +const TEAM_PATH = 'DevOpsDay' |
| 85 | + |
| 86 | +// Conference details |
| 87 | +const CONFERENCE_CONFIG = { |
| 88 | + name: 'DevOpsDays Taipei 2025', |
| 89 | + website: 'https://devopsdays.tw/', |
| 90 | + community: 'https://www.facebook.com/groups/DevOpsTaiwan/', |
| 91 | + tags: 'DevOpsDays Taipei 2025' |
| 92 | +} |
| 93 | +``` |
| 94 | + |
| 95 | +#### Session Data Format |
| 96 | + |
| 97 | +The script expects session data in `sessions.json` with the following structure: |
| 98 | + |
| 99 | +```json |
| 100 | +[ |
| 101 | + { |
| 102 | + "id": "session-001", |
| 103 | + "title": "Session Title", |
| 104 | + "speaker": [ |
| 105 | + { |
| 106 | + "speaker": { |
| 107 | + "public_name": "Speaker Name" |
| 108 | + } |
| 109 | + } |
| 110 | + ], |
| 111 | + "session_type": "talk", |
| 112 | + "started_at": "2025-03-15T09:00:00Z", |
| 113 | + "finished_at": "2025-03-15T09:30:00Z", |
| 114 | + "tags": ["tag1", "tag2"], |
| 115 | + "classroom": { |
| 116 | + "tw_name": "會議室名稱", |
| 117 | + "en_name": "Room Name" |
| 118 | + }, |
| 119 | + "language": "en", |
| 120 | + "difficulty": "General" |
| 121 | + } |
| 122 | +] |
| 123 | +``` |
| 124 | + |
| 125 | +## Running the Example |
| 126 | + |
| 127 | +### Development Mode (with file watching) |
| 128 | +```bash |
| 129 | +npm run dev |
| 130 | +``` |
| 131 | + |
| 132 | +### Production Mode |
| 133 | +```bash |
| 134 | +npm start |
| 135 | +``` |
| 136 | + |
| 137 | +### Direct Execution with tsx |
| 138 | +```bash |
| 139 | +npx tsx index.ts |
| 140 | +``` |
| 141 | + |
| 142 | +## Sample Session Data |
| 143 | + |
| 144 | +The included `sessions.json` contains sample conference session data with: |
| 145 | + |
| 146 | +- **Multiple session types**: keynotes, talks, workshops |
| 147 | +- **Multi-day schedule**: Sessions across different days |
| 148 | +- **Bilingual support**: English and Traditional Chinese sessions |
| 149 | +- **Various difficulty levels**: General, Beginner, Intermediate, Advanced |
| 150 | +- **Multiple speakers**: Examples of single and multiple speaker sessions |
| 151 | + |
| 152 | +## Generated Output |
| 153 | + |
| 154 | +The script will create: |
| 155 | + |
| 156 | +1. **Individual Session Notes**: Each with a dedicated HackMD note containing: |
| 157 | + - Session title with speaker names |
| 158 | + - Embedded announcement note |
| 159 | + - Sections for collaborative note-taking |
| 160 | + - Discussion area |
| 161 | + - Related links |
| 162 | + |
| 163 | +2. **Main Conference Book**: A master note containing: |
| 164 | + - Conference welcome information |
| 165 | + - Organized schedule with links to all session notes |
| 166 | + - Quick navigation by day and time |
| 167 | + - Useful conference resources |
| 168 | + |
| 169 | +### Example Output |
| 170 | + |
| 171 | +``` |
| 172 | +=== Creating Individual Session Notes === |
| 173 | +✓ Created note for: Welcome to DevOpsDays - John Doe |
| 174 | +✓ Created note for: Introduction to CI/CD - Jane Smith |
| 175 | +✓ Created note for: Advanced Kubernetes Operations - Alex Chen & Sarah Wilson |
| 176 | +... |
| 177 | +
|
| 178 | +=== Session URLs === |
| 179 | +[ |
| 180 | + { |
| 181 | + "id": "session-001", |
| 182 | + "url": "https://hackmd.io/abc123", |
| 183 | + "title": "Welcome to DevOpsDays - John Doe" |
| 184 | + }, |
| 185 | + ... |
| 186 | +] |
| 187 | +
|
| 188 | +=== Main Conference Book Created === |
| 189 | +✓ Book URL: https://hackmd.io/xyz789 |
| 190 | +🎉 Book mode conference notes created successfully! |
| 191 | +📚 Main book contains links to 6 session notes |
| 192 | +``` |
| 193 | + |
| 194 | +## Customization |
| 195 | + |
| 196 | +### Modifying Note Templates |
| 197 | + |
| 198 | +You can customize the session note template by modifying the `generateSessionNoteContent` function: |
| 199 | + |
| 200 | +```typescript |
| 201 | +function generateSessionNoteContent(session: ProcessedSession): string { |
| 202 | + return `# ${session.title} |
| 203 | +
|
| 204 | +{%hackmd ${ANNOUNCEMENT_NOTE} %} |
| 205 | +
|
| 206 | +## Your Custom Section |
| 207 | +> Add your custom content here |
| 208 | +
|
| 209 | +## ${SESSION_NOTE_CONFIG.sections.notes} |
| 210 | +> ${SESSION_NOTE_CONFIG.sections.notesDescription} |
| 211 | +
|
| 212 | +// ... rest of template |
| 213 | +` |
| 214 | +} |
| 215 | +``` |
| 216 | + |
| 217 | +### Changing the Book Structure |
| 218 | + |
| 219 | +The book organization can be modified by changing the nesting keys in the main function: |
| 220 | + |
| 221 | +```typescript |
| 222 | +// Current: organize by day, then by start time |
| 223 | +const nestedSessions = nest(sessionList.filter(s => s.noteUrl !== 'error'), ['day', 'startTime']) |
| 224 | + |
| 225 | +// Alternative: organize by session type, then by day |
| 226 | +const nestedSessions = nest(sessionList.filter(s => s.noteUrl !== 'error'), ['sessionType', 'day']) |
| 227 | +``` |
| 228 | + |
| 229 | +### Adding Additional Metadata |
| 230 | + |
| 231 | +You can extend the session data structure and processing by: |
| 232 | + |
| 233 | +1. Adding new fields to the `ProcessedSession` interface |
| 234 | +2. Updating the `loadAndProcessSessions` function to process new fields |
| 235 | +3. Modifying the note templates to include the new information |
| 236 | + |
| 237 | +## Error Handling |
| 238 | + |
| 239 | +The script includes comprehensive error handling: |
| 240 | + |
| 241 | +- **Missing Environment Variables**: Clear error messages with setup instructions |
| 242 | +- **Missing Session File**: Helpful error message with expected file location |
| 243 | +- **API Failures**: Individual session note failures don't stop the entire process |
| 244 | +- **Network Issues**: The HackMD API client includes built-in retry logic |
| 245 | + |
| 246 | +## Troubleshooting |
| 247 | + |
| 248 | +### Common Issues |
| 249 | + |
| 250 | +**"HACKMD_ACCESS_TOKEN environment variable is not set"** |
| 251 | +- Solution: Set your access token using one of the methods in the Setup section |
| 252 | + |
| 253 | +**"Sessions file not found"** |
| 254 | +- Solution: Ensure `sessions.json` exists in the same directory as `index.ts` |
| 255 | + |
| 256 | +**"Failed to create note for [session]"** |
| 257 | +- Check your team permissions |
| 258 | +- Verify the team path is correct |
| 259 | +- Ensure your access token has team note creation permissions |
| 260 | + |
| 261 | +**"Failed to create main book"** |
| 262 | +- Same troubleshooting steps as individual notes |
| 263 | +- Check that you have sufficient API quota remaining |
| 264 | + |
| 265 | +### Development Tips |
| 266 | + |
| 267 | +1. **Start Small**: Test with a few sessions first by modifying `sessions.json` |
| 268 | +2. **Check Permissions**: Ensure your HackMD team allows note creation |
| 269 | +3. **Monitor Rate Limits**: The script includes built-in retry logic, but be mindful of API limits |
| 270 | +4. **Backup Data**: Consider backing up important notes before running the script |
| 271 | + |
| 272 | +## API Features Demonstrated |
| 273 | + |
| 274 | +This example showcases several HackMD API features: |
| 275 | + |
| 276 | +- **Team Note Creation**: Creating notes within a team context |
| 277 | +- **Permission Management**: Setting read/write permissions for notes |
| 278 | +- **Content Templates**: Using consistent note structures |
| 279 | +- **Bulk Operations**: Creating multiple notes programmatically |
| 280 | +- **Error Handling**: Graceful handling of API errors |
| 281 | + |
| 282 | +## License |
| 283 | + |
| 284 | +This example is part of the HackMD API client and is licensed under the MIT License. |
| 285 | + |
| 286 | +## Contributing |
| 287 | + |
| 288 | +If you have suggestions for improving this example or find bugs, please open an issue or submit a pull request to the main repository. |
0 commit comments