Skip to content

Commit 1a3e483

Browse files
Init
1 parent d32b185 commit 1a3e483

36 files changed

+7539
-1
lines changed

.github/workflows/ai.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Build & Push AI
2+
3+
on:
4+
push:
5+
branches:
6+
- "**"
7+
paths:
8+
- "ai/**"
9+
- ".github/workflows/ai.yml"
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: read
14+
packages: write
15+
16+
jobs:
17+
build-and-push-ai:
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
- uses: actions/checkout@v4
22+
- uses: docker/setup-buildx-action@v3
23+
- uses: docker/login-action@v3
24+
with:
25+
registry: ghcr.io
26+
username: ${{ github.actor }}
27+
password: ${{ secrets.GITHUB_TOKEN }}
28+
29+
- name: Determine tags
30+
id: tags
31+
run: |
32+
REPO_LOWER="${GITHUB_REPOSITORY,,}"
33+
BRANCH_LOWER="${GITHUB_REF_NAME,,}"
34+
35+
if [ "$BRANCH_LOWER" = "main" ]; then
36+
echo "TAGS=ghcr.io/$REPO_LOWER/ai:latest,ghcr.io/$REPO_LOWER/ai:$GITHUB_SHA" >> $GITHUB_OUTPUT
37+
else
38+
echo "TAGS=ghcr.io/$REPO_LOWER/ai:$BRANCH_LOWER,ghcr.io/$REPO_LOWER/ai:$GITHUB_SHA" >> $GITHUB_OUTPUT
39+
fi
40+
41+
- uses: docker/build-push-action@v5
42+
with:
43+
context: ./ai
44+
file: ./ai/Dockerfile
45+
push: true
46+
tags: ${{ steps.tags.outputs.TAGS }}
47+
cache-from: type=registry,ref=ghcr.io/${{ github.repository }}/ai:latest
48+
cache-to: type=inline

.github/workflows/api.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Build & Push API
2+
3+
on:
4+
push:
5+
branches:
6+
- "**"
7+
paths:
8+
- "api/**"
9+
- ".github/workflows/api.yml"
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: read
14+
packages: write
15+
16+
jobs:
17+
build-and-push-api:
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
- uses: actions/checkout@v4
22+
- uses: docker/setup-buildx-action@v3
23+
- uses: docker/login-action@v3
24+
with:
25+
registry: ghcr.io
26+
username: ${{ github.actor }}
27+
password: ${{ secrets.GITHUB_TOKEN }}
28+
29+
- name: Determine tags
30+
id: tags
31+
run: |
32+
REPO_LOWER="${GITHUB_REPOSITORY,,}"
33+
BRANCH_LOWER="${GITHUB_REF_NAME,,}"
34+
35+
if [ "$BRANCH_LOWER" = "main" ]; then
36+
echo "TAGS=ghcr.io/$REPO_LOWER/api:latest,ghcr.io/$REPO_LOWER/api:$GITHUB_SHA" >> $GITHUB_OUTPUT
37+
else
38+
echo "TAGS=ghcr.io/$REPO_LOWER/api:$BRANCH_LOWER,ghcr.io/$REPO_LOWER/api:$GITHUB_SHA" >> $GITHUB_OUTPUT
39+
fi
40+
41+
- uses: docker/build-push-action@v5
42+
with:
43+
context: ./api
44+
file: ./api/Dockerfile
45+
push: true
46+
tags: ${{ steps.tags.outputs.TAGS }}
47+
cache-from: type=registry,ref=ghcr.io/${{ github.repository }}/api:latest
48+
cache-to: type=inline

