Astro Gallery with admin

Astro Gallery with admin

December 25, 2025

Tl;DR

lets start the development and add the comments when each of them will be done and tested (when this is all finished, lets create a z-walkthrough.md with how to run the project)

#sudo apt install gh
gh auth login
gh repo create entreagujaypunto-next-gallery --private --source=. --remote=origin --push

#git init && git add . && git commit -m "Initial commit: Starting NextJS photo gallery entreagujaypunto v2" && gh repo create entreagujaypunto-next-gallery --private --source=. --remote=origin --push

This was the brd, the clarifications and the development plan.

And…the final result as per the walkthrough.

Intro

About the Tech Stack

Astro is an incredible framework, and for a purely static gallery (like a photographer’s portfolio that only changes once a month), it might actually be faster than Next.js. However, based on your specific requirement for an authenticated editor and dynamic photo management, Next.js is the more practical choice.

Here is a breakdown of why Next.js fits your “Admin + Gallery” vision better than Astro:

1. The “Application” vs. “Website” Problem

Astro is built with a “Content-First” philosophy (optimized for reading). Next.js is “Application-First” (optimized for doing).

  • Next.js: Has built-in API Routes and Server Actions. This makes the “Upload” and “Edit Text” parts of your /editor route feel like a native part of the framework. You can handle the password check and the image upload logic in a single file.
  • Astro: While it can do SSR (Server-Side Rendering), its strength is shipping zero JavaScript to the user. Building a protected admin dashboard in Astro often requires more “wiring up” of external backends or complex middleware configurations compared to the “batteries-included” nature of Next.js.

2. Image Optimization: On-Demand vs. Build-Time

This is the biggest technical difference for a gallery:

  • Astro: Its built-in image optimization usually happens at build time. If you upload a new photo through your /editor route, Astro might not “see” it or optimize it until you trigger a full rebuild of the entire site.
  • Next.js: The next/image component (and next-cloudinary) optimizes images on-demand. The moment you upload an image, it is available and optimized for the next visitor without needing to rebuild the code. This is essential for an admin-driven gallery.

3. Authentication Ecosystem

Since you want “good authentication” for your /editor path:

  • Next.js: Has Auth.js (Next-Auth), which is arguably the most mature auth library in the JavaScript ecosystem. It makes “hardcoding” a user/pass and protecting a specific route (/editor) a 5-minute task.
  • Astro: Authentication is possible (using libraries like Lucia or Auth.js for Astro), but the integration is less “plug-and-play” than it is in the React/Next.js ecosystem.

Comparison Summary

FeatureNext.js (Recommended)Astro
Admin DashboardSuperior (Built-in Server Actions)Moderate (Requires SSR mode/Adapters)
Image OptimizationOn-the-fly (No rebuild needed)Build-time (Usually needs rebuild)
Auth SetupVery Easy (Next-Auth)Moderate (Manual setup)
Speed (Public Gallery)FastBlazing Fast (Slight edge over Next)

If you want to manage your site (uploading, deleting, changing text) without touching code or waiting for “builds” every time you add a photo, Next.js is the winner. If you were building a site where you only added photos by changing the code yourself, Astro would be the winner.

Going ISR

Choosing Next.js is a smart move for this specific project. While Astro is faster for static content, Next.js is a web application framework that makes building your “Editor” and handling secure uploads much more seamless.

To answer your question: Yes, it will be SSR (or more accurately, a hybrid), and the authentication can be exactly as “hardcoded and top-notch” as you described.


1. Hardcoded, Top-Notch Authentication

You don’t need a database for a single admin.

You can use Next-Auth (Auth.js) with the CredentialsProvider.

It is “top-notch” because it handles secure session cookies (HTTP-only), CSRF protection, and JWT encryption automatically.

  • The “Hardcoded” Part: You store your username and a hashed version of your password in your .env file.
  • The Security Part: Never store the plain password. Use a tool like bcrypt to generate a hash once, and only store that hash in your environment variables.

