Architecture:
SPA, RESTful API, FSD.
Composition:
Full code | Package.json: frontend โด backend
Structure:
MongoDB v8.0.4.
Express.js v4.21.2.
React v19.0.0.
Node.js v24.0.2.
NPM v11.3.0.
PM2 v5.4.3.
Vite v6.1.0.
This version can be deployed and tested on a local PC or VPC.
Functionally, this version is almost completely identical to CRYSTAL v1.0, but has a number of key improvements:
- UX/UI design has been improved for larger tablet screens (iPad Pro and similar devices). The side navigation bar has become more compact, increasing the display area of โthe main content:
iPad Pro 13" 2025 (iOS v26, Safari)
-
Mongoose has been removed and replaced by native driver MongoDB.
-
Data schemas for all collections (
users,posts,likes,hashtags), defined using the standard JSON Schema and initialized in MongoDB using the$jsonSchema. This approach provides consistency and a common structure for documents in collections. -
For
hashtagsandlikesseparate collections were created with denormalization and indexing, which will provide higher performance with a large amount of data. -
To search through post content, MongoDB Full-Text Search is used based on the
$textoperator. Frontend (SearchPage.jsx, Search.jsx) | Backend (searchPosts):
Demonstration of the search engine
-
Added user status (online/offline). The logic is implemented using WebSocket (frontend | backend). Added display of the time of the last visit to the site.
-
The user status (when offline) now displays the time of their last visit to the site.
-
Multer has been replaced by Sharp. The following image upload management and cybersecurity features have been added to sharp-upload.js:
โ Limiting simultaneous image processing (Semaphore)
To prevent processor overload during resource-intensive image processing, a semaphore mechanism is used.
โ Request rate limiting (Rate Limiting)
To protect against DDoS attacks and spam, a limit on the number of download requests from a single IP address is used.
โ Limiting the size of the uploaded file
Checking limit occurs early in the upload process to avoid reading excessively large files into memory.
โ Uploaded file validation process
After passing the initial checks (Semaphore and Rate Limiting), the uploaded file undergoes a double check (!isImageExtension and !isImageMime) to ensure that it is indeed a safe image. The system simultaneously checks two independent characteristics of the file: the extension (checking the file name for one of the allowed extensions: jpe?g|png|webp|gif) and the MIME type, which must match: image/(jpeg|png|webp|gif). If any of these checks fail, the file goes to a special GIF check, and the subsequent isValidGif(fileBuffer), which checks for "Magic Bytes" in the file header (GIF87a or GIF89a).
-
GIFs are sanitized via special logic. All images except GIFs are converted to WebP.
-
Added an interface setting that allows you to hide all GIF images on the site:
Hidden GIF images, light theme
Hidden GIF images, dark theme
-
Added the ability to specify user gender.
-
On the user page, a section with detailed user information has been added: gender, registration date.
-
Added a privacy setting that allows you to hide gender.
-
To increase productivity, offset pagination was replaced with cursor pagination in the sections for displaying user likes, posts with a specific hashtag, and searching for posts.
-
Added a 'Back' button.
-
Added logic for deleting old images from posts and users: after deleting/replacing images, after deleting a user or post.
-
Added validation for hashtags in the backend, which prevents saving hashtags like:
##Test,#Te#st,#Te?st, etc. The check is performed using a regular expression โ/^[\p{L}0-9_-]+$/u(allows any Unicode letters, numbers, hyphens, and underscores). You can also set the allowed number of hashtags in one post and the hashtag length using constants:MAX_HASHTAGS_COUNTandMAX_HASHTAG_LENGTH. If a hashtag fails validation, it is not added to the database, but the post is still created and its text will contain an invalid hashtag โ#Te#st. After successful verification, the hashtag#Testis added to thenamefield of thehashtagscollection, in lowercase โtest. -
Added validation for hashtags in the frontend. To be displayed as a clickable link, the hashtag must be validated using a regular expression โ
/^[\p{L}0-9_-]+$/u(Allows any Unicode letters, numbers, hyphens, and underscores). -
Added more informative display of post creation and update dates in the full and preview versions. Date formatting occurs in a special hook โ useFormattedPostDate, which performs localized date and time formatting in two languages โโ(Russian and English) using
toLocaleDateStringandtoLocaleTimeString. For the English locale, a 12-hour clock is used (Jul 4, 2025 โ 10:45 PM), and for the Russian locale, a 24-hour clock (4 ะธัะปั 2025 โ 22:45). The hook automatically detects the current interface language viai18n.languageand displays the year only if the date belongs to the previous year. -
Database cybersecurity system complies with CRYSTAL v1.0 (Production).




