Astro Gallery with admin
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 --pushThis 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
/editorroute 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
/editorroute, Astro might not “see” it or optimize it until you trigger a full rebuild of the entire site. - Next.js: The
next/imagecomponent (andnext-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
| Feature | Next.js (Recommended) | Astro |
|---|---|---|
| Admin Dashboard | Superior (Built-in Server Actions) | Moderate (Requires SSR mode/Adapters) |
| Image Optimization | On-the-fly (No rebuild needed) | Build-time (Usually needs rebuild) |
| Auth Setup | Very Easy (Next-Auth) | Moderate (Manual setup) |
| Speed (Public Gallery) | Fast | Blazing 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
.envfile. - The Security Part: Never store the plain password. Use a tool like
bcryptto 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
| Component | Implementation |
|---|---|
| Auth | Next-Auth + CredentialsProvider (Bcrypt hash in .env). |
| Editor Route | app/editor/page.tsx (Protected by Middleware). |
| Uploads | CldUploadWidget from next-cloudinary (Supports folders). |
| Content | Server Actions to update a JSON file or KV store. |
| Performance | ISR (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)
| Feature | Cloudinary (SaaS) | imgproxy (Open Source) |
|---|---|---|
| API Key Needed? | Yes | No (You make your own) |
| Costs | Free tier (then $$$) | $0 (Only your electricity) |
| Privacy | They have your photos | 100% Private (Photos stay home) |
| Setup Difficulty | Very Easy | Medium (Needs Docker config) |
| Internet Required? | Always | No (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.