.github/workflows/app.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Build & Push App
2+
3+
on:
4+
push:
5+
branches:
6+
- "**"
7+
paths:
8+
- "app/**"
9+
- ".github/workflows/app.yml"
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: read
14+
packages: write
15+
16+
jobs:
17+
build-and-push-app:
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@v4
23+
24+
- name: Set up Docker Buildx
25+
uses: docker/setup-buildx-action@v3
26+
27+
- name: Log in to GHCR
28+
uses: docker/login-action@v3
29+
with:
30+
registry: ghcr.io
31+
username: ${{ github.actor }}
32+
password: ${{ secrets.GITHUB_TOKEN }}
33+
34+
- name: Determine tags
35+
id: tags
36+
run: |
37+
REPO_LOWER="${GITHUB_REPOSITORY,,}"
38+
BRANCH_LOWER="${GITHUB_REF_NAME,,}"
39+
40+
if [ "$BRANCH_LOWER" = "main" ]; then
41+
echo "TAGS=ghcr.io/$REPO_LOWER/app:latest,ghcr.io/$REPO_LOWER/app:$GITHUB_SHA" >> $GITHUB_OUTPUT
42+
else
43+
echo "TAGS=ghcr.io/$REPO_LOWER/app:$BRANCH_LOWER,ghcr.io/$REPO_LOWER/app:$GITHUB_SHA" >> $GITHUB_OUTPUT
44+
fi
45+
46+
- name: Build & Push App
47+
uses: docker/build-push-action@v5
48+
with:
49+
context: ./app
50+
file: ./app/Dockerfile
51+
push: true
52+
tags: ${{ steps.tags.outputs.TAGS }}
53+
cache-from: type=registry,ref=ghcr.io/${{ github.repository }}/app:latest
54+
cache-to: type=inline

