A hub for connecting tattoo artists, studios, and academies. Browse profiles, limited offers, events and conventions, request quotes, and manage your professional profile—with an admin panel for content and user management.
- Client: React 18, Vite, React Router
- Server: Node.js, Express
- Database: MongoDB (Mongoose)
- Auth: JWT, bcrypt
- Other: Nodemailer (SMTP), Sharp (images), OpenStreetMap Nominatim (geocoding)
- Node.js 18+
- MongoDB 7 (local or Docker)
- npm or yarn
git clone <repo-url>
cd InkHub
npm install --prefix server
npm install --prefix clientServer – copy server/.env.example to server/.env and set:
PORT=4000
MONGODB_URI=mongodb://127.0.0.1:27017/linkedink
JWT_SECRET=your-secret-at-least-32-chars
CORS_ORIGIN=http://localhost:5173
FRONTEND_URL=http://localhost:5173Optional (contact forms, password reset, promotions, events email):
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=mailer@example.com
SMTP_PASS=your-password
CONTACT_TO_EMAIL=contact@example.com
CONTACT_FROM_EMAIL=no-reply@example.com
RESET_PASSWORD_FROM_EMAIL=no-reply@example.comClient – copy client/.env.example to client/.env:
VITE_API_URL=http://localhost:4000/apiWith Docker:
docker-compose up -dOr use a local MongoDB instance on mongodb://127.0.0.1:27017.
Terminal 1 – API
cd server && npm run devTerminal 2 – Frontend
cd client && npm run devOpen http://localhost:5173.
| Script | Description |
|---|---|
npm run dev |
Start API with watch mode |
npm start |
Start API (production) |
npm run admin:create |
Create or update admin user (see below) |
npm run seed:locations |
Seed Spanish provinces and cities |
npm run seed:providers-demo |
Seed demo providers |
npm run backfill:geocode |
Backfill profile coordinates from addresses |
| Script | Description |
|---|---|
npm run dev |
Start Vite dev server |
npm run build |
Production build |
npm run preview |
Preview production build |
From server/:
npm run admin:create -- --email=admin@example.com --password=YourSecurePassword --name="Admin Name"LinkedInk/
├── client/ # React (Vite) frontend
│ ├── public/
│ ├── src/
│ │ ├── api/
│ │ ├── components/
│ │ ├── context/
│ │ ├── data/
│ │ ├── pages/
│ │ ├── styles/
│ │ ├── App.jsx
│ │ └── main.jsx
│ └── index.html
├── server/ # Express API
│ ├── src/
│ │ ├── config/
│ │ ├── controllers/
│ │ ├── middleware/
│ │ ├── models/
│ │ ├── routes/
│ │ ├── scripts/
│ │ ├── utils/
│ │ ├── app.js
│ │ └── index.js
│ └── .env.example
├── docker-compose.yml # MongoDB
└── README.md
- Auth: Register, login, JWT, password reset by email
- Profiles: Professional profiles (artist / studio / academy) with geocoding
- Map: Directory map with search and location detection
- Quotes: Clients send quote requests; artists/studios/academies approve or reject
- Offers & events: Limited offers, seminars, conventions (admin-created + user submissions)
- Promotions: Form to request promotion on the site
- Contact: General contact form
- Admin: Users, offers, events, contacts, providers
Proprietary. See LICENSE for terms.
To report a vulnerability, see SECURITY.md.