Description and capabilities of CRYSTAL v2.0
October 28, 2025
upd: September 5
Contents:
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.
Description and features
Functionally, this version is almost completely identical to CRYSTAL v1.0, but has a number of key improvements:
- 1. 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)
- 2. Mongoose has been removed and replaced by the native MongoDB driver.
- 3. Data schemas for all collections (
users,posts,likes,hashtags), are defined using the JSON Schema standard and initialized in MongoDB using the $jsonSchema. This approach ensures consistency and a unified structure for documents in collections. - 4. Separate collections with denormalization and indexing have been created for hashtags and likes, ensuring better performance with large data volumes.
- 5. To search through post content, MongoDB Full-Text Search is used based on the $text operator. Frontend (SearchPage.jsx, Search.jsx) | Backend (searchPosts):
Demonstration of the search engine
- 6. Added online/offline user status powered by WebSocket (frontend | backend).
- 7. The user status (when offline) now displays the time of their last visit to the site.
- 8. Multer has been replaced by Sharp. The following image upload management and cybersecurity features have been added to sharp-upload.js:
8.1. Limiting simultaneous image processing (Semaphore)
To prevent processor overload during resource-intensive image processing, a semaphore mechanism is used.
8.2. 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.
8.3. Limiting the size of the uploaded file
Checking limit occurs early in the upload process to avoid reading excessively large files into memory.
8.4. Uploaded file validation process
After passing the initial checks (Semaphore and Rate Limiting), the uploaded file undergoes a double check (
!isImageExtensionand!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 subsequentisValidGif(fileBuffer), which checks for "Magic Bytes" in the file header (GIF87aorGIF89a). - 9. GIFs are sanitized via special logic. All images except GIFs are converted to WebP.
- 10. 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
- 11. Added the ability to specify user gender.
- 12. On the user page, a section with detailed user information has been added: gender, registration date.
- 13. Added a privacy setting that allows you to hide gender.
- 14. 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.
- 15. Added a 'Back' button.
- 16. Added logic for deleting old images from posts and users: after deleting/replacing images, after deleting a user or post.
- 17. 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. - 18. 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). - 19. 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. - 20. Database cybersecurity system complies with CRYSTAL v1.0 (Production).
Demonstration of the capabilities of CRYSTAL v2.0
Share









Comment on