This is a work in progress 🚧
I’m using it to practice with new tools and to share photos with friends 🦊 🐶
- See an example gallery
- Here’s a visualization of the gallery’s state machine
- Project goals
- Helpful resources
- Guide about improving image loading for this project
- Quick start
- Setting up a local environment
- Creating a gallery
- Editing a gallery
- How to add a new album
- How to publish your gallery
- Secret albums
- Group albums
- Social sharing image
- How to add a story about an album
- Image captions
- Image file storage
To create your own gallery, you can open this project in a codespace on GitHub.
-
Make a copy of this project on GitHub (or download it)
-
Install Deno (version
1.46.3
or greater). -
From the root of your project, start a server for development...
deno task dev
- Visit
http://localhost:4000
If you see an error related to deno.lock, you can delete this file at the root of your project folder (it will be created again automatically).
- Add your pictures to the
_pictures
folder, grouped by album name
_pictures/
your-album/
original/
1.jpg
2.jpg
3.jpg
your-other-album/
original/
1.jpg
2.jpg
3.jpg
You may also want to delete the example pictures, and the LICENSE file:
_pictures/
LICENSE
northern-lights
secret-recipes
wildflowers
You can also make groups of albums.
- Add information about your gallery and featured albums to
_api/index.json
{
"title": "A name for your gallery",
"date": "2019 to 2020",
"albums": [
"your-album",
"your-other-album"
]
}
You may also want to remove the japan
and wildflowers
examples from the list in _api/index.json
.
- Create data and responsive images for your new gallery.
In the root of your project run...
deno task create
You can edit the JSON files that were created for you in the _api
folder:
_api/
index.json
your-album.json
your-other-album.json
For example, you may want to change the title
and add a date
for each album:
"title": "A name for your album",
"date": "February & March, 2020",
To see your changes, you may need to stop the server (press “control C”) and then restart the server (deno task dev
).
It’s okay to commit the generated files in these folders:
_api
_archives
_pictures
These files are your data and will only change if you re-run the deno task create
script or edit them yourself.
Running deno task create
a second time will skip any existing files, even if
they would ideally be updated–for example, .zip
files in the _archives
folder. You can work around this by removing any files or folders that you want to re-create.
- Add your pictures to the
_pictures
folder:
_pictures/
your-new-album/
original/
1.jpg
2.jpg
3.jpg
- Create data for your new album:
deno task create
- Edit the data file for your album (optional):
_api/
your-new-album.json
- Add your album to the
index.json
file to feature it on your gallery’s home page (optional):
{
"title": "A name for your gallery",
"date": "2019 to 2020",
"albums": [
"your-new-album"
]
}
The build
command will create a _site
folder that can be published on any web server.
deno task build
You can browse the static site locally with this command:
deno task file-server
And then visit http://localhost:4000
To publish with Deno Deploy, you can skip a build step and use server.js
for the entrypoint
.
If you want to publish an album to share with friends without making it public,
you can leave it out of the api/index.json
file. That way, it won’t appear on the home page of your picture gallery site.
To make the album name hard to guess, you may want to include a UUID as part of the name. For example:
your-secret-album-0c64f7ea-ad3d-4101-b379-fb5098aed301
You can also ask search engines not to index your album by setting askSearchEnginesNotToIndex
to true
in the JSON
file for your album.
{
"uri": "your-secret-album-0c64f7ea-ad3d-4101-b379-fb5098aed301",
"title": "A name of your secret album",
"date": "February & March, 2019",
"askSearchEnginesNotToIndex": true,
}
This will add a noindex meta element to your page.
And you can ask search engines not to index your entire gallery (including the home page) by setting askSearchEnginesNotToIndex
to true
in the _config.js file:
"askSearchEnginesNotToIndex": true
If your gallery is stored in a public place like GitHub, it may also be a good idea to make your repository private.
To group several albums together and show them on a single web page, create a new folder using the name of your group–and place the albums inside it.
_pictures/
your-group-of-related-albums/
related-album/
original/
1.jpg
2.jpg
3.jpg
another-related-album/
original/
1.jpg
2.jpg
3.jpg
And then visit http://localhost:4000/your-group-of-related-albums/
To make an open graph image available for each page in your gallery, add your domain name to the _config.js file:
"host": "https://your-domain-name.com"
If you’d like to include some words about your album, create a markdown file with the same name as your album’s .json
file and place it in the _api
folder. For example:
_api/
your-album.json
your-album.markdown
Your story will appear along with the images, on the page for your album.
You can write captions and descriptions for your images by editing the data file for your album:
_api/
your-new-album.json
{
"filename": "44.jpeg",
"description": "close-up of a tiny plant with purple flowers growing out of ground covered in pebbles",
"caption": "Desert Canterbury Bells at Mastodon Peak",
"uri": "44-mastodon-peak-desert-canterbury-bells"
},
The caption
will appear as part of the page title for the image. And the description
will be used as the alt
text for the image.
You can also edit the uri
to match your caption. This will appear as part of the URL for the image. For example: https://pictures.tobbi.co/wildflowers/44-mastodon-peak-desert-canterbury-bells/
If you have a lot of images, you may be able to get a head start writing descriptions by using something like Azure Computer Vision or OpenAI Vision.
The basic steps for this are...
- Copy the
.env-example
file in your local copy of this repo to a new file named.env
- Add your API key for Azure or OpenAPI to the
.env
file.
Using OpenAI Vision may require a paid account.
If you create a new album, descriptions will be generated and added to the data file for your album. You can improve or make corrections to the descriptions by manually editing the file.
You may want to use Git LFS, if your repository is getting close to 1 GB in size. See GitHub disk quota
Here are some commands that I used to migrate large files to Git LFS, when they were already in my Git commit history.
git lfs migrate import --everything --include="*.jpg,*.jpeg,*.webp,*.avif,*.png,*.zip"
git status
git push --force-with-lease
And here are a few commands that I used to switch between git-lfs
hosts.
- Fetch images from a
git-lfs
remote host, replacing local pointer files
git lfs fetch --all
- Upload images to a
git-lfs
remote host, using local image files
# Step 1: Push all commits, without uploading any large files
GIT_LFS_SKIP_PUSH=1 git push origin
# Step 2: Upload the large files for any commits that have been pushed
git lfs push origin --all
https://stately.ai/registry/editor/83f73a9c-669c-4c94-ad55-b9a10acc0644
This project is an experiment to see how easily the following goals can be achieved in a reactive single-page application on the web…
User experience
- Essential content/features are available in any web browser
- Browser features (like forward/back and bookmarks) are supported
- Site is just as accessible as it would be with static HTML and page refreshes
- Site is just as findable by search engines and archivable as it would be if it were made of static HTML pages
- First page renders as quickly as static HTML
- The application works well on a slow network
- The application has cues that are equivalent to a normal browsing experience, like a page loading indicator
- The application is still usable when things go wrong, like if a CSS file doesn’t load or a JavaScript error happens
- Gesture-driven animations and transitions between pages can be added
Editor experience
- Content can be created with a simple language like markdown
- Content can be added, edited and removed using a simple mechanism like files and folders
- The gallery can be hosted anywhere and kept private, if desired
Developer experience
- The application’s logic is easy to understand and reason about (Thanks XState!)
- Large features can be broken up into smaller components and modules
- Code for templates and logic can be used on the client or server side
- The application can be continuously deployed in a way that is reliable, scalable and secure
- New features can be added with confidence that things won’t break
- The code is easy to read
- The app can be ported to another framework without too much rework
These projects and guides have been super helpful to me, while working on the gallery…
- https://barrgroup.com/Embedded-Systems/How-To/State-Machines-Event-Driven-Systems
- https://barrgroup.com/Embedded-Systems/How-To/Introduction-Hierarchical-State-Machines
- https://xstate.js.org
- https://overreacted.io/a-complete-guide-to-useeffect/
- https://developers.google.com/web/fundamentals/web-components/
- https://hacks.mozilla.org/category/es6-in-depth/
- https://github.com/developit/htm
- https://www.pika.dev/
The code for this project is available under an open source license.
The example photos and recipes are available under a creative commons license.