Storylio
Storylio is my personal portfolio and CMS for projects, writing, and photography. Built with Next.js and PostgreSQL, it brings content editing, media management, and publishing controls into a private dashboard.

- My part
- Developed the public site and CMS, integrated the database and authentication, and refined responsive layouts, editing workflows, and media management.
- Updated
- November 8, 2026
- Reading time
- 3 min read
A portfolio with its own management space
Storylio holds my projects, writing, and photography in a single site. Behind the public pages is a dashboard for changing content without having to edit code every time I want to update a project description or add an image.
The management needs differ for each type of content. Projects have a tech stack and screenshots that can be reordered. Articles have drafts and publish schedules. Photos in the gallery can be hidden without being deleted. These differences shaped the structure of the CMS and the layout of its editors.
Connecting the editor to the public pages
The public site and the dashboard are built in a single Next.js application, with PostgreSQL for data storage and Drizzle ORM for queries and the schema.
Public content is cached, while draft reads and dashboard data are kept separate from the shared cache. Once a change is saved, the related parts of the cache are refreshed so the public pages can show the latest content.
Publication status is also checked when a detail page is opened. An article that is still a draft, or hasn't reached its scheduled time, is not available through its public URL. This check is still necessary even though the link is already hidden from the article list.
The parts that took repeated attempts
While refining the dashboard, I kept returning to details that look small: checkbox placement, filter height, how clear the delete button is on top of an image, and how the sidebar behaves when moving between screen sizes.
On phone screens, the arrangement of thumbnail, title, metadata, and action buttons easily becomes too crowded. Some parts had to be rearranged so the text gets enough room. Simply shrinking the elements didn't solve the problem.

