Open-source project
opennookorg/screenshot-studio avatar
opennookorg/screenshot-studio

Screenshot Studio: a browser-based screenshot and mockup editor you can self-host

A free, browser-based editor for creating stunning screenshots and visuals. No signup, no watermarks.

1,083 stars162 forksTypeScriptApache-2.0

At a glance

What is it?
Screenshot Studio is an open-source, browser-based editor for screenshots, mockups and social graphics, with no signup and no watermarks, built on Next.js, React, Tailwind and Zustand, with a canvas renderer, server-side screenshot caching, and a Next.js app plus a Prisma and PostgreSQL data layer. The last push was on 2026-10-11.
Who is it for?
Screenshot Studio fits a team that needs a screenshot or app-store asset tool it can run itself, with no account, no watermark and no third-party upload of its marketing material. It does not fit someone who wants a design tool with layers of arbitrary type and vector editing, since the feature set is centred on compositing images, frames, text and annotations.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A full editor in a browser tab, with no account to create

Screenshot Studio is described as a free, open-source editor for screenshots, mockups and social graphics, with no signup and no watermarks, and the repository is a Vercel OSS Program project with a live site at screenshot-studio.com.

The no-signup and no-watermark position is the commercial argument, and it is a real one. Most tools in this space either put their branding on your export or make you create an account before the first render. For a team producing store listings, changelog graphics or documentation images, both are friction, and both are the kind of thing that decides which tool you use.

The product is split into several entry points on the site. There is the editor itself at `/editor`, a set of image tools at `/tools`, a code to image tool at `/code`, and an App Store screenshots tool at `/store-screenshots`. The code to image route is the interesting one for a developer audience, because it turns a snippet into a graphic, which is the format the README's own screenshot is in.

The capability list is worth reading as a scope definition. Screenshot designs cover backgrounds, browser and device frames, shadows and 3D perspective. Text-only graphics let you start without an image, choose Inter, Geist or other fonts, then drag or centre your text. Layered compositions combine text, images, annotations and blur regions. Store and social assets have ready-made layouts and exact export sizes, including Chrome Web Store screenshots.

The export formats are broad, PNG, JPEG, WebP, batch ZIP, MP4, WebM and GIF, and the quick edits are resize, crop, convert, compress and remove image backgrounds.

That combination of motion exports, blur regions and 3D perspective is the difference from a plain mockup tool, and it is where the dependency list starts to explain itself.

The dependency list is a map of what the editor actually does

The `package.json` in the repository is long, and it reads as a specification of the feature set rather than a list of helpers.

The rendering stack is the first group. `@react-three/fiber` at ^9.5.0 and `@react-three/drei` at ^10.7.7 are React bindings for Three.js, and `@shadergradient/react` at ^2.4.20 is for gradient backgrounds. That is where 3D perspective and shader-based backgrounds come from, and it is a heavy dependency to carry for an image editor, but it buys real 3D rather than a 2D skew.

The media stack is the second. `@ffmpeg/ffmpeg` and `@ffmpeg/util` handle the video and animation exports, and the wasm builds of FFmpeg are what make MP4, WebM and GIF possible without a server. `@jsquash/avif` is a browser-side AVIF encoder, `@huggingface/transformers` at ~3.8.1 suggests some on-device model work, and `@sparticuz/chromium` at ^141.0.0 is a serverless Chromium build, which is the giveaway for how the server-side screenshot rendering works.

The UI layer is the standard shadcn/ui stack, with the Radix primitives for accordion, alert dialog, avatar, dialog, dropdown menu, label, popover, select, separator, slider, slot, tabs and tooltip, plus `components.json` at the root confirming the shadcn configuration.

The data layer is Prisma at ^6.19.0 with a `prisma/` directory and a `prisma.config.ts`, and the storage layer is the AWS SDK for S3 at ^3.990.0 with the request presigner, which is how uploads to R2 work.

And the state layer is Zustand, with `@tanstack/react-query` for server data, `clsx`, `tailwind-merge` and `class-variance-authority` for styling, `@use-gesture/react` for drag interactions.

The browser editor needs no database, the build does

The local run instructions are unusually honest about which parts of the system are optional, and that saves an hour of setup confusion.

