jekyll-notion-cms 1.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 89eeb4c8a68356250340a7d9d5c5ecab86f0e48d82a2f79dfb25a8126e316204
4
+ data.tar.gz: 15c7213ec7bcb8d5178b0b237fd38d573fcc180060bd4c7b3ef43beed7c069a0
5
+ SHA512:
6
+ metadata.gz: 3607b7445372d94c2e307a0a4e97b660d4df71ec910e5062297a1b3bad4579e8d24b611a4e92dcfd9adbf8a4a4090c4adc1342d938b2ccf425fe401b0c29c0bd
7
+ data.tar.gz: 726d1ad69582b93f779b97b3cca31fb642cdbfe04da56692fb4458ba77f398681f5ca270e15e07bb42179af6909060e21612a4202e2fa734f4f398ed409c0138
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,87 @@
1
+ require:
2
+ - rubocop-rspec
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.7
6
+ NewCops: enable
7
+ SuggestExtensions: false
8
+ Exclude:
9
+ - 'vendor/**/*'
10
+ - 'spec/fixtures/**/*'
11
+
12
+ # Naming
13
+ Naming/FileName:
14
+ Exclude:
15
+ - 'lib/jekyll-notion-cms.rb'
16
+
17
+ # Gemspec
18
+ Gemspec/DevelopmentDependencies:
19
+ Enabled: false
20
+
21
+ # Metrics
22
+ Metrics/AbcSize:
23
+ Max: 35
24
+
25
+ Metrics/BlockLength:
26
+ Max: 35
27
+ Exclude:
28
+ - 'spec/**/*'
29
+ - '*.gemspec'
30
+
31
+ Metrics/MethodLength:
32
+ Max: 45
33
+
34
+ Metrics/ClassLength:
35
+ Max: 200
36
+
37
+ Metrics/ModuleLength:
38
+ Max: 250
39
+
40
+ Metrics/CyclomaticComplexity:
41
+ Max: 25
42
+
43
+ Metrics/PerceivedComplexity:
44
+ Max: 12
45
+
46
+ # Style
47
+ Style/Documentation:
48
+ Enabled: false
49
+
50
+ Style/StringLiterals:
51
+ EnforcedStyle: single_quotes
52
+
53
+ Style/FrozenStringLiteralComment:
54
+ Enabled: true
55
+
56
+ # Layout
57
+ Layout/LineLength:
58
+ Max: 120
59
+ Exclude:
60
+ - 'spec/**/*'
61
+
62
+ # Lint
63
+ Lint/DuplicateBranch:
64
+ Enabled: false
65
+
66
+ # RSpec
67
+ RSpec/ExampleLength:
68
+ Max: 25
69
+
70
+ RSpec/MultipleExpectations:
71
+ Max: 5
72
+
73
+ RSpec/NestedGroups:
74
+ Max: 4
75
+
76
+ RSpec/MultipleMemoizedHelpers:
77
+ Max: 10
78
+
79
+ RSpec/MessageSpies:
80
+ Enabled: false
81
+
82
+ RSpec/IndexedLet:
83
+ Enabled: false
84
+
85
+ # Capybara
86
+ Capybara/RSpec/PredicateMatcher:
87
+ Enabled: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,48 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Changed
11
+
12
+ - **BREAKING**: Renamed `skills_by_category` organizer to `items_by_category` for more generic usage
13
+ - **BREAKING**: Output key `skills` renamed to `items` in `items_by_category` organizer
14
+
15
+ ### Added
16
+
17
+ - Documentation: use cases, examples (projects, services, testimonials, skills)
18
+ - Documentation: automation section with GitHub Actions and n8n workflow templates
19
+ - Architecture diagram
20
+
21
+ ## [1.0.0] - 2026-01-21
22
+
23
+ ### Added
24
+
25
+ - Initial release of jekyll-notion-cms
26
+ - Configurable collections via `_config.yml`
27
+ - Support for multiple Notion property types:
28
+ - Title, Rich text, Number, Checkbox
29
+ - Date, Select, Multi-select, URL
30
+ - Email, Phone number, Files
31
+ - Rollup, Formula, Relation
32
+ - People, Status, Created/Last edited time
33
+ - Multiple data organizers:
34
+ - `simple_list` - Sorted array of items
35
+ - `items_by_category` - Items grouped by category (skills, products, etc.)
36
+ - `grouped_by` - Items grouped by a field
37
+ - `nested` - Hierarchical tree structure
38
+ - Automatic fallback to Jekyll collections
39
+ - Pagination support for large databases
40
+ - Data file caching to avoid unnecessary regeneration
41
+ - Comprehensive logging
42
+
43
+ ### Security
44
+
45
+ - Secure handling of Notion API tokens via environment variables
46
+
47
+ [Unreleased]: https://github.com/maxime-lenne/jekyll-notion-cms/compare/v1.0.0...HEAD
48
+ [1.0.0]: https://github.com/maxime-lenne/jekyll-notion-cms/releases/tag/v1.0.0
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in jekyll-notion-cms.gemspec
6
+ gemspec
7
+
8
+ group :development do
9
+ gem 'pry', '~> 0.14'
10
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 Maxime Lenne
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,362 @@
1
+ # Jekyll Notion CMS
2
+
3
+ <p align="center">
4
+ <img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/notion/notion-original.svg" alt="Notion" width="80" height="80" />
5
+ <img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/jekyll/jekyll-original.svg" alt="Jekyll" width="80" height="80" />
6
+ <img src="https://upload.vectorlogo.zone/logos/n8nio/images/b751b1e9-f500-4b33-b8b1-3b8126059c0c.svg" alt="n8n" width="80" height="80" />
7
+ <img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/githubactions/githubactions-original-wordmark.svg" alt="Github Action" width="80" height="80" />
8
+ </p>
9
+
10
+ <p align="center">
11
+ <strong>Use Notion as a CMS for your Jekyll static site</strong>
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="https://badge.fury.io/rb/jekyll-notion-cms"><img src="https://badge.fury.io/rb/jekyll-notion-cms.svg" alt="Gem Version" /></a>
16
+ <a href="https://github.com/maxime-lenne/jekyll-notion-cms/actions/workflows/ci.yml"><img src="https://github.com/maxime-lenne/jekyll-notion-cms/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
17
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
18
+ </p>
19
+
20
+ ---
21
+
22
+ A configurable Jekyll plugin that fetches content from Notion databases and makes it available as Jekyll data files. Perfect for building landing pages, portfolios, blogs, and resumes with Notion as your content management system.
23
+
24
+ ## Features
25
+
26
+ - **Configurable Collections**: Define any number of Notion database collections via `_config.yml`
27
+ - **Multiple Organizers**: Support for different data organization patterns (simple list, grouped, skills by category, nested)
28
+ - **All Property Types**: Support for all Notion property types (text, number, date, select, multi-select, relations, rollups, formulas, files, etc.)
29
+ - **Fallback System**: Automatic fallback to Jekyll collections when Notion is unavailable
30
+ - **Pagination**: Handles large databases with automatic pagination
31
+ - **Caching**: Intelligent file caching to avoid unnecessary regenerations
32
+
33
+
34
+ ## Architecture
35
+
36
+ <p align="center">
37
+ <img src="docs/architecture.png" alt="Jekyll Notion CMS Architecture" width="800" />
38
+ </p>
39
+
40
+ The diagram above shows how Jekyll Notion CMS integrates with your workflow:
41
+
42
+ 1. **Content editing** in Notion databases
43
+ 2. **Change detection** via n8n polling or webhooks
44
+ 3. **Build trigger** through GitHub Actions workflow_dispatch
45
+ 4. **Static site generation** with Jekyll + jekyll-notion-cms
46
+ 5. **Deployment** to GitHub Pages (or any static host)
47
+
48
+ ## Use Cases
49
+
50
+ ### Landing Page
51
+
52
+ Build dynamic landing pages with content managed entirely in Notion:
53
+
54
+ | Content Type | Notion Database | Description |
55
+ |--------------|-----------------|-------------|
56
+ | **Services** | Services DB | List your offerings with icons, descriptions, and pricing |
57
+ | **Testimonials** | Testimonials DB | Client reviews with photos, quotes, and ratings |
58
+ | **Team** | Team DB | Team member profiles with photos and bios |
59
+ | **FAQ** | FAQ DB | Frequently asked questions organized by category |
60
+
61
+ ### Portfolio
62
+
63
+ Showcase your work with a portfolio powered by Notion:
64
+
65
+ | Content Type | Notion Database | Description |
66
+ |--------------|-----------------|-------------|
67
+ | **Projects** | Projects DB | Portfolio pieces with images, descriptions, and links |
68
+ | **Skills** | Skills DB | Technical skills organized by category with proficiency levels |
69
+ | **Certifications** | Certifications DB | Professional certifications and badges |
70
+
71
+ ### Blog
72
+
73
+ Run a full-featured blog with Notion as your writing tool:
74
+
75
+ | Content Type | Notion Database | Description |
76
+ |--------------|-----------------|-------------|
77
+ | **Posts** | Blog DB | Articles with rich text, tags, and publication dates |
78
+ | **Categories** | Categories DB | Blog categories for organization |
79
+ | **Authors** | Authors DB | Author profiles for multi-author blogs |
80
+
81
+ ### Resume / CV
82
+
83
+ Create a dynamic online resume:
84
+
85
+ | Content Type | Notion Database | Description |
86
+ |--------------|-----------------|-------------|
87
+ | **Experiences** | Experiences DB | Work history with dates, companies, and descriptions |
88
+ | **Education** | Education DB | Academic background and degrees |
89
+ | **Skills** | Skills DB | Technical and soft skills with proficiency |
90
+ | **Languages** | Languages DB | Language proficiencies |
91
+
92
+ ## Installation
93
+
94
+ Add this line to your application's Gemfile:
95
+
96
+ ```ruby
97
+ gem 'jekyll-notion-cms'
98
+ ```
99
+
100
+ And then execute:
101
+
102
+ ```bash
103
+ bundle install
104
+ ```
105
+
106
+ Or install it yourself as:
107
+
108
+ ```bash
109
+ gem install jekyll-notion-cms
110
+ ```
111
+
112
+ ## Quick Start
113
+
114
+ ### 1. Set up your Notion Integration
115
+
116
+ 1. Go to [Notion Developers](https://www.notion.so/my-integrations)
117
+ 2. Create a new integration
118
+ 3. Copy the Internal Integration Token
119
+ 4. Share your Notion databases with the integration
120
+
121
+ ### 2. Configure Environment Variables
122
+
123
+ ```bash
124
+ export NOTION_TOKEN=secret_xxx
125
+ export NOTION_EXPERIENCES_DB=your_database_id
126
+ export NOTION_BLOG_DB=your_blog_database_id
127
+ ```
128
+
129
+ ### 3. Add Configuration to `_config.yml`
130
+
131
+ ```yaml
132
+ notion:
133
+ enabled: true
134
+
135
+ collections:
136
+ experiences:
137
+ database_env: NOTION_EXPERIENCES_DB
138
+ data_file: notion_experiences.yml
139
+ organizer: simple_list
140
+ sort_by: order
141
+ properties:
142
+ - { name: Title, type: title }
143
+ - { name: Company, type: rich_text }
144
+ - { name: Start Date, type: date, key: start_date }
145
+ - { name: Current, type: checkbox }
146
+ - { name: Tags, type: multi_select }
147
+
148
+ blog_posts:
149
+ database_env: NOTION_BLOG_DB
150
+ data_file: notion_blog_posts.yml
151
+ organizer: simple_list
152
+ sort_by: published_at
153
+ sort_order: desc
154
+ properties:
155
+ - { name: Title, type: title }
156
+ - { name: Slug, type: rich_text }
157
+ - { name: Language, type: select }
158
+ - { name: Published At, type: date, key: published_at }
159
+ - { name: Status, type: select }
160
+ - { name: Excerpt, type: rich_text }
161
+ - { name: Tags, type: multi_select }
162
+ ```
163
+
164
+ ### 4. Use Data in Templates
165
+
166
+ ```liquid
167
+ {% for exp in site.data.notion_experiences %}
168
+ <h3>{{ exp.title }}</h3>
169
+ <p>{{ exp.company }} - {{ exp.start_date }}</p>
170
+ {% endfor %}
171
+ ```
172
+
173
+ ## Examples & Configuration
174
+
175
+ For detailed examples and configuration reference, see **[Examples & Configuration](docs/EXAMPLES_AND_CONFIGURATION.md)**.
176
+
177
+ **Examples included:**
178
+ - Projects Database (portfolio, case studies)
179
+ - Services Database (freelancers, agencies)
180
+ - Testimonials Database (client reviews)
181
+ - Skills Database (technical expertise)
182
+
183
+ **Configuration reference:**
184
+ - Collection options
185
+ - Organizer types (`simple_list`, `items_by_category`, `grouped_by`, `nested`)
186
+ - All 18 property types supported
187
+ - Property configuration syntax
188
+
189
+ ## Fallback System
190
+
191
+ When Notion is unavailable, the plugin automatically falls back to Jekyll collections:
192
+
193
+ 1. **No `NOTION_TOKEN`**: Uses all Jekyll collections
194
+ 2. **Missing database ID**: Uses fallback for that collection
195
+ 3. **API Error**: Falls back gracefully with error logging
196
+
197
+ Create fallback collections in `_collections/`:
198
+
199
+ ```
200
+ _collections/
201
+ ├── _experiences/
202
+ │ ├── experience-1.md
203
+ │ └── experience-2.md
204
+ └── _blog_posts/
205
+ └── my-post.md
206
+ ```
207
+
208
+ ## Automation & Deployment
209
+
210
+ ### GitHub Actions Workflow
211
+
212
+ Copy the workflow template to your repository:
213
+
214
+ ```bash
215
+ cp docs/templates/github-actions_notion-sync.yml .github/workflows/notion-sync.yml
216
+ ```
217
+
218
+ **Full workflow file:** [`docs/templates/github-actions_notion-sync.yml`](docs/templates/github-actions_notion-sync.yml)
219
+
220
+ ```yaml
221
+ name: Notion Sync Workflow
222
+
223
+ on:
224
+ workflow_dispatch:
225
+ inputs:
226
+ notion_event:
227
+ description: 'Type of Notion event'
228
+ required: true
229
+ type: string
230
+ page_id:
231
+ description: 'Notion page ID'
232
+ required: true
233
+ type: string
234
+ database_id:
235
+ description: 'Notion database ID'
236
+ required: true
237
+ type: string
238
+ updated_at:
239
+ description: 'Last update timestamp'
240
+ required: true
241
+ type: string
242
+
243
+ permissions:
244
+ contents: read
245
+ pages: write
246
+ id-token: write
247
+
248
+ jobs:
249
+ build:
250
+ runs-on: ubuntu-latest
251
+ steps:
252
+ - name: Checkout
253
+ uses: actions/checkout@v4
254
+
255
+ - name: Setup Ruby
256
+ uses: ruby/setup-ruby@v1
257
+ with:
258
+ ruby-version: '3.3'
259
+ bundler-cache: true
260
+
261
+ - name: Build with Jekyll
262
+ run: bundle exec jekyll build
263
+ env:
264
+ JEKYLL_ENV: production
265
+ NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }}
266
+ NOTION_SKILLS_DB: ${{ secrets.NOTION_SKILLS_DB }}
267
+ NOTION_EXPERIENCES_DB: ${{ secrets.NOTION_EXPERIENCES_DB }}
268
+ NOTION_BLOG_DB: ${{ secrets.NOTION_BLOG_DB }}
269
+ # Add more database secrets as needed
270
+
271
+ - name: Upload artifact
272
+ uses: actions/upload-pages-artifact@v3
273
+
274
+ deploy:
275
+ environment:
276
+ name: github-pages
277
+ url: ${{ steps.deployment.outputs.page_url }}
278
+ runs-on: ubuntu-latest
279
+ needs: build
280
+ steps:
281
+ - name: Deploy to GitHub Pages
282
+ id: deployment
283
+ uses: actions/deploy-pages@v4
284
+ ```
285
+
286
+ ### Automatic Sync with n8n
287
+
288
+
289
+ Use [n8n](https://n8n.io) to automatically trigger builds when Notion content changes.
290
+
291
+ **Import the workflow template:** [`docs/templates/n8n-workflow_Notion-database-change-trigger-GitHub-Actions.json`](docs/templates/n8n-workflow_Notion-database-change-trigger-GitHub-Actions.json)
292
+
293
+ **Workflow steps:**
294
+
295
+ 1. **Notion Trigger** - Polls Notion database for changes (configurable interval)
296
+ 2. **GitHub Action** - Triggers `workflow_dispatch` event on your repository
297
+ 3. **Notification** (optional) - Sends Telegram/Slack message on deployment
298
+
299
+ **n8n Configuration:**
300
+
301
+ | Node | Configuration |
302
+ |------|---------------|
303
+ | Notion Trigger | Database ID, poll interval (e.g., every hour) |
304
+ | GitHub | Repository owner, repo name, workflow ID, branch |
305
+ | Telegram/Slack | Chat ID for notifications (optional) |
306
+
307
+ **Required credentials:**
308
+ - Notion API integration token
309
+ - GitHub Personal Access Token (with `repo` and `workflow` scopes)
310
+
311
+ ### Manual Trigger
312
+
313
+ You can also trigger the workflow manually via GitHub CLI:
314
+
315
+ ```bash
316
+ gh workflow run notion-sync.yml \
317
+ -f notion_event=manual \
318
+ -f page_id=none \
319
+ -f database_id=all \
320
+ -f updated_at=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
321
+ ```
322
+
323
+ Or via the GitHub Actions UI by clicking "Run workflow" on the Actions tab.
324
+
325
+ ## Development
326
+
327
+ After checking out the repo:
328
+
329
+ ```bash
330
+ # Install dependencies
331
+ bundle install
332
+
333
+ # Run tests
334
+ bundle exec rspec
335
+
336
+ # Run linter
337
+ bundle exec rubocop
338
+
339
+ # Run console
340
+ bundle exec rake console
341
+ ```
342
+
343
+ ## Contributing
344
+
345
+ Bug reports and pull requests are welcome on GitHub at https://github.com/maxime-lenne/jekyll-notion-cms.
346
+
347
+ 1. Fork it
348
+ 2. Create your feature branch (`git checkout -b feature/my-feature`)
349
+ 3. Commit your changes (`git commit -am 'Add my feature'`)
350
+ 4. Push to the branch (`git push origin feature/my-feature`)
351
+ 5. Create a Pull Request
352
+
353
+ ## License
354
+
355
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
356
+
357
+ ## Author
358
+
359
+ **Maxime Lenne** - [maxime-lenne.fr](https://maxime-lenne.fr)
360
+
361
+ - GitHub: [@maxime-lenne](https://github.com/maxime-lenne)
362
+ - LinkedIn: [maximelenne](https://linkedin.com/in/maximelenne)
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new
9
+
10
+ task default: %i[spec rubocop]
11
+
12
+ desc 'Run all tests and linters'
13
+ task ci: %i[spec rubocop]
14
+
15
+ desc 'Build and install gem locally'
16
+ task :install_local do
17
+ sh 'gem build jekyll-notion-cms.gemspec'
18
+ sh 'gem install jekyll-notion-cms-*.gem'
19
+ end
20
+
21
+ desc 'Run console with gem loaded'
22
+ task :console do
23
+ require 'pry'
24
+ require_relative 'lib/jekyll-notion-cms'
25
+ Pry.start
26
+ end