Skip to content

Commit a1047c1

Browse files
committed
docs: improve documentation for ai-blog setup
1 parent 6f7bfb7 commit a1047c1

File tree

1 file changed

+54
-28
lines changed
  • adminforth/documentation/blog/2024-10-01-ai-blog

1 file changed

+54
-28
lines changed

adminforth/documentation/blog/2024-10-01-ai-blog/index.md

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ npx adminforth create-app --app-name ai-blog
4646
Add modules:
4747

4848
```bash
49+
cd ai-blog
4950
npm i @adminforth/upload @adminforth/rich-editor @adminforth/text-complete
5051
```
5152

@@ -169,7 +170,7 @@ model Post {
169170
//diff-add
170171
published Boolean
171172
//diff-add
172-
author User? @relation(fields: [authorId], references: [id])
173+
author adminuser? @relation(fields: [authorId], references: [id])
173174
//diff-add
174175
authorId String?
175176
//diff-add
@@ -211,7 +212,7 @@ Open `index.ts` file in root directory and update it with the following content:
211212
```ts title="./index.ts"
212213
import express from 'express';
213214
import AdminForth, { Filters, Sorts } from 'adminforth';
214-
import userResource from './resources/user.js';
215+
import userResource from './resources/adminuser.js';
215216
import postResource from './resources/posts.js';
216217
import contentImageResource from './resources/content-image.js';
217218
import httpProxy from 'http-proxy';
@@ -231,7 +232,7 @@ export const admin = new AdminForth({
231232
auth: {
232233
usersResourceId: 'adminuser', // resource to get user during login
233234
usernameField: 'email', // field where username is stored, should exist in resource
234-
passwordHashField: 'passwordHash',
235+
passwordHashField: 'password_hash',
235236
},
236237
customization: {
237238
brandName: 'My Admin',
@@ -289,7 +290,9 @@ if (import.meta.url === `file://${process.argv[1]}`) {
289290

290291
// api to server recent posts
291292
app.get('/api/posts', async (req, res) => {
292-
const { offset = 0, limit = 100, slug = null } = req.query;
293+
const offset = parseInt(req.query.offset as string) || 0;
294+
const limit = parseInt(req.query.limit as string) || 100;
295+
const slug = req.query.slug as string | null;
293296
const posts = await admin.resource('post').list(
294297
[Filters.EQ('published', true), ...(slug ? [Filters.LIKE('slug', slug)] : [])],
295298
limit,
@@ -331,13 +334,13 @@ if (import.meta.url === `file://${process.argv[1]}`) {
331334
if (!await admin.resource('adminuser').get([Filters.EQ('email', '[email protected]')])) {
332335
await admin.resource('adminuser').create({
333336
334-
passwordHash: await AdminForth.Utils.generatePasswordHash('adminforth'),
337+
password_hash: await AdminForth.Utils.generatePasswordHash('adminforth'),
335338
});
336339
}
337340
});
338341

339342
admin.express.listen(port, () => {
340-
console.log(`\n⚡ AdminForth is available at http://localhost:${port}\n`)
343+
console.log(`\n⚡ AdminForth is available at http://localhost:${port}/admin\n`)
341344
});
342345
}
343346
```
@@ -377,7 +380,14 @@ export default {
377380
type: AdminForthDataTypes.STRING,
378381
},
379382
{
380-
name: 'createdAt',
383+
name: 'role',
384+
enum: [
385+
{ value: 'superadmin', label: 'Super Admin' },
386+
{ value: 'user', label: 'User' },
387+
]
388+
},
389+
{
390+
name: 'created_at',
381391
type: AdminForthDataTypes.DATETIME,
382392
showIn: {
383393
edit: false,
@@ -403,9 +413,9 @@ export default {
403413
AdminForth.Utils.PASSWORD_VALIDATORS.UP_LOW_NUM,
404414
],
405415
},
406-
{ name: 'passwordHash', backendOnly: true, showIn: { all: false } },
416+
{ name: 'password_hash', backendOnly: true, showIn: { all: false } },
407417
{
408-
name: 'publicName',
418+
name: 'public_name',
409419
type: AdminForthDataTypes.STRING,
410420
},
411421
{ name: 'avatar' },
@@ -425,7 +435,7 @@ export default {
425435
return { ok: true }
426436
},
427437
},
428-
}
438+
},
429439
plugins: [
430440
new UploadPlugin({
431441
pathColumnName: 'avatar',
@@ -462,6 +472,8 @@ import UploadPlugin from '@adminforth/upload';
462472
import RichEditorPlugin from '@adminforth/rich-editor';
463473
import ChatGptPlugin from '@adminforth/chat-gpt';
464474
import slugify from 'slugify';
475+
import CompletionAdapterOpenAIChatGPT from "@adminforth/completion-adapter-open-ai-chat-gpt";
476+
import ImageGenerationAdapterOpenAI from '@adminforth/image-generation-adapter-openai';
465477

466478
export default {
467479
table: 'post',
@@ -561,23 +573,23 @@ export default {
561573
{ originalFilename, originalExtension }: {originalFilename: string, originalExtension: string }
562574
) => `post-previews/${new Date().getFullYear()}/${randomUUID()}/${originalFilename}.${originalExtension}`,
563575
generation: {
564-
provider: 'openai',
565576
countToGenerate: 2,
566-
openAiOptions: {
567-
model: 'gpt-4o',
568-
apiKey: process.env.OPENAI_API_KEY,
569-
},
570-
fieldsForContext: ['title'],
577+
adapter: new ImageGenerationAdapterOpenAI({
578+
openAiApiKey: process.env.OPENAI_API_KEY as string,
579+
model: 'gpt-image-1',
580+
}),
571581
},
572582
}),
573583
new RichEditorPlugin({
574584
htmlFieldName: 'content',
575585
completion: {
576-
provider: 'openai-chat-gpt',
577-
params: {
578-
apiKey: process.env.OPENAI_API_KEY,
586+
adapter: new CompletionAdapterOpenAIChatGPT({
587+
openAiApiKey: process.env.OPENAI_API_KEY as string,
579588
model: 'gpt-4o',
580-
},
589+
expert: {
590+
temperature: 0.7
591+
}
592+
}),
581593
expert: {
582594
debounceTime: 250,
583595
}
@@ -618,11 +630,19 @@ export default {
618630
{
619631
name: 'id',
620632
primaryKey: true,
633+
showIn: {
634+
edit: false,
635+
create: false,
636+
},
621637
fillOnCreate: () => randomUUID(),
622638
},
623639
{
624640
name: 'createdAt',
625641
type: AdminForthDataTypes.DATETIME,
642+
showIn: {
643+
edit: false,
644+
create: false,
645+
},
626646
fillOnCreate: () => (new Date()).toISOString(),
627647
},
628648
{
@@ -951,7 +971,7 @@ Open `Dockerfile` in root project directory (`ai-blog`) and put in the following
951971
FROM node:20-slim
952972
EXPOSE 3500
953973
WORKDIR /app
954-
RUN apk add --no-cache supervisor
974+
RUN apt-get update && apt-get install -y supervisor
955975
COPY package.json package-lock.json ./
956976
RUN npm ci
957977
COPY seo/package.json seo/package-lock.json seo/
@@ -972,6 +992,8 @@ autostart=true
972992
autorestart=true
973993
stdout_logfile=/dev/stdout
974994
stderr_logfile=/dev/stderr
995+
stdout_logfile_maxbytes = 0
996+
stderr_logfile_maxbytes = 0
975997

976998
[program:seo]
977999
command=sh -c "cd seo && node .output/server/index.mjs"
@@ -980,13 +1002,17 @@ autostart=true
9801002
autorestart=true
9811003
stdout_logfile=/dev/stdout
9821004
stderr_logfile=/dev/stderr
1005+
stdout_logfile_maxbytes = 0
1006+
stderr_logfile_maxbytes = 0
9831007

9841008
[program:prisma]
9851009
command=npm run migrate:prod
9861010
directory=/app
9871011
autostart=true
9881012
stdout_logfile=/dev/stdout
9891013
stderr_logfile=/dev/stderr
1014+
stdout_logfile_maxbytes = 0
1015+
stderr_logfile_maxbytes = 0
9901016

9911017
EOF
9921018

@@ -1011,8 +1037,8 @@ terraform*
10111037
Build and run your docker container locally:
10121038

10131039
```bash
1014-
sudo docker build -t my-ai-blog .
1015-
sudo docker run -p80:3500 -v ./prodDb:/app/db --env-file .env -it --name my-ai-blog -d my-ai-blog
1040+
docker build -t my-ai-blog .
1041+
docker run -p80:3500 -v ./prodDb:/app/db --env-file .env -it --name my-ai-blog -d my-ai-blog
10161042
```
10171043

10181044
Now you can open `http://localhost` in your browser and see your blog.
@@ -1088,7 +1114,7 @@ data "aws_subnet" "default_subnet" {
10881114
}
10891115
10901116
resource "aws_security_group" "instance_sg" {
1091-
name = "my-ai-blog-instance-sg"
1117+
name = "my-aiblog-instance-sg"
10921118
vpc_id = data.aws_vpc.default.id
10931119
10941120
ingress {
@@ -1118,14 +1144,14 @@ resource "aws_security_group" "instance_sg" {
11181144
}
11191145
11201146
resource "aws_key_pair" "deployer" {
1121-
key_name = "terraform-deployer-key"
1147+
key_name = "terraform-deployer-my-aiblog-key"
11221148
public_key = file("~/.ssh/id_rsa.pub") # Path to your public SSH key
11231149
}
11241150
11251151
11261152
resource "aws_instance" "docker_instance" {
11271153
ami = data.aws_ami.amazon_linux.id
1128-
instance_type = "t3a.micro"
1154+
instance_type = "t3a.small"
11291155
subnet_id = data.aws_subnet.default_subnet.id
11301156
vpc_security_group_ids = [aws_security_group.instance_sg.id]
11311157
key_name = aws_key_pair.deployer.key_name
@@ -1164,13 +1190,13 @@ resource "null_resource" "wait_for_user_data" {
11641190
11651191
connection {
11661192
type = "ssh"
1167-
user = "ubuntu"
1193+
user = "ec2-user"
11681194
private_key = file("~/.ssh/id_rsa")
11691195
host = aws_instance.docker_instance.public_ip
11701196
}
11711197
}
11721198
1173-
depends_on = [aws_instance.app_instance]
1199+
depends_on = [aws_instance.docker_instance]
11741200
}
11751201
11761202

0 commit comments

Comments
 (0)