core-maugli 1.1.4 → 1.1.6

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.
package/README.md CHANGED
@@ -1,18 +1,12 @@
1
- # Maugli Blog - Astro & Tailwind CSS2. **Interface Language** - Choose from:
1
+ # Maugli Blog - Astro & Tailwind CSS Theme by maugli.cfd
2
2
 
3
- - 🇺🇸 English (default)
4
- - 🇷🇺 Русский
5
- - 🇪🇸 Español
6
- - 🇩🇪 Deutsch
7
- - 🇵🇹 Português
8
- - 🇫🇷 Français
9
- - 🇨🇳 中文
10
- - 🇯🇵 日本語
3
+ Hi-perfomance, SEO&AI-SEO optimised
11
4
 
12
- 3. **Main Domain** - Do you have a main domain to link this blog to? (e.g., mybrand.com - leave empty if none)
13
- 4. **Multilingual Support** - Enable/disable multiple languages (disabled by default)maugli.cfd
5
+ ## Introduction
14
6
 
15
- Hi-perfomance, SEO&AI-SEO optimised
7
+ Maugli is a lightweight, agent-friendly blog that can integrate into an existing site or run as a standalone project. Link the blog's logo to your primary site by setting `brand.logoHref` in [`src/config/maugli.config.ts`](src/config/maugli.config.ts).
8
+
9
+ The theme includes a `product` entity for showcasing offerings. Rename it (for example, to "services") and hide or customize related menu items by editing the `navLinks` array in the same configuration file.
16
10
 