.gitignore

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,45 @@ cython_debug/
205205
marimo/_static/
206206
marimo/_lsp/
207207
__marimo__/
208+
209+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
210+
211+
# dependencies
212+
/node_modules
213+
/.pnp
214+
.pnp.*
215+
.yarn/*
216+
!.yarn/patches
217+
!.yarn/plugins
218+
!.yarn/releases
219+
!.yarn/versions
220+
221+
# testing
222+
/coverage
223+
224+
# next.js
225+
/.next/
226+
/out/
227+
228+
# production
229+
/build
230+
231+
# misc
232+
.DS_Store
233+
*.pem
234+
235+
# debug
236+
npm-debug.log*
237+
yarn-debug.log*
238+
yarn-error.log*
239+
.pnpm-debug.log*
240+
241+
# env files (can opt-in for committing if needed)
242+
.env*
243+
244+
# vercel
245+
.vercel
246+
247+
# typescript
248+
*.tsbuildinfo
249+
next-env.d.ts

.husky/pre-commit

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env sh
2+
set -e
3+
4+
echo "🧼 Running Prettier and Black..."
5+
6+
pnpm lint-staged
7+
8+
# Run black via python to avoid PATH issues
9+
cd ai
10+
python -m black .
11+
cd ..

.prettierignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules
2+
dist
3+
.next
4+
coverage
5+
.env
6+
venv
7+
__pycache__

.prettierrc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"semi": true,
3+
"singleQuote": false,
4+
"tabWidth": 2,
5+
"trailingComma": "es5",
6+
"printWidth": 100,
7+
"bracketSpacing": true,
8+
"arrowParens": "always",
9+
"endOfLine": "lf"
10+
}

.vscode/settings.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"editor.formatOnSave": true,
3+
"editor.defaultFormatter": "esbenp.prettier-vscode",
4+
"files.eol": "\n",
5+
"prettier.requireConfig": true,
6+
"prettier.useEditorConfig": false,
7+
"[python]": {
8+
"editor.defaultFormatter": "ms-python.black-formatter"
9+
},
10+
"[javascript]": {
11+
"editor.defaultFormatter": "esbenp.prettier-vscode"
12+
},
13+
"[typescript]": {
14+
"editor.defaultFormatter": "esbenp.prettier-vscode"
15+
},
16+
"[json]": {
17+
"editor.defaultFormatter": "esbenp.prettier-vscode"
18+
},
19+
"[yaml]": {
20+
"editor.defaultFormatter": "esbenp.prettier-vscode"
21+
}
22+
}

README.md

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,126 @@
11
# next-api-ai-template
2-
A full-stack AI-powered starter template with Next.js frontend, Express backend, and a dedicated AI module. Structured into app/, api/, and ai/ for clean development, rapid prototyping, and seamless integration.
2+
3+
A full-stack AI-powered starter template with **Next.js frontend**, **Express backend**, and a **Python AI module**.
4+
Structured into `app/`, `api/`, and `ai/` for clean development, rapid prototyping, and seamless integration.
5+
6+
---
7+
8+
## Tech Stack
9+
10+
- **Frontend:** Next.js (TypeScript, pnpm)
11+
- **Backend:** Express.js (Node.js, pnpm)
12+
- **AI Service:** Python (Flask)
13+
- **Containerization:** Docker + Docker Compose
14+
- **CI/CD:** GitHub Actions (ready for build + push caching)
15+
16+
---
17+
18+
## Folder Structure
19+
20+
```
21+
.
22+
├── app/ # Next.js frontend
23+
│ └── Dockerfile
24+
├── api/ # Express backend
25+
│ └── Dockerfile
26+
├── ai/ # Python Flask microservice
27+
│ ├── main.py
28+
│ ├── requirements.txt
29+
│ └── Dockerfile
30+
├── docker-compose.yml
31+
└── pnpm-workspace.yaml
32+
```
33+
34+
---
35+
36+
## Getting Started
37+
38+
### Clone the repo
39+
40+
```bash
41+
git clone https://github.com/upayanmazumder/next-api-ai-template.git
42+
cd next-api-ai-template
43+
```
44+
45+
### Run with Docker
46+
47+
Build and start all services:
48+
49+
```bash
50+
docker compose up --build
51+
```
52+
53+
Then open:
54+
55+
- **Frontend:** [http://localhost:3000](http://localhost:3000)
56+
- **API:** [http://localhost:4000](http://localhost:4000)
57+
- **AI:** [http://localhost:5000](http://localhost:5000)
58+
59+
---
60+
61+
## How It Works
62+
63+
- **Next.js (`app/`)** → Handles UI + user interactions.
64+
- **Express (`api/`)** → Acts as middleware and routes frontend requests to AI service.
65+
- **Flask (`ai/`)** → Processes AI logic or ML inference and returns responses to the API.
66+
67+
Each layer is isolated, containerized, and easily swappable.
68+
69+
---
70+
71+
## Example Flow
72+
73+
1. Frontend sends text → `/api/analyze`
74+
2. Express forwards it to Flask at `/predict`
75+
3. Flask responds with mock or real AI prediction
76+
4. Response bubbles back to UI instantly
77+
78+
---
79+
80+
## Docker Compose Overview
81+
82+
| Service | Port | Description |
83+
| ------- | ---- | ---------------- |
84+
| `app` | 3000 | Next.js frontend |
85+
| `api` | 4000 | Express backend |
86+
| `ai` | 5000 | Flask AI service |
87+
88+
Each service includes caching, health checks, and restart policies.
89+
You can deploy them independently or as a full stack.
90+
91+
---
92+
93+
## Development Notes
94+
95+
- Uses `pnpm` for efficient dependency management.
96+
- Python virtual env not needed — handled via Docker.
97+
- Ready for GitHub Actions auto-build (with GHA cache).
98+
99+
---
100+
101+
## Commands
102+
103+
```bash
104+
# Run locally (no docker)
105+
cd app && pnpm dev
106+
cd api && pnpm run dev
107+
cd ai && python main.py
108+
109+
# Run all with docker
110+
docker compose up
111+
```
112+
113+
---
114+
115+
## Future Ideas
116+
117+
- Add real model inference (OpenAI / Ollama / HuggingFace)
118+
- Add shared types via `common/`
119+
- Integrate PostgreSQL or Redis service
120+
- Deploy to Fly.io, Railway, or Render
121+
122+
---
123+
124+
## License
125+
126+
Licensed under the [MIT License](LICENSE).

0 commit comments

Comments
 (0)