The requirements are Node.js 20.9 or newer and npm, and the setup is four commands:

bash
git clone https://github.com/opennookorg/screenshot-studio.git
cd screenshot-studio
npm ci
printf 'DATABASE_URL="postgresql://localhost:5432/screenshot_studio"\n' > .env
npm run dev

The `.env` line looks ceremonial and is not. The documentation explains that the browser editor needs no running database, but `DATABASE_URL` is required by Prisma during startup and builds. Since the `dev` and `build` scripts both start with `npx prisma generate`, the environment variable has to exist before anything runs, even if the editor itself never talks to the database.

The second optional piece is the screenshot cache. Server-side screenshot caching requires PostgreSQL and R2 credentials, and the configuration lives in `lib/screenshot-cache.ts`. So the architecture has three tiers: the editor in the browser, which needs nothing; a Prisma and PostgreSQL layer for accounts, saved work or whatever else the app persists; and an R2-backed cache for rendered screenshots, which is the path for producing images at a size or volume the browser should not do.

That three-tier split is a good design for a self-hosted tool, because a user who only wants the editor can run it without either piece of infrastructure, and a user who wants the caching adds the rest.

The upload scripts in the manifest reflect the third tier. There are separate scripts for uploading to R2, uploading all of it, uploading by pattern and uploading a demo set, which is the shape of a project where the object store holds a large number of pre-generated assets.

A Next.js app with the internals on display

The top-level listing shows a Next.js App Router project with a lot of its working parts exposed.

There is an `app/` directory for the routes, `components/` and `hooks/` for the client side, `lib/` for shared code, `types/` and a `css-modules.d.ts` for the TypeScript side, and `public/` for static assets. There is a `middleware.ts` at the root, which is where the request pipeline lives, and an `instrumentation-client.ts`, which is where client-side instrumentation hooks go.

Two directories are worth singling out. There is an `i18n/` directory with a `messages/` directory beside it, which is the standard arrangement for a Next.js project with translated copy, and it is a signal that the tool is meant for users outside one language market. There is also a `scripts/` directory with the R2 upload scripts, and a `tests/` directory with the test suite.

The test story is small and specific. The `test` script is `tsx --test tests/*.test.ts`, which is the Node test runner rather than Jest or Vitest, so the tests run without a framework dependency. There is a separate `verify:agents` script, `tsx tests/verify-agent-endpoints.ts`, and the top-level `.agents/`, `.claude/` directories and `skills-lock.json` point to the same thing: the project has agent-facing configuration and a script that checks the agent endpoints work.

The `jackbutcher.md` file at the root of the repository is an outlier, a standalone markdown file that is not part of the application tree. Whatever its purpose, it is not wired into the build.

The `next.config.ts` and `vercel.json` are both present, and the `postcss.config.mjs`, `tsconfig.json` and `eslint.config.mjs` are the standard Next.js TypeScript setup. The `ARCHITECTURE.md` at the root is the file to read first, and `CONTRIBUTING.md` covers the workflow and the checks.

The scripts show a self-hosted project with a deployment story

The script list in `package.json` is short enough to read in one go, and it explains a fair amount about the project's operation.

json
"scripts": {
    "dev": "npx prisma generate && next dev --webpack",
    "build": "npx prisma generate && next build --webpack",
    "start": "next start",
    "lint": "eslint .",
    "test": "tsx --test tests/*.test.ts",
    "verify:agents": "tsx tests/verify-agent-endpoints.ts",
    "upload-to-r2": "tsx scripts/upload-to-r2.ts",
    "upload-all-to-r2": "tsx scripts/upload-all-to-r2.ts",
    "upload-pattern": "tsx scripts/upload-pattern-to-r2.ts",
    "upload-demo": "tsx scripts/upload-demo-to-r2.ts"
}

Two details stand out.

The first is `--webpack` on both `dev` and `build`. The project explicitly selects webpack in both `dev` and `build`. That is usually a sign of an unusual dependency, and this project has one: `@react-three/fiber`, `@shadergradient/react` and the wasm FFmpeg build are all things that have historically had rough edges under a bundler that makes different assumptions. Pinning the bundler removes a class of surprise at the cost of build speed.

