Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
61 changes: 61 additions & 0 deletions .agents/rules/FSD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
## 🏗️ Architecture Overview
Feature-Sliced Design (FSD) is a structural methodology for frontend applications. It organizes code into **Layers**, **Slices**, and **Segments**.



### 1. Layers (The Hierarchy)
Layers are strictly ordered. A layer may only depend on layers **below** it.
- **`app/`**: Global initialization (providers, global styles, routing).
- **`pages/`**: Full views/screens. Composition only, minimal logic.
- **`widgets/`**: Large, self-contained UI blocks (e.g., `Header`, `ProductList`).
- **`features/`**: User interactions that bring business value (e.g., `AddToCart`, `SearchUsers`).
- **`entities/`**: Business domains (e.g., `User`, `Product`, `Order`). Contains logic, state, and UI related to the entity.
- **`shared/`**: Reusable technical modules (UI Kit, API clients, `utils`, `hooks`).

---

## 📏 Core Rules

### 🚫 Rule 1: No Cross-Imports (Same Layer)
Slices within the same layer **cannot** import from each other.
* **Wrong:** `features/add-to-cart` importing from `features/remove-from-cart`.
* **Fix:** Move shared logic to `entities/` or `shared/`, or compose them in a `widget/` or `page/`.

### ⬇️ Rule 2: Unidirectional Flow
Imports must always point **downward** in the hierarchy.
* **Wrong:** `entities/user` importing from `features/auth`.
* **Fix:** A feature can use an entity, but an entity must be independent.

### 📦 Rule 3: Public API (Public Interface)
Every Slice and Segment must have an `index.ts` file.
* **Requirement:** Always import from the `index.ts` of a slice, never from internal files.
* **Agent/Dev Rule:** Only export the minimum necessary components/functions to the `index.ts`.

---

## 📂 Folder Structure Example
Each **Slice** should generally contain these **Segments**:
- `ui/`: React components.
- `model/`: State management, hooks, and business logic.
- `api/`: Request logic and types.
- `lib/`: Helper functions specific to this slice.

```text
src/
├── app/ # Entry point, providers, global styles
├── pages/ # Composition of widgets/features
├── widgets/ # Composition of features/entities
├── features/ # Action-oriented slices (e.g. auth-by-email)
├── entities/ # Domain-oriented slices (e.g. user, product)
└── shared/ # UI Kit, API base, general utils
├── ui/ # (e.g. Button, Input)
└── api/ # (e.g. Axios instance)
```

---

## 🤖 Instructions for AI Agents
1. **Placement:** Before creating a new file, determine its Layer based on business value vs. technical abstraction.
2. **Refactoring:** If you encounter a circular dependency, move the shared logic one layer down.
3. **Encapsulation:** Do not reach into a slice's internal folders (`ui/`, `model/`). Only use the `index.ts` exports.
4. **Consistency:** Keep logic in `model/` and view in `ui/` within each slice.
16 changes: 16 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
node_modules
dist
.git
.github
legacy
*.md
.gitignore
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.agents
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_API_URL=http://localhost:3000/api
14 changes: 4 additions & 10 deletions .github/workflows/build-and-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
- develop

env:
REGISTRY: ghcr.io
Expand Down Expand Up @@ -43,9 +41,9 @@ jobs:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix={{branch}}-
type=ref,event=pr
type=sha,format=long
type=sha
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push Docker image
Expand All @@ -58,11 +56,7 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
REACT_APP_BASE_URL=${{ secrets.REACT_APP_BASE_URL || 'https://backend.craftnepal.net' }}
REACT_APP_API=${{ secrets.REACT_APP_API || '/api/' }}
REACT_APP_LOGIN=${{ secrets.REACT_APP_LOGIN || '/auth/login' }}
REACT_APP_CHECK_AUTH=${{ secrets.REACT_APP_CHECK_AUTH || '/auth/verify' }}
REACT_APP_AVATAR=${{ secrets.REACT_APP_AVATAR || 'https://cdn.discordapp.com/avatars/' }}
VITE_API_URL=${{ secrets.VITE_API_URL || 'https://backend.craftnepal.net/api' }}

- name: Trigger Dokploy Deployment
if: github.event_name != 'pull_request'
Expand Down
60 changes: 37 additions & 23 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,29 +1,43 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

# Dependency directories
node_modules/
**/node_modules/

# Build outputs
dist
dist-ssr
build/
.next/
out/

# Environment variables
.env
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea/
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

./src/config.json
.vscode
# System files
Thumbs.db
db.json

# Bun
bun.lockb

.env
.env
52 changes: 14 additions & 38 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,49 +1,25 @@
# Build stage
FROM node:18-alpine AS builder

FROM oven/bun:1 AS build
WORKDIR /app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm install --legacy-peer-deps
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile

# Copy source code and env file
# Copy source code
COPY . .

# Build the React app with environment variables
ARG REACT_APP_BASE_URL=http://localhost:3006
ARG REACT_APP_API=/api/
ARG REACT_APP_LOGIN=/auth/login
ARG REACT_APP_CHECK_AUTH=/auth/verify
ARG REACT_APP_AVATAR=https://cdn.discordapp.com/avatars/

ENV REACT_APP_BASE_URL=$REACT_APP_BASE_URL
ENV REACT_APP_API=$REACT_APP_API
ENV REACT_APP_LOGIN=$REACT_APP_LOGIN
ENV REACT_APP_CHECK_AUTH=$REACT_APP_CHECK_AUTH
ENV REACT_APP_AVATAR=$REACT_APP_AVATAR
# Build arguments
ARG VITE_API_URL
ENV VITE_API_URL=$VITE_API_URL

RUN npm run build
# Build the application
RUN bun run build

# Production stage
FROM node:18-alpine

WORKDIR /app

# Install serve to run the app
RUN npm install -g serve

# Copy built app from builder
COPY --from=builder /app/build ./build

# Expose port
EXPOSE 5000

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:5000', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})"
FROM nginx:stable-alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

# Start the app
CMD ["serve", "-s", "build", "-l", "5000"]
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Loading
Loading