Skip to content

Commit f0ffffe

Browse files
committed
Merge branch 'develop'
2 parents 0b08625 + 1eaca05 commit f0ffffe

9 files changed

Lines changed: 125 additions & 21 deletions

File tree

apps/backend/.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ JWT_REFRESH_SECRET=
88
JWT_REFRESH_EXPIRES_IN=7d
99

1010
# Redis
11+
REDIS_URL=
1112
REDIS_HOST=
1213
REDIS_PORT=6379
1314

apps/backend/package-lock.json

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/backend/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"@nestjs/passport": "^11.0.5",
3030
"@nestjs/platform-express": "^11.0.1",
3131
"@nestjs/platform-socket.io": "^11.1.26",
32+
"@nestjs/throttler": "^6.5.0",
3233
"@nestjs/websockets": "^11.1.26",
3334
"@prisma/adapter-pg": "^7.8.0",
3435
"@prisma/client": "^7.8.0",
@@ -38,6 +39,7 @@
3839
"class-transformer": "^0.5.1",
3940
"class-validator": "^0.15.1",
4041
"dotenv": "^17.4.2",
42+
"helmet": "^8.2.0",
4143
"ioredis": "^5.11.1",
4244
"passport": "^0.7.0",
4345
"passport-jwt": "^4.0.1",

apps/backend/prisma/schema.prisma

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ model Workspace {
3030
userId String
3131
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
3232
projects Project[]
33+
34+
@@index([userId])
3335
}
3436