The second is the four R2 upload scripts. `upload-to-r2` is a targeted upload, `upload-all-to-r2` is a bulk one, `upload-pattern` is a glob-driven one and `upload-demo` is for a demo asset set. Four variants of the same operation is a project that regularly moves generated assets to object storage, and the difference between targeted and pattern upload is the difference between a one-off and a nightly job.

The `start` script is `next start`, and there is a `lint:fix`. Combined with the `CONTRIBUTING.md` reference in the readme, the contribution loop is: clone, set the environment variable, install with `npm ci`, run the checks, and open a pull request.

Where Screenshot Studio is the wrong choice

The first case is a design task with real vector editing. The feature list is compositing, framing, text, annotations and blur regions, and the export formats are raster and video. If you need to draw a logo, adjust bezier paths or set a paragraph's leading, this is the wrong tool, and a design application is the right one.

The second case is a team that needs a screenshot service, not an editor. The project has a server-side screenshot cache with R2 and PostgreSQL, and an `@sparticuz/chromium` build for headless rendering, but the product is an editor with a person in the loop. Using it as a batch renderer means building the automation around the cache tier, and the documentation does not describe an API for that.

The third case is a user who does not want to run anything. The hosted site exists, and it is free with no account, but the reason to take the source is control, and control means you deploy it. The dependency footprint is the thing to weigh before you do. A React Three Fiber stack, wasm FFmpeg, a wasm AVIF encoder, `@huggingface/transformers` and Prisma is a large client bundle, and the `next build --webpack` pin hints at the build being a consideration rather than a non-issue.

The fourth is a team with a compliance requirement. The editor keeps no account, which is good, but the optional tiers need a PostgreSQL database and object storage credentials, and a self-hosted deployment of a Next.js app with a database and a bucket is a system to operate and secure.

A practical note on the fork path. This is a young project at version 0.1.0 in the manifest, with no GitHub releases, so the history of what changed is in the commit log rather than in tags. Before you base work on it, read `ARCHITECTURE.md` and the `lib/screenshot-cache.ts` configuration, because those two files tell you where the boundaries between the browser editor, the data layer and the cache actually sit, and that is the first thing you will need to change.

Editorial conclusion

Screenshot Studio fits a team that needs a screenshot or app-store asset tool it can run itself, with no account, no watermark and no third-party upload of its marketing material. It does not fit someone who wants a design tool with layers of arbitrary type and vector editing, since the feature set is centred on compositing images, frames, text and annotations. Before you deploy it, read `ARCHITECTURE.md` and decide about the two pieces of infrastructure the project keeps optional, PostgreSQL for the Prisma data layer and R2 for the server-side screenshot cache, since the editor itself runs without a database but the build does not.

Frequently asked questions

How do I run Screenshot Studio locally?

It requires Node.js 20.9 or newer and npm. Clone the repository, run `npm ci`, write a `DATABASE_URL` for PostgreSQL into `.env`, then run `npm run dev` and open localhost:3000. The editor itself needs no running database, but Prisma requires the variable during startup and builds.

What can Screenshot Studio create?

Screenshot designs with backgrounds, browser and device frames, shadows and 3D perspective; text-only graphics with fonts such as Inter and Geist; layered compositions with text, images, annotations and blur regions; store and social assets with exact export sizes including Chrome Web Store screenshots; and exports as PNG, JPEG, WebP, batch ZIP, MP4, WebM and GIF.

What is Screenshot Studio built with?

Next.js, React, TypeScript, Tailwind CSS and Zustand, with shadcn/ui and Radix for the interface, React Three Fiber for 3D, wasm FFmpeg for video exports, Prisma with PostgreSQL for the data layer, and the AWS SDK for R2 object storage.

Does Screenshot Studio need a database or object storage?

The browser editor needs no running database, but `DATABASE_URL` is required by Prisma during startup and builds. Server-side screenshot caching additionally requires PostgreSQL and R2 credentials, configured in `lib/screenshot-cache.ts`.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. opennookorg/screenshot-studio on GitHub
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/opennookorg-screenshot-studio.svg)](https://hysenlabs.com/projects/opennookorg-screenshot-studio)

Was this useful?