PrimeMemory is a full-stack web app for saving and organizing useful links/content, then sharing a public read-only "brain" view with others using a generated short hash link.
This repository is organized as a two-app workspace:
frontend- React + Vite + TypeScript clientbackend- Express + TypeScript + MongoDB API
Core user flow:
- User signs up / signs in.
- User stores content items (title, link, type).
- User sees all personal items on dashboard.
- User can update/delete items.
- User can generate a share link.
- Anyone with
/share/:shareIdcan view shared content publicly.
Current branding in UI identifies product as PrimeMemory.
- React 19
- TypeScript
- Vite
- React Router
- Axios
- Tailwind CSS v4
- ESLint (frontend only)
- Node.js + Express 5
- TypeScript (compiled to
dist) - MongoDB with Mongoose
- JSON Web Tokens (
jsonwebtoken) - CORS
secondBrain/
├── frontend/
│ ├── src/
│ │ ├── pages/ # Landing, auth, dashboard
│ │ ├── component/ # Reusable UI and content cards/modals
│ │ ├── hooks/ # Data hooks (e.g. useContent)
│ │ ├── Icon/ # Icon components
│ │ ├── App.tsx # Route map
│ │ └── config.ts # Frontend API base URL
│ ├── package.json
│ └── ...
├── backend/
│ ├── src/
│ │ ├── index.ts # Express server + all API routes
│ │ ├── db.ts # Mongo connection + schemas/models
│ │ ├── middleware.ts # JWT auth middleware
│ │ ├── config.ts # JWT secret constant
│ │ └── utils.ts # Helper utilities
│ ├── package.json
│ └── ...
└── READ.md
Defined in frontend/src/App.tsx:
/-> Landing page/signup-> Signup screen/signin-> Signin screen/dashboard-> Private dashboard (token expected in localStorage)/share/:shareId-> Public shared dashboard view*-> basic fallback "Content Not Found"
Base URL (current frontend config): http://localhost:3000
Creates a new user.
Request body:
{
"username": "alice",
"password": "secret"
}Response (success):
{ "message": "User Signed Up" }Possible failure:
411if username already exists
Authenticates user and returns JWT.
Request body:
{
"username": "alice",
"password": "secret"
}Response (success):
{ "token": "<jwt>" }Possible failure:
403invalid credentials
Create content item.
Request body:
{
"title": "My link",
"link": "https://example.com",
"type": "article"
}Response:
{ "message": "Content Added" }Returns current user's content list.
Response:
{
"content": [
{
"_id": "...",
"title": "My link",
"link": "https://example.com",
"type": "article",
"userId": { "_id": "...", "username": "alice" }
}
]
}Update one content item belonging to user.
Request body:
{
"title": "Updated",
"link": "https://example.com/new",
"type": "article"
}Response:
{ "message": "Content updated" }Possible failure:
404if content not found for this user
Delete one content item belonging to user.
Response:
{ "message": "Deleted" }If body has "share": true, generates (or reuses) a unique hash for current user.
Request:
{ "share": true }Response:
{ "hash": "abc123def0" }If "share" is falsey, existing share link is removed:
{ "message": "Link removed" }Returns shared content and username for hash.
Response:
{
"username": "alice",
"content": [ ... ]
}Possible failure:
411invalid share link
Defined in backend/src/db.ts.
username: string(unique)password: string
title: stringlink: stringtags: ObjectId[](ref"Tag", no Tag schema currently implemented)type: stringuserId: ObjectId(ref"User", required)
hash: stringuserId: ObjectId(ref"User", required, unique)
Auth middleware (backend/src/middleware.ts) expects:
- Header:
Authorization: Bearer <token> - Token signed with backend
JWT_PASSWORD - Decoded payload includes
id
On success:
req.userIdis attached and used in protected queries
On failure:
403returned
- Node.js 18+ (recommended)
- npm
- Internet access to MongoDB Atlas (current connection is cloud-hosted)
cd backend
npm install
npm run build
npm run startBackend listens on:
http://localhost:3000
Note:
- Current
npm run devis not watch mode. It runsbuildthenstart.
cd frontend
npm install
npm run devFrontend default:
http://localhost:5173
npm run dev- start Vite dev servernpm run build- type-check/build frontend bundlenpm run lint- run ESLintnpm run preview- preview production build
npm run build- compile TypeScript intodistnpm run start- run compiled servernpm run dev- build then start (no auto-reload)npm test- placeholder (currently always fails)
The current codebase contains hardcoded secrets/config values:
- MongoDB connection URI in
backend/src/db.ts - JWT secret in
backend/src/config.ts - Frontend API URL in
frontend/src/config.ts
Recommended immediate improvements:
- Move these to environment variables.
- Add
.env.examplefiles for frontend/backend. - Rotate exposed credentials and secrets.
Suggested env variables:
- Backend:
PORTMONGODB_URIJWT_SECRETCORS_ORIGIN
- Frontend:
VITE_BACKEND_URL
- Passwords are stored in plain text (no hashing).
- Hardcoded DB URI and JWT secret in source.
- No backend validation layer (e.g., zod/joi).
- No automated tests (unit/integration/e2e).
- No backend lint config and no formatting standard config.
- Error status codes are inconsistent (
411used for business errors). - Backend "dev" flow lacks watcher (
nodemon/tsx watch).
Priority order:
- Add password hashing (
bcrypt) and secure signin flow. - Move secrets to env files and rotate leaked secrets.
- Add request validation and centralized error handling.
- Add basic backend tests for auth/content/share endpoints.
- Add backend linting + prettier + CI checks.
- Add Docker + deployment docs (or hosting guides).
- Start backend and frontend.
- Sign up a new account.
- Sign in and confirm token stored.
- Add 2-3 content items.
- Update one item.
- Delete one item.
- Generate share link and open in incognito.
- Verify public page shows shared user + content.
Current maturity: MVP / local-development focused
Strong points:
- Clean basic full-stack flow
- Token-protected content ownership checks
- Share-link feature implemented end-to-end
Before production:
- Security hardening
- Configuration/env cleanup
- Observability + tests + CI/CD
- Deployment architecture and CORS tightening