3537
model Project {
@@ -46,6 +48,8 @@ model Project {
4648
notes Note[]
4749
repoEmbeddings RepoEmbedding[]
4850
conversations Conversation[]
51+
52+
@@index([workspaceId])
4953
}
5054

5155
model Note {
@@ -64,6 +68,8 @@ model Note {
6468
embeddings NoteEmbedding[]
6569
6670
@@index([searchVector], type: Gin)
71+
@@index([userId])
72+
@@index([projectId])
6773
}
6874

6975
model NoteEmbedding {
@@ -94,6 +100,9 @@ model Conversation {
94100
projectId String?
95101
project Project? @relation(fields: [projectId], references: [id], onDelete: SetNull)
96102
messages Message[]
103+
104+
@@index([userId])
105+
@@index([projectId])
97106
}
98107

99108
model Message {
@@ -103,6 +112,8 @@ model Message {
103112
createdAt DateTime @default(now())
104113
conversationId String
105114
conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
115+
116+
@@index([conversationId])
106117
}
107118

108119
model RepoEmbedding {
@@ -112,6 +123,8 @@ model RepoEmbedding {
112123
embedding Unsupported("vector(768)")?
113124
projectId String
114125
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
126+
127+
@@index([projectId])
115128
}
116129

117130
model Notification {
@@ -123,4 +136,6 @@ model Notification {
123136
createdAt DateTime @default(now())
124137
userId String
125138
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
139+
140+
@@index([userId])
126141
}

apps/backend/src/app.module.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { Module } from '@nestjs/common';
22
import { ConfigModule } from '@nestjs/config';
33
import { BullModule } from '@nestjs/bullmq';
4+
import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
5+
import { APP_GUARD } from '@nestjs/core';
6+
import Redis from 'ioredis';
47
import { AppController } from './app.controller';
58
import { AppService } from './app.service';
69
import { PrismaModule } from './prisma/prisma.module';
@@ -18,11 +21,19 @@ import { NotificationsModule } from './notifications/notifications.module';
1821
imports: [
1922
ConfigModule.forRoot({ isGlobal: true }),
2023
BullModule.forRoot({
21-
connection: {
22-
host: process.env.REDIS_HOST || 'localhost',
23-
port: parseInt(process.env.REDIS_PORT || '6379'),
24-
},
24+
connection: process.env.REDIS_URL
25+
? new Redis(process.env.REDIS_URL, { maxRetriesPerRequest: null })
26+
: {
27+
host: process.env.REDIS_HOST || 'localhost',
28+
port: parseInt(process.env.REDIS_PORT || '6379'),
29+
},
2530
}),
31+
ThrottlerModule.forRoot([
32+
{
33+
ttl: 60000,
34+
limit: 100, // 100 requests per minute
35+
},
36+
]),
2637
PrismaModule,
2738
RedisModule,
2839
AuthModule,
@@ -34,6 +45,12 @@ import { NotificationsModule } from './notifications/notifications.module';
3445
NotificationsModule,
3546
],
3647
controllers: [AppController],
37-
providers: [AppService],
48+
providers: [
49+
AppService,
50+
{
51+
provide: APP_GUARD,
52+
useClass: ThrottlerGuard,
53+
},
54+
],
3855
})
3956
export class AppModule {}

apps/backend/src/main.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { NestFactory } from '@nestjs/core';
22
import { AppModule } from './app.module';
33
import { ValidationPipe } from '@nestjs/common';
4+
import helmet from 'helmet';
45

56
async function bootstrap() {
67
const app = await NestFactory.create(AppModule);
@@ -12,7 +13,16 @@ async function bootstrap() {
1213
}),
1314
);
1415

15-
app.enableCors();
16+
app.use(helmet());
17+
18+
app.enableCors({
19+
origin: [
20+
'http://localhost:3000',
21+
'http://10.0.2.2:3000',
22+
'https://devflowai.vercel.app',
23+
],
24+
credentials: true,
25+
});
1626

1727
await app.listen(process.env.PORT ?? 3001);
1828
console.log(

apps/backend/src/redis/redis.service.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@ export class RedisService implements OnModuleDestroy {
77
private client: Redis;
88

99
constructor(private config: ConfigService) {
10-
this.client = new Redis({
11-
host: this.config.get('REDIS_HOST'),
12-
port: this.config.get<number>('REDIS_PORT'),
13-
});
10+
const url = this.config.get<string>('REDIS_URL');
11+
if (url) {
12+
this.client = new Redis(url);
13+
} else {
14+
this.client = new Redis({
15+
host: this.config.get<string>('REDIS_HOST') || 'localhost',
16+
port: this.config.get<number>('REDIS_PORT') || 6379,
17+
});
18+
}
1419
}
1520

1621
async set(key: string, value: string, ttlSeconds?: number): Promise<void> {

apps/web/next.config.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,35 @@ const nextConfig: NextConfig = {
44
turbopack: {
55
root: __dirname,
66
},
7+
async headers() {
8+
return [
9+
{
10+
source: '/(.*)',
11+
headers: [
12+
{
13+
key: 'X-DNS-Prefetch-Control',
14+
value: 'on'
15+
},
16+
{
17+
key: 'Strict-Transport-Security',
18+
value: 'max-age=63072000; includeSubDomains; preload'
19+
},
20+
{
21+
key: 'X-Frame-Options',
22+
value: 'SAMEORIGIN'
23+
},
24+
{
25+
key: 'X-Content-Type-Options',
26+
value: 'nosniff'
27+
},
28+
{
29+
key: 'Referrer-Policy',
30+
value: 'strict-origin-when-cross-origin'
31+
}
32+
]
33+
}
34+
];
35+
},
736
};
837

938
export default nextConfig;

devflow-ai-docs.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3808,16 +3808,16 @@ MIT
38083808

38093809
| Day | Focus | Tasks |
38103810
|-----|-------|-------|
3811-
| 81 | Neon DB setup | Create database, run migrations |
3812-
| 82 | Railway backend | Deploy Docker container |
3813-
| 83 | Vercel frontend | Connect repo, configure env vars |
3814-
| 84 | Upstash Redis | Set up, connect to backend |
3815-
| 85 | Ollama (Oracle VM) | Set up Oracle free VM, deploy Ollama |
3816-
| 86 | CI/CD pipeline | GitHub Actions deploy on main push |
3817-
| 87 | Production testing | Test all features on live URLs |
3818-
| 88 | Screenshots + demo | Record Loom video, capture screenshots |
3819-
| 89 | README complete | Full README, architecture diagram |
3820-
| 90 | Portfolio launch | Update portfolio, LinkedIn post, GitHub public |
3811+
| 81 | Neon DB setup | Create free DB, enable pgvector, run migrations |
3812+
| 82 | Upstash Redis | Set up serverless free tier Redis |
3813+
| 83 | Oracle Cloud VM | Set up Always Free ARM VM, install Docker & Ollama |
3814+
| 84 | Render backend | Deploy NestJS API on Render Web Service (Free) |
3815+
| 85 | Vercel frontend | Deploy Next.js app on Vercel Hobby tier |
3816+
| 86 | Mobile config | Set production endpoints for React Native |
3817+
| 87 | Production testing | End-to-End testing on live URLs |
3818+
| 88 | CI/CD pipeline | GitHub Actions automated deploys |
3819+
| 89 | Architecture assets| Generate architecture diagrams, finalize README |
3820+
| 90 | Portfolio launch | Record Loom, LinkedIn post, make public |
38213821

38223822
---
38233823

@@ -3832,7 +3832,7 @@ MIT
38323832
| AI Chat working | Day 50 | Streaming chat E2E |
38333833
| AI Tools + RAG | Day 60 | All AI features |
38343834
| GitHub + Notifications | Day 70 | GitHub integration |
3835-
| Mobile complete | Day 77 | Flutter app functional |
3835+
| Mobile complete | Day 77 | React Native app functional |
38363836
| Tests + Polish | Day 80 | 70% test coverage |
38373837
| **Live in production** | Day 87 | Public URL working |
38383838
| **Portfolio ready** | Day 90 | Open sourced, showcased |

0 commit comments

Comments
 (0)