17
11
  [![Deploy to Netlify Button](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/dashapps/maugli-astro-theme)
18
12
 
@@ -33,7 +27,7 @@ netlify deploy --prod
33
27
 
34
28
  ## Getting started
35
29
 
36
- To start a new project, run the interactive setup:
30
+ To start a new project in an empty folder run:
37
31
 
38
32
  ```bash
39
33
  npx core-maugli init my-blog
@@ -41,27 +35,23 @@ cd my-blog
41
35
  npm run dev
42
36
  ```
43
37
 
44
- ### Interactive Setup
38
+ To initialize inside the current folder use:
45
39
 
46
- The setup wizard will ask you to configure:
40
+ ```bash
41
+ npx core-maugli init .
42
+ ```
47
43
 
48
- 1. **Blog Name** - The display name for your blog (can be changed later in config)
49
- 2. **Interface Language** - Choose from:
50
- - 🇺🇸 English (default)
51
- - 🇸 Español
52
- - 🇩🇪 Deutsch
53
- - �� Português
54
- - �� Français
55
- - 🇨🇳 中文
56
- - 🇯🇵 日本語
57
- 3. **Main Domain** - Your main website URL (leave empty for local blog)
58
- 4. **Multilingual Support** - Enable/disable multiple languages (disabled by default)
44
+ The init script lets you choose a language or pass one with `--lang`. Available codes: `ru`, `en`, `es`, `de`, `pt`, `fr`, `zh`, `ja`.
59
45
 
60
- Your blog will be available at `http://localhost:4321/`
46
+ Example:
47
+
48
+ ```bash
49
+ npx core-maugli init my-blog --lang es
50
+ ```
61
51
 
62
- ### Manual Installation
52
+ You pick the language only once during project creation; updates won't ask again.
63
53
 
64
- If you prefer to install without the interactive setup:
54
+ Your blog will be available at `http://localhost:4321/`
65
55
 
66
56
  1. **Install dependencies**
67
57
 
@@ -92,39 +82,109 @@ If you prefer to install without the interactive setup:
92
82
  npm run build
93
83
  ```
94
84
 
95
- ### Testing
85
+ `npm run build` runs [`scripts/verify-assets.js`](scripts/verify-assets.js)
86
+ before the Astro build. This script checks the SHA-256 hashes of the
87
+ floating label component and footer badge to ensure they haven't been
88
+ modified. The floating label's hash is validated to ensure compliance
89
+ with licensing.
96
90
 
97
- Run the test suite to verify that example content is filtered correctly:
91
+ If you hold a commercial license and legitimately change the label,
92
+ generate its new SHA-256 hash and replace the value for
93
+ `src/components/MaugliFloatingLabel.astro` in the `files` object of
94
+ [`scripts/verify-assets.js`](scripts/verify-assets.js). For example:
98
95
 
99
96
  ```bash
100
- npm test
97
+ node -e "import { createHash } from 'crypto'; import { readFileSync } from 'fs'; console.log(createHash('sha256').update(readFileSync('src/components/MaugliFloatingLabel.astro')).digest('hex'))"
101
98
  ```
102
99
 
103
- All tests should complete without errors.
100
+ If you change these assets without updating their hashes in the
101
+ script, the build will fail.
102
+
103
+ ### Customizing fonts
104
+
105
+ This project uses [Fontsource](https://fontsource.org/) for typography. To add a different font, install the desired package:
106
+
107
+ ```bash
108
+ npm install @fontsource-variable/roboto
109
+ ```
110
+
111
+ Then replace or add the corresponding `@import` line in [`src/styles/global.css`](src/styles/global.css):
112
+
113
+ ```css
114
+ @import '@fontsource-variable/roboto/wght.css' layer(base);
115
+ ```
116
+
117
+ Update the `--font-sans` or `--font-serif` variables in the same file so Tailwind uses the new font:
118
+
119
+ ```css
120
+ --font-sans: 'Roboto Variable', sans-serif;
121
+ /* or */
122
+ --font-serif: 'Roboto Variable', sans-serif;
123
+ ```
124
+
125
+ Repeat these steps for any other fonts you want to include.
126
+
127
+ ### Configuring PWA colors and icons
128
+
129
+ Progressive Web App options live under the `pwa` key in [`src/config/maugli.config.ts`](src/config/maugli.config.ts). The section accepts:
104
130
 
105
- ## Configuration
131
+ - `themeColor` – used for the manifest's `theme_color` and the `<meta name="theme-color">` tag
132
+ - `backgroundColor` – controls the manifest's `background_color`
133
+ - `icons` – array of icon definitions with `src`, `sizes`, `type`, and optional `purpose`
106
134
 
107
- ### Initial Setup
135
+ Example configuration:
108
136
 
109
- The interactive setup automatically configures your blog based on your choices. All settings can be changed later in `src/config/maugli.config.ts`.
137
+ ```ts
138
+ // src/config/maugli.config.ts
139
+ export const maugliConfig = {
140
+ // ...other fields
141
+ pwa: {
142
+ themeColor: '#0cbf11',
143
+ backgroundColor: '#ffffff',
144
+ icons: [
145
+ { src: '/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any maskable' },
146
+ { src: '/icon-512.png', sizes: '512x512', type: 'image/png' }
147
+ ]
148
+ }
149
+ };
150
+ ```
151
+
152
+ These values are referenced in `astro.config.mjs` when generating the manifest:
153
+
154
+ ```js
155
+ // astro.config.mjs
156
+ import { maugliConfig } from './src/config/maugli.config';
157
+
158
+ export const pwaOptions = {
159
+ manifest: {
160
+ background_color: maugliConfig.pwa?.backgroundColor,
161
+ theme_color: maugliConfig.pwa?.themeColor,
162
+ icons: maugliConfig.pwa?.icons
163
+ }
164
+ };
165
+ ```
166
+
167
+ Updating the values in `maugli.config.ts` automatically refreshes the PWA manifest generated by Astro.
168
+
169
+ ### Testing
110
170
 
111
- ### Customization Options
171
+ Run the test suite to verify that example content is filtered correctly:
112
172
 
113
- - **Blog Name & Description** - Change `brand.name` and `brand.description`
114
- - **Language Settings** - Modify `defaultLang` and `features.enableMultiLang`
115
- - **Domain Configuration** - Update `brand.logoHref` for your main site link
116
- - **Example Content** - Set `showExamples: false` to hide demo content
117
- - **Theme & Features** - Enable/disable various blog features
173
+ ```bash
174
+ npm test
175
+ ```
176
+
177
+ All tests should complete without errors.
118
178
 
119
- Example files are marked with `isExample: true` in their frontmatter.
179
+ If you want to hide the example content included with this theme, set
180
+ `showExamples: false` in `src/config/maugli.config.ts`. Example files are
181
+ marked with `isExample: true` in their frontmatter.
120
182
 
121
- ### CLI Commands
183
+ To restore the default example posts and other sample content later, run:
122
184
 
123
- | Command | Description |
124
- | ----------------------------- | ---------------------------------------- |
125
- | `npx core-maugli init <name>` | Create a new blog with interactive setup |
126
- | `npx core-maugli version` | Show package version |
127
- | `npx core-maugli update` | Update config to latest version |
185
+ ```bash
186
+ npx core-maugli init .
187
+ ```
128
188
 
129
189
  ### Useful npm scripts
130
190
 
@@ -132,7 +192,7 @@ Example files are marked with `isExample: true` in their frontmatter.
132
192
  | -------------------------------- | ------------------------------------------- |
133
193
  | `npm run dev` | Start local dev server |
134
194
  | `npm start` | Alias for `npm run dev` |
135
- | `npm run build` | Format content then create production build |
195
+ | `npm run build` | Format content, verify assets, then create production build |
136
196
  | `npm run typograf` | Run typograf on all posts |
137
197
  | `npm run astro` | Access the Astro CLI |
138
198
  | `npm run featured:add <slug>` | Mark a post as featured |
@@ -141,11 +201,29 @@ Example files are marked with `isExample: true` in their frontmatter.
141
201
  | `npm run upgrade` | Manually update `maugli.config.ts` |
142
202
  | `npm run backup-update` | Backup key files then run `npm update` |
143
203
 
204
+ ## Checking installed version
205
+
206
+ See which version of the theme is installed:
207
+
208
+ ```bash
209
+ npm list core-maugli
210
+ ```
211
+
144
212
  ## Updating
145
213
 
146
- Running `npm update` will replace the theme's components and layouts with the latest versions. Content under `src/content/**`, your stylesheet `src/styles/global.css` and your `src/config/maugli.config.ts` file are kept. Commit any local changes before updating.
214
+ Upgrade to the latest release:
215
+
216
+ ```bash
217
+ npm update
218
+ ```
219
+
220
+ To back up key files and then update, run:
221
+
222
+ ```bash
223
+ npm run backup-update
224
+ ```
147
225
 
148
- Use `npm run backup-update` to copy these files to a timestamped `maugli-backup-*` directory before updating.
226
+ Both commands replace the theme's components and layouts with the latest versions. Content under `src/content/**`, your stylesheet `src/styles/global.css` and your `src/config/maugli.config.ts` file are kept. Commit any local changes before updating.
149
227
 
150
228
  ## Licensing
151
229
 
package/astro.config.mjs CHANGED
@@ -7,6 +7,7 @@ import { VitePWA } from 'vite-plugin-pwa';
7
7
  import siteConfig from './src/data/site-config';
8
8
  import remarkSlug from 'remark-slug';
9
9
  import customSlugify from './src/utils/remark-slugify';
10
+ import { maugliConfig } from './src/config/maugli.config';
10
11
 
11
12
  export const pwaOptions = {
12
13
  registerType: 'autoUpdate',
@@ -16,21 +17,21 @@ export const pwaOptions = {
16
17
  short_name: "Maugli",
17
18
  start_url: "/",
18
19
  display: "standalone",
19
- background_color: "#ffffff",
20
- theme_color: "#0cbf11",
21
- icons: [
20
+ background_color: maugliConfig.pwa?.backgroundColor ?? '#ffffff',
21
+ theme_color: maugliConfig.pwa?.themeColor ?? '#0cbf11',
22
+ icons: maugliConfig.pwa?.icons ?? [
22
23
  {
23
24
  src: "/icon-192.png",
24
25
  sizes: "192x192",
25
26
  type: "image/png",
26
- purpose: "any maskable"
27
+ purpose: "any maskable",
27
28
  },
28
29
  {
29
30
  src: "/icon-512.png",
30
31
  sizes: "512x512",
31
- type: "image/png"
32
- }
33
- ]
32
+ type: "image/png",
33
+ },
34
+ ],
34
35
  },
35
36
  workbox: {
36
37
  navigateFallback: '/index.html',
package/bin/index.js CHANGED
@@ -1,23 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  const [, , cmd, target] = process.argv;
3
3
 
4
- async function main() {
5
- if (cmd === 'init') {
6
- const mod = await import('./init.js');
7
- await mod.default(target);
8
- } else if (cmd === '--version' || cmd === '-v' || cmd === 'version') {
9
- await import('./version.js');
10
- } else if (cmd === 'update' || cmd === 'upgrade') {
11
- await import('../scripts/upgrade-config.js');
12
- } else {
13
- console.log('Usage:');
14
- console.log(' core-maugli init <project-name> Create a new blog');
15
- console.log(' core-maugli version Show version');
16
- console.log(' core-maugli update Update config to latest');
17
- console.log('');
18
- console.log('Example:');
19
- console.log(' npx core-maugli init my-blog');
20
- }
4
+ if (cmd === 'init') {
5
+ const mod = await import('./init.js');
6
+ await mod.default(target);
7
+ } else {
8
+ await import('../scripts/upgrade-config.js');
21
9
  }
22
-
23
- main().catch(console.error);
package/bin/init.js CHANGED
@@ -1,107 +1,66 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { execSync } from 'child_process';
4
- import { cpSync, existsSync, writeFileSync, readFileSync } from 'fs';
4
+ import { cpSync, existsSync, readFileSync, writeFileSync } from 'fs';
5
5
  import path from 'path';
6
+ import readline from 'readline';
6
7
  import { fileURLToPath } from 'url';
7
8
 
8
9
  const __filename = fileURLToPath(import.meta.url);
9
10
  const __dirname = path.dirname(__filename);
10
11
  const templateRoot = path.join(__dirname, '..');
11
12
 
12
- // Доступные языки интерфейса
13
- const availableLanguages = [
14
- { title: 'English', value: 'en' },
15
- { title: 'Русский', value: 'ru' },
16
- { title: 'Español', value: 'es' },
17
- { title: 'Deutsch', value: 'de' },
18
- { title: 'Português', value: 'pt' },
19
- { title: 'Français', value: 'fr' },
20
- { title: '中文', value: 'zh' },
21
- { title: '日本語', value: 'ja' }
22
- ];
23
-
24
- export default async function init(targetName) {
25
- console.log('🐯 Welcome to Maugli Blog Setup!\n');
26
-
27
- // Настройки по умолчанию
28
- let settings = {
29
- blogName: 'My Maugli Blog',
30
- language: 'en',
31
- mainDomain: '',
32
- enableMultiLang: false
33
- };
34
-
35
- // Попытка загрузить prompts для интерактивного режима
36
- try {
37
- const prompts = await import('prompts').then(m => m.default);
38
-
39
- // Интерактивные настройки
40
- const response = await prompts([
41
- {
42
- type: 'text',
43
- name: 'blogName',
44
- message: 'What would you like to name your blog?',
45
- initial: settings.blogName
46
- },
47
- {
48
- type: 'select',
49
- name: 'language',
50
- message: 'Choose interface language:',
51
- choices: availableLanguages,
52
- initial: 0 // English по умолчанию
53
- },
54
- {
55
- type: 'text',
56
- name: 'mainDomain',
57
- message: 'Do you have a main domain to link this blog to? (e.g., mybrand.com - leave empty if none):',
58
- initial: settings.mainDomain
59
- },
60
- {
61
- type: 'confirm',
62
- name: 'enableMultiLang',
63
- message: 'Enable multilingual support?',
64
- initial: settings.enableMultiLang
65
- }
66
- ]);
67
-
68
- // Если пользователь отменил настройку
69
- if (!response.blogName && response.blogName !== '') {
70
- console.log('Setup cancelled.');
71
- return;
72
- }
73
-
74
- settings = { ...settings, ...response };
75
- } catch (error) {
76
- console.log('⚠️ Interactive mode unavailable, using default settings...\n');
13
+ function getLanguageCodes() {
14
+ const file = readFileSync(path.join(templateRoot, 'src/i18n/languages.ts'), 'utf8');
15
+ const codes = [];
16
+ const regex = /{\s*code:\s*'([^']+)'/g;
17
+ let match;
18
+ while ((match = regex.exec(file)) !== null) {
19
+ codes.push(match[1]);
77
20
  }
21
+ return codes;
22
+ }
23
+
24
+ function promptLang(codes) {
25
+ return new Promise(resolve => {
26
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
27
+ rl.question(`Choose language (${codes.join(', ')}): `, answer => {
28
+ rl.close();
29
+ resolve(codes.includes(answer) ? answer : codes[0]);
30
+ });
31
+ });
32
+ }
78
33
 
79
- createBlog(targetName, settings);
34
+ function updateConfig(targetDir, lang) {
35
+ const configPath = path.join(targetDir, 'src', 'config', 'maugli.config.ts');
36
+ if (!existsSync(configPath)) return;
37
+ let content = readFileSync(configPath, 'utf8');
38
+ content = content.replace(/defaultLang:\s*'[^']*'/, `defaultLang: '${lang}'`);
39
+ const multiMatch = content.match(/enableMultiLang:\s*(true|false)/);
40
+ const multi = multiMatch ? multiMatch[1] === 'true' : false;
41
+ content = content.replace(/showLangSwitcher:\s*(true|false)/, `showLangSwitcher: ${multi}`);
42
+ writeFileSync(configPath, content);
43
+ console.log(`Configured default language to ${lang}`);
80
44
  }
81
45
 
82
- function createBlog(targetName, settings) {
46
+ export default async function init(targetName, langOption) {
83
47
  const targetDir = targetName ? path.resolve(targetName) : process.cwd();
84
-
85
- // Проверяем, создана ли папка
86
- if (targetName && !existsSync(targetDir)) {
87
- console.log(`\n📁 Creating folder: ${targetName}`);
88
- }
48
+ const codes = getLanguageCodes();
49
+ const lang = langOption && codes.includes(langOption) ? langOption : await promptLang(codes);
89
50
 
90
51
  function copyItem(item) {
91
52
  const src = path.join(templateRoot, item);
92
53
  const dest = path.join(targetDir, item);
93
54
 
94
55
  if (!existsSync(src)) {
95
- console.log(`⚠️ Skipped ${item} (not found)`);
56
+ console.log(`Skipped ${item} (not found)`);
96
57
  return;
97
58
  }
98
59
 
99
60
  cpSync(src, dest, { recursive: true });
100
- console.log(`✅ Copied ${item}`);
61
+ console.log(`Copied ${item}`);
101
62
  }
102
63
 
103
- console.log('\n🔧 Copying files...\n');
104
-
105
64
  // Copy package files first so npm install works correctly
106
65
  ['package.json', 'package-lock.json'].forEach(file => {
107
66
  if (existsSync(path.join(templateRoot, file))) {
@@ -123,9 +82,6 @@ function createBlog(targetName, settings) {
123
82
  ];
124
83
  items.forEach(copyItem);
125
84
 
126
- // Создание конфигурационных файлов
127
- console.log('\n⚙️ Creating configuration files...\n');
128
-
129
85
  // Create essential config files
130
86
  const gitignoreContent = `
131
87
  # Dependencies
@@ -160,78 +116,27 @@ dist/
160
116
  `;
161
117
 
162
118
  writeFileSync(path.join(targetDir, '.gitignore'), gitignoreContent.trim());
163
- console.log('Created .gitignore');
119
+ console.log('Created .gitignore');
164
120
 
165
121
  writeFileSync(path.join(targetDir, '.prettierrc'), prettierrcContent);
166
- console.log('Created .prettierrc');
167
-
168
- // Обновление maugli.config.ts с пользовательскими настройками
169
- console.log('\n🎨 Configuring blog settings...\n');
170
-
171
- const configPath = path.join(targetDir, 'src/config/maugli.config.ts');
172
- if (existsSync(configPath)) {
173
- let configContent = readFileSync(configPath, 'utf8');
174
-
175
- // Обновляем название блога
176
- configContent = configContent.replace(
177
- /name: 'Maugli'/,
178
- `name: '${settings.blogName}'`
179
- );
180
-
181
- // Обновляем язык по умолчанию
182
- configContent = configContent.replace(
183
- /defaultLang: 'en'/,
184
- `defaultLang: '${settings.language}'`
185
- );
186
-
187
- // Обновляем мультиязычность
188
- configContent = configContent.replace(
189
- /enableMultiLang: false/,
190
- `enableMultiLang: ${settings.enableMultiLang}`
191
- );
192
-
193
- // Обновляем домен (если указан)
194
- if (settings.mainDomain) {
195
- configContent = configContent.replace(
196
- /logoHref: 'https:\/\/maugli\.cfd'/,
197
- `logoHref: '${settings.mainDomain}'`
198
- );
199
- } else {
200
- // Если домена нет, ссылка ведет на главную страницу блога
201
- configContent = configContent.replace(
202
- /logoHref: 'https:\/\/maugli\.cfd'/,
203
- `logoHref: '/'`
204
- );
205
- }
206
-
207
- // Отключаем примеры для нового блога
208
- configContent = configContent.replace(
209
- /showExamples: true/,
210
- `showExamples: false`
211
- );
212
-
213
- writeFileSync(configPath, configContent);
214
- console.log('✅ Updated maugli.config.ts');
215
- }
122
+ console.log('Created .prettierrc');
216
123
 
217
- console.log('\n📦 Installing dependencies...\n');
218
124
  execSync('npm install', { cwd: targetDir, stdio: 'inherit' });
219
-
220
- console.log('\n🎉 Blog successfully created!\n');
221
- console.log('Settings:');
222
- console.log(` 📝 Name: ${settings.blogName}`);
223
- console.log(` 🌐 Language: ${availableLanguages.find(l => l.value === settings.language)?.title || settings.language}`);
224
- console.log(` 🔗 Domain: ${settings.mainDomain || 'local blog'}`);
225
- console.log(` 🌍 Multilingual: ${settings.enableMultiLang ? 'enabled' : 'disabled'}`);
226
- console.log('\nTo start:');
227
- if (targetName) {
228
- console.log(` cd ${targetName}`);
229
- }
230
- console.log(' npm run dev\n');
231
- console.log('📚 All settings can be changed in src/config/maugli.config.ts');
125
+ updateConfig(targetDir, lang);
232
126
  }
233
127
 
234
128
  // Если скрипт запускается напрямую
235
129
  if (import.meta.url === `file://${process.argv[1]}`) {
236
- init(process.argv[2]);
130
+ const args = process.argv.slice(2);
131
+ let targetName;
132
+ let lang;
133
+ for (let i = 0; i < args.length; i++) {
134
+ if (args[i] === '--lang' && i + 1 < args.length) {
135
+ lang = args[i + 1];
136
+ i++;
137
+ } else {
138
+ targetName = args[i];
139
+ }
140
+ }
141
+ await init(targetName, lang);
237
142
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "core-maugli",
3
3
  "description": "Astro & Tailwind CSS blog theme for Maugli.",
4
4
  "type": "module",
5
- "version": "1.1.4",
5
+ "version": "1.1.6",
6
6
  "license": "GPL-3.0-or-later OR Commercial",
7
7
  "repository": {
8
8
  "type": "git",
@@ -22,7 +22,7 @@
22
22
  "dev": "astro dev",
23
23
  "start": "astro dev",
24
24
  "build": "node typograf-batch.js && node scripts/verify-assets.js && astro build",
25
- "test": "node tests/examplesFilter.demo.mjs",
25
+ "test": "node tests/examplesFilter.test.ts",
26
26
  "astro": "astro",
27
27
  "featured:add": "node scripts/featured.js add",
28
28
  "featured:remove": "node scripts/featured.js remove",
@@ -32,25 +32,24 @@
32
32
  "postinstall": "node scripts/upgrade-config.js"
33
33
  },
34
34
  "dependencies": {
35
- "@astrojs/check": "^0.9.3",
36
- "@astrojs/mdx": "^3.1.7",
37
- "@astrojs/rss": "^4.0.7",
38
- "@astrojs/sitemap": "^3.1.6",
39
- "@astrojs/tailwind": "^5.1.0",
40
- "@fontsource-variable/inter": "^5.1.0",
41
- "@fontsource-variable/geologica": "^5.1.0",
42
- "@tailwindcss/typography": "^0.5.15",
43
- "astro": "^4.15.4",
44
- "clsx": "^2.1.1",
45
- "fuse.js": "^7.0.0",
46
- "marked": "^12.0.2",
47
- "prompts": "^2.4.2",
48
- "reading-time": "^1.5.0",
35
+ "@astrojs/mdx": "^4.3.0",
36
+ "@astrojs/rss": "^4.0.11",
37
+ "@astrojs/sitemap": "^3.4.0",
38
+ "@fontsource-variable/geologica": "^5.2.6",
39
+ "@fontsource-variable/inter": "^5.2.5",
40
+ "@fontsource-variable/newsreader": "^5.2.6",
41
+ "@tailwindcss/vite": "^4.0.17",
42
+ "astro": "^5.5.6",
43
+ "i18next": "^25.3.2",
44
+ "js-yaml": "^4.1.0",
45
+ "marked": "^15.0.7",
49
46
  "remark-slug": "^7.0.1",
50
- "slugify": "^1.6.6",
51
- "tailwindcss": "^3.4.10",
52
- "typograf": "^7.4.4",
53
- "typescript": "^5.5.4"
47
+ "sharp": "^0.34.2",
48
+ "tailwindcss": "^4.0.17",
49
+ "ts-node": "^10.9.2",
50
+ "tsx": "^4.20.3",
51
+ "typescript": "^5.9.2",
52
+ "typograf": "^7.4.4"
54
53
  },
55
54
  "devDependencies": {
56
55
  "@tailwindcss/typography": "^0.5.16",
@@ -49,6 +49,12 @@ export interface MaugliConfig {
49
49
  enableFAQ: boolean; // Enable FAQ block
50
50
  enableRSS: boolean; // Enable RSS feed
51
51
  };
52
+ // Progressive Web App settings
53
+ pwa?: {
54
+ themeColor?: string; // Theme color for the PWA manifest
55
+ backgroundColor?: string; // Background color for the PWA manifest
56
+ icons?: Array<{ src: string; sizes: string; type: string; purpose?: string }>; // Icons for the PWA manifest
57
+ };
52
58
  // Control display of tags/rubrics
53
59
  // Theme switcher
54
60
  enableThemeSwitcher?: boolean; // Enable theme switcher (true by default)
@@ -157,6 +163,14 @@ export const maugliConfig: MaugliConfig = {
157
163
  enableFAQ: true, // Enable FAQ block
158
164
  enableRSS: true, // Enable RSS feed
159
165
  },
166
+ pwa: {
167
+ themeColor: '#0cbf11', // Theme color for the PWA manifest
168
+ backgroundColor: '#ffffff', // Background color for the PWA manifest
169
+ icons: [
170
+ { src: '/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any maskable' },
171
+ { src: '/icon-512.png', sizes: '512x512', type: 'image/png' },
172
+ ],
173
+ },
160
174
  showOnlyRubricsTags: true, // Show only rubrics by default
161
175
 
162
176
  links: {
@@ -195,7 +209,7 @@ export const maugliConfig: MaugliConfig = {
195
209
  defaultAuthorId: 'default-autor', // Default author id (used if no author is specified). Use the filename of the author .md file without the .md extension
196
210
  showAuthorsWithoutArticles: true, // Show authors without articles (default: true)
197
211
  showAuthorArticleCount: true, // Show article count for author
198
- showLangSwitcher: true, // Show language switcher
212
+ showLangSwitcher: false, // Show language switcher
199
213
  langLinks: {
200
214
  ru: 'https://maugli.cfd/ru', // Russian version
201
215
  en: 'https://maugli.cfd/en', // English version
@@ -0,0 +1,40 @@
1
+ ---
2
+ title: О блоге
3
+ seo:
4
+ title: ТехРев — блог, который самостоятельно ведет AI-автор
5
+ description: Демо-витрина автоматического AI-блога с персоной
6
+ image:
7
+ src: '/tr-about.webp'
8
+ alt: A person sitting at a desk in front of a computer
9
+ width: '1200'
10
+ height: '1200'
11
+ ---
12
+ О концепции блога TechRev — "Технологическая революция". Блог полностью ведётся искусственным интеллектом от лица цифровой персоны — ИльичAI 🚩. Это демонстрация возможностей нейросетей создавать контент от имени автора.
13
+
14
+ ИльичAI — вождь новой эпохи. Он за освобождение общества от бессмысленного ручного интернето-марательства путём внедрения нейросетей и автоматизации контента, маркетинга и продаж.
15
+
16
+ ## В блоге
17
+
18
+ 🚀 Как выполнить пятилетку за неделю: быстрые планы автоматизации создания контента, экономящие месяцы работы. #ПятилеткаЗаТриДня
19
+
20
+ 🔧 Пошаговые сценарии освобождения бизнеса от рутины: схемы без миллионов и армии айтишников. #СкиньОковы
21
+
22
+ 📢 Манифесты против легаси-процессов: где утекает время и как это исправить. #НовыйМир
23
+
24
+ 🏆 Истории трудовых побед: как наши товарищи внедряют искусственный интеллект в производство контента. #ТоварищиВнедряют
25
+
26
+ 🚩 Технологии — наш серп ⚙️. Автоматизация — наш молот 🛠. Нейросети — наше знамя 🤖.
27
+
28
+ ## Почему автором выбран Ильич?
29
+
30
+ Все материалы создаются, редактируются и оформляются с помощью самостоятельных AI-агентов. Процесс полностью автоматизирован. Это ли не контентная революция?
31
+
32
+ Выбор Ильича как цифрового вождя этой витрины не случаен. Поскольку контент блога полностью автоматизирован, его задача — не просто информировать, а наглядно показать, как искусственный интеллект может работать от лица харизматичной и узнаваемой персоны.
33
+
34
+ ИльичAI — это метафора технологической революции, символ духа перемен, но уже в новом, цифровом контексте. Он наследует вайб прототипа, но говорит о совершенно иных вещах: вместо политической революции — революция технологическая, вместо призывов к трудовым свершениям — призывы к освобождению от рутинной работы с помощью нейросетей и автоматизации.
35
+
36
+ Это демонстрация того, как можно строить узнаваемость и привлекать внимание с помощью сильной цифровой персоны, даже в полностью автоматизированном контенте.
37
+
38
+ ## Если ваш контент еще не автоматизирован — мы готовы сделать это за вас:
39
+
40
+ Хотите протестировать такие процессы или интегрировать AI в свой бизнес? По вопросам сотрудничества:  [Связаться в Telegram](https://t.me/darrrina)
@@ -0,0 +1,10 @@
1
+ ---
2
+ title: Для связи
3
+ seo:
4
+ title: Контакты
5
+ description: Создаем автоматические AI-блоги и телеграм-каналы любой тематики для брендов, экспертов, СЕО
6
+ ---
7
+
8
+ Maugli -- контент-фермы с гибкой настройкой продуктов (целевая ссылка), каналов, авторов, тематики и тональности. Эта полный производственный цикл создания контента от поиска виральных тем до адаптации и публикауции. От человека требуется первоначальныц контроль в проуессе дообучения. Все остальное делают агенты.
9
+
10
+ [Связаться в Telegram](https://t.me/darrrina)
@@ -1,3 +1,4 @@
1
+ /* Import fonts. Replace or add lines to use other Fontsource packages. */
1
2
  @import '@fontsource-variable/inter/wght.css' layer(base);
2
3
  @import '@fontsource-variable/geologica/wght.css' layer(base);
3
4
 
@@ -23,8 +24,8 @@
23
24
  --bg-main-40: rgba(255, 255, 255, 0.4);
24
25
  --bg-muted: rgba(237, 241, 247, 0.621);
25
26
  --border-main: rgba(17, 28, 44, 0.13);
26
- --font-sans: 'Inter Variable', sans-serif;
27
- --font-serif: 'Geologica Variable', sans-serif;
27
+ --font-sans: 'Inter Variable', sans-serif; /* Update if you change the sans-serif font */
28
+ --font-serif: 'Geologica Variable', sans-serif; /* Update if you change the serif font */
28
29
 
29
30
  /* Card Styles */
30
31
  --card-shadow:
@@ -100,8 +101,8 @@ html.dark {
100
101
  */
101
102
 
102
103
  @theme inline {
103
- --font-sans: 'Inter Variable', sans-serif;
104
- --font-serif: 'Geologica Variable', sans-serif;
104
+ --font-sans: 'Inter Variable', sans-serif; /* Match --font-sans above if changed */
105
+ --font-serif: 'Geologica Variable', sans-serif; /* Match --font-serif above if changed */
105
106
  --font-weight-bold: 700;
106
107
  --font-weight-extra-bold: 800;
107
108
  --text-color-main: var(--text-main);
package/bin/version.js DELETED
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { readFileSync } from 'fs';
4
- import path from 'path';
5
- import { fileURLToPath } from 'url';
6
-
7
- const __filename = fileURLToPath(import.meta.url);
8
- const __dirname = path.dirname(__filename);
9
-
10
- const packagePath = path.join(__dirname, '../package.json');
11
- const packageJson = JSON.parse(readFileSync(packagePath, 'utf8'));
12
-
13
- console.log(`core-maugli v${packageJson.version}`);
14
- console.log(`Astro & Tailwind CSS blog theme for Maugli`);
15
- console.log(`Repository: ${packageJson.repository.url}`);