2. How the Editor will work

The /editor will be a protected page where you handle two main things:

A. Folder-Based Image Uploads

Using the next-cloudinary library, you can embed a “Cloudinary Upload Widget” directly in your editor.

  • Folders: You can configure the widget to allow you to type a folder name (e.g., “Summer2025”) or select from a dropdown.
  • Instant Optimization: The moment you upload, Cloudinary generates the optimized versions.
  • Pathing: On your gallery, you fetch images based on these folder names.

B. Editable Text

Since you only have “minimal text,” you don’t need a heavy CMS.

  • Storage: Use a simple JSON file (if on a VPS) or Vercel KV (a tiny, fast key-value store).
  • The UI: On /editor, you’ll have a simple form. When you hit “Save,” it triggers a Next.js Server Action that updates your JSON/KV store and refreshes the site cache.

3. SSR vs. SSG (The Best of Both Worlds)

In Next.js, you don’t have to choose just one. You can use Incremental Static Regeneration (ISR).

  • The Public Gallery: This stays static and lightning-fast (like Astro).
  • The Update: When you finish uploading photos in /editor, you tell Next.js to “revalidate” the gallery. It then regenerates the page in the background.
  • Result: Your users get the speed of a static site, but your content is always fresh.

Summary Table: Your Next.js Gallery

ComponentImplementation
AuthNext-Auth + CredentialsProvider (Bcrypt hash in .env).
Editor Routeapp/editor/page.tsx (Protected by Middleware).
UploadsCldUploadWidget from next-cloudinary (Supports folders).
ContentServer Actions to update a JSON file or KV store.
PerformanceISR (Static speed with dynamic updates).

CLoudinary vs imgproxy

If you decide to go with the internal open-source (imgproxy) route, you will not need an API key for Cloudinary or any other third-party service.

Since you are running everything inside your own Docker environment, the only “keys” you will use are the ones you generate yourself to secure the communication between your Next.js app and your imgproxy container.


1. How the Internal Keys Work

Instead of an API key from a company, you use two environment variables in your docker-compose.yml:

  • IMGPROXY_KEY: A hex-encoded random string.
  • IMGPROXY_SALT: Another hex-encoded random string.

Your Next.js app uses these to “sign” the image URLs. This prevents someone from maliciously changing the URL parameters (e.g., trying to resize a photo to 99999x99999 pixels to crash your server).

2. The Updated “Zero-SaaS” Architecture

  • Next.js Container: Runs your gallery and the /editor.
  • imgproxy Container: Watches your local folder. When Next.js asks for an image, imgproxy grabs the file, optimizes it, and sends it back.
  • Shared Volume: A folder on your hard drive (e.g., /home/user/photos) is “mounted” into both containers so they can both see the original files.

3. Final Comparison: Cloudinary vs. Internal (imgproxy)

FeatureCloudinary (SaaS)imgproxy (Open Source)
API Key Needed?YesNo (You make your own)
CostsFree tier (then $$$)$0 (Only your electricity)
PrivacyThey have your photos100% Private (Photos stay home)
Setup DifficultyVery EasyMedium (Needs Docker config)
Internet Required?AlwaysNo (Works offline/local network)

4. Updated Business Requirements (BRD Addendum)

To make this 100% open-source, we will update the Technical Requirements section:

  • Image Processor: imgproxy:latest (Docker Image).
  • Storage: Local Docker Bind-Mount (No S3/Cloud storage).
  • URL Generation: Custom Next.js Image Loader (Open source).
  • Security: URL Signature checking enabled via IMGPROXY_KEY.

Since you want this to be “top-notch” and professional: Would you like the full docker-compose.yml file and the next.config.js settings to link these two together right now? This will give you a “one-click” command (docker-compose up) to start your entire private gallery.

Self-hosting image optimization with imgproxy This video is helpful because it demonstrates how to set up a custom image loader in Next.js, which is the exact mechanism you’ll use to connect your gallery to your internal imgproxy container.