A full‑stack incidents management app with a Go (Echo) backend and a React + Vite + Tailwind frontend. It supports authentication, role‑based access (Admin/User), incident CRUD with image upload, and user management. The frontend can run in dev mode with a proxy to the API or be built and served by the backend.
- API docs: http://localhost:8080/swagger/index.html
- Create backend env file:
cat > backend/.env <<'EOF' PORT=8080 DB_PATH=incidents.sqlite JWT_SECRET=devsecret_change_me IMAGES_DIR=images EOF
- Start backend:
cd backend go run ./cmd/app
- Start frontend:
cd frontend npm i npm run dev
- Open http://localhost:5173
Notes
- The Vite dev server proxies
/api
and/images
to http://localhost:8080 (seefrontend/vite.config.ts
). - SQLite DB and
images/
live at the repo root by default (based on env). - For first login, you’ll need an Admin user (see “Seeding an admin”).
- Backend
- Go 1.24.x, Echo
- SQLite + sqlx, goqu (query builder)
- JWT auth, Echo middleware, validator
- Swagger via
echo-swagger
- Frontend
- React 18, Vite
- Tailwind CSS + HeroUI
- React Router
- Build/Serve
- Dev: Vite dev server proxies to Go server
- Prod:
npm run build
emits tobackend/dist/
and Go serves the SPA and images
backend/cmd/app/main.go
: boots the service (reads env, connects DB, starts API).backend/api/config.go
: Echo wiring: routes, middleware, swagger, SPA static serving, and/images
.backend/api/route.go
: groups incident and user routes behind JWT middleware.backend/api/handler/
:user.go
: login/logout, users CRUD (admin‑only).incident.go
: incidents CRUD. Non‑admins see only their incidents; listing ordered bycreated_at desc
.
backend/pkg/repository/
: DB access, filters via goqu (e.g.,OrderByFilter
).backend/config/config.go
: loads.env
, computes project paths (e.g., images dir).frontend/
: SPA with routes for login, incidents (list/create/edit), users (list/create/edit).src/components/protected-route.tsx
: protects routes based on auth.src/config/site.ts
: navbar items for Home, Incidents, Users.
Data flow
- Client authenticates via email/password. Server issues JWT and sets an HttpOnly cookie; middleware validates on subsequent requests.
- Incidents can include image files; server stores under
images/
and serves via/images/...
.
- Authentication
- Email/password login (
POST /api/login
) - JWT returned and set as HttpOnly cookie (SameSite=Lax)
- Email/password login (
- Authorization
- Roles:
ADMIN
,USER
(backend/pkg/model/entity.go
) - Admin manages users and all incidents
- Users can CRUD their own incidents
- Roles:
- Incidents
- List, view, create, update, delete
- Image upload handled via multipart form; served publicly under
/images
- Listing ordered by newest first
- Users (admin)
- List, create, update (password hashing), delete
- Frontend
- Tailwind + HeroUI UI
- SPA with protected routes; build artifacts served by the backend in production
- API Docs
- Swagger UI at
/swagger/
- Swagger UI at
Backend .env
(expected at backend/.env
):
PORT
(default: 3000) — set to8080
for dev to match Vite proxyDB_PATH
(default: incidents.sqlite) — SQLite file path at repo rootJWT_SECRET
— secret for JWT signing (use a strong value)IMAGES_DIR
(default: images) — directory for uploads; served at/images
- Auth
POST /api/login
— returns token and user, sets cookieGET /api/logout
— clears cookie
- Users (admin)
GET /api/users
POST /api/users/create
PATCH /api/users/edit
DELETE /api/users/delete/:id
- Incidents (auth required)
GET /api/incidents
— non‑admins see their own; ordered bycreated_at desc
GET /api/incidents/:id
POST /api/incidents/create
— multipart form for image uploadPATCH /api/incidents/update
DELETE /api/incidents/delete/:id
See backend/api/handler/*.go
for handler details.
- Cookies in local dev: cookie is set with
Secure: true
. On plain HTTP some browsers may not persist it.- Option A: run behind HTTPS locally.
- Option B: relax the secure flag for local only (not recommended for prod).
- SQLite chosen for simplicity; migrations tool not included.
- Minimal filtering/pagination now; repository layer is ready for pagination/search filters.
- In production builds, the backend serves
backend/dist/
at/
. - Images are persisted on disk at
images/
. For containers/cloud, mount persistent storage.
Seeding an Admin (manual)
- Create an admin row directly in SQLite or temporarily add a seeding snippet (bcrypt) in
api/config.go
and remove it after first run. Example fields:email
,name
,role=ADMIN
,password
hashed via bcrypt.
Done
- Backend API (Echo), JWT auth, role‑based access
- Incidents CRUD with image upload and ordering
- Users CRUD (admin), password hashing
- Frontend pages for login, incidents (list/create/edit), users (list/create/edit)
- Dev proxy and prod build pipeline
- Swagger docs endpoint
Backend
cd backend
go run ./cmd/app
Frontend (dev)
cd frontend
npm i
npm run dev
Frontend (prod build served by backend)
cd frontend
npm i
npm run build
cd ../backend
go run ./cmd/app
- Drafted this README and consolidated run instructions.
- Helped plan the frontend pages aligned with backend handlers to make more fast the development of the frontend.
See LICENSE
.