My Carrd website
  • TypeScript 95.8%
  • CSS 4%
  • Dockerfile 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-28 09:17:17 +02:00
data Initial import 2026-09-27 07:52:28 +02:00
prisma Initial import 2026-09-27 07:52:28 +02:00
public Initial import 2026-09-27 07:52:28 +02:00
scripts Initial import 2026-09-27 07:52:28 +02:00
src Fixed serveral bugs with the background slideshow and added image optimization button under the file browser 2026-09-28 09:17:17 +02:00
.dockerignore Initial import 2026-09-27 07:52:28 +02:00
.env.example Initial import 2026-09-27 07:52:28 +02:00
.gitignore Initial import 2026-09-27 07:52:28 +02:00
docker-compose.yml Initial import 2026-09-27 07:52:28 +02:00
Dockerfile Initial import 2026-09-27 07:52:28 +02:00
eslint.config.mjs Initial import 2026-09-27 07:52:28 +02:00
next.config.ts Initial import 2026-09-27 07:52:28 +02:00
package-lock.json Initial import 2026-09-27 07:52:28 +02:00
package.json Initial import 2026-09-27 07:52:28 +02:00
postcss.config.mjs Initial import 2026-09-27 07:52:28 +02:00
prisma.config.ts Initial import 2026-09-27 07:52:28 +02:00
README.md Fixed serveral bugs with the background slideshow and added image optimization button under the file browser 2026-09-28 09:17:17 +02:00
tailwind.config.ts Initial import 2026-09-27 07:52:28 +02:00
tsconfig.json Initial import 2026-09-27 07:52:28 +02:00

Partner Carrd

A self-hosted portfolio, link-in-bio, and lightweight storefront builder.

Partner Carrd is a full-stack website builder for creators who want a polished online presence without depending on a hosted site-building platform. It combines a block-based visual editor with a fast public site, first-party analytics, managed media, version history, backups, and optional Stripe Checkout.

The project is built as a single-site, single-admin application. It is a strong fit for a personal portfolio, creator hub, campaign page, or small merchandise storefront that you want to own and operate yourself.

This is an independent project inspired by the simplicity of one-page website builders. It is not affiliated with Carrd.

What it does

From one private admin workspace, you can compose and publish a responsive website without editing source code:

  • Build pages from hero, links, text, gallery, portfolio, contact, merchandise, and custom sections
  • Reorder sections with drag and drop and start quickly from section templates
  • Control colors, typography, spacing, cards, navigation, backgrounds, and intro effects
  • Upload images through a managed pipeline that creates WebP display, preview, thumbnail, and hero variants
  • Create dedicated portfolio case-study pages at /portfolio/[slug]
  • Schedule links, target them by device or country, and configure A/B variants
  • Manage SEO metadata, social previews, the favicon, and footer content
  • Track privacy-minded first-party analytics without a third-party analytics account
  • Restore prior content versions and create, download, or restore SQLite backups
  • Sell merchandise through optional hosted Stripe Checkout and manage order fulfillment

Project scope

Partner Carrd deliberately favors a focused, maintainable architecture over becoming a general-purpose website platform.

In scope Out of scope
One public website and one admin workspace Multi-tenant accounts or customer workspaces
Creator portfolios, link hubs, and small storefronts A general-purpose CMS or page builder
Self-hosting on a single persistent instance Serverless deployments with ephemeral storage
Local SQLite data, uploads, history, and backups Horizontally scaled database and object storage
Optional Stripe-hosted checkout Inventory, shipping, tax, or marketplace management
First-party traffic and conversion analytics Enterprise analytics or behavioral replay

This scope keeps the application straightforward to deploy, inspect, customize, and back up. For higher traffic or multiple application replicas, SQLite and filesystem storage should be replaced with shared production services.

Technical highlights

  • Next.js App Router powers the public site, admin workspace, and API routes in one application.
  • Typed content model and Zod validation protect saved and imported site data.
  • Prisma + SQLite provide a portable data layer with committed migrations.
  • Server-side image processing uses Sharp to validate uploads, strip metadata, and generate optimized variants.
  • Content recovery includes the newest 30 editor snapshots plus independent full-database backups.
  • Security controls include hashed passwords and sessions, login throttling, same-origin checks, upload validation, path and URL sanitization, restrictive headers, and session revocation after password changes.
  • First-party analytics stores page views, outbound clicks, referral hosts, approximate unique visitors, location, device, browser, section activity, and store conversions locally.

Technology

Layer Technology
Framework Next.js 16, React 19
Language TypeScript
Styling Tailwind CSS 4
Database SQLite, Prisma ORM 6
Validation Zod
Authentication Cookie sessions, bcrypt
Media Sharp
Payments Stripe Checkout (optional)

Getting started

Prerequisites

  • Node.js 20 or newer
  • npm

1. Install the project

git clone <your-repository-url>
cd my-carrd
npm install

2. Create the environment file

On macOS or Linux:

cp .env.example .env

On PowerShell:

Copy-Item .env.example .env

The npm development and production scripts run the app on port 3001. Update the three URL values in .env accordingly:

APP_ORIGIN="http://localhost:3001"
NEXT_PUBLIC_SITE_URL="http://localhost:3001"
NEXT_PUBLIC_APP_URL="http://localhost:3001"

Before seeding, replace the default admin password:

SEED_ADMIN_USERNAME="admin"
SEED_ADMIN_PASSWORD="use-a-long-unique-password"
ANALYTICS_SALT="use-a-long-random-value"

Do not commit .env; it contains secrets and is already ignored by Git.

3. Initialize the database

npm run setup

This command generates the Prisma client, applies the schema to SQLite, creates or updates the admin account, and adds starter content when the site is empty. Existing content is preserved unless SEED_OVERWRITE_CONTENT is set to true.

4. Start the application

npm run dev

Open the public site at http://localhost:3001 and the editor at http://localhost:3001/admin.

Environment configuration

The defaults and optional seed settings live in .env.example.

Variable Required Purpose
DATABASE_URL Yes SQLite datasource used by Prisma. The provided relative path is resolved beneath prisma/.
APP_ORIGIN Production Trusted origin for protected write requests and checkout redirects.
NEXT_PUBLIC_SITE_URL Recommended Canonical public URL used for metadata and links.
NEXT_PUBLIC_APP_URL Recommended Public application URL and fallback trusted origin.
ADMIN_COOKIE_NAME No Admin session cookie name. Defaults to pc_admin.
ADMIN_COOKIE_TTL_DAYS No Admin session lifetime in days.
ADMIN_LOGIN_WINDOW_MS No Time window used for login throttling.
ADMIN_LOGIN_MAX_ATTEMPTS No Failed attempts allowed within the login window.
ADMIN_LOGIN_BLOCK_MS No Lockout duration after the limit is reached.
ANALYTICS_SALT Yes Private salt used to derive privacy-minded visitor hashes.
ANALYTICS_RETENTION_DAYS No Analytics retention period; defaults to 365 days.
DATABASE_BACKUP_RETENTION No Number of SQLite backups to retain; defaults to 20.

The SEED_* variables customize the initial admin account and starter page. The seed script accepts additional values for metadata, hero copy, about copy, and the two starter links; see scripts/seed.ts for the complete set.

In production, the seed script refuses to use the example password change-me-now.

Available commands

Command Description
npm run dev Start the development server on port 3001
npm run build Create a production build
npm start Start the production server on port 3001
npm run lint Run ESLint
npm run setup Generate Prisma, sync the schema, and seed the site
npm run seed Create/update the admin user and seed missing content
npm run db:push Sync the Prisma schema without creating a migration
npm run backup Create and validate a SQLite snapshot
npm run maintenance Prune expired records and create a scheduled backup

For a migration-based production deployment, apply committed migrations with:

npx prisma generate
npx prisma migrate deploy
npm run build
npm start

Docker

The repository includes a multi-stage Dockerfile and a Compose configuration with persistent mounts for uploads, Prisma data, and site history.

The application process listens on port 3001. When running the current image, publish the container's port 3001 and set the public URLs to the host-facing address. For example, the Compose port mapping should be 3000:3001 when the site should be available at http://localhost:3000.

After aligning that mapping and creating .env:

docker compose up --build -d

The container syncs the Prisma schema when it starts. Seed a new instance once with:

docker compose exec carrd-clone npm run seed

For production, use a unique admin password and analytics salt, set all public URL variables to the real HTTPS origin, and keep the mounted directories on persistent storage.

Stripe checkout

Stripe is optional; the rest of the application works without it.

  1. Open Admin → Payments and enter the Stripe publishable key, secret key, and webhook signing secret.
  2. Enable Stripe and choose the store currency.
  3. Add a Stripe Price ID to each merchandise item that should be purchasable.
  4. Register https://your-domain.example/api/store/webhook as a Stripe webhook endpoint.

Checkout uses Stripe's hosted payment page. Completed sessions are recorded as orders and can be reviewed and marked fulfilled in the admin workspace. Secret values remain server-side and are not returned to the browser after saving.

Data, recovery, and maintenance

Persistent application state is stored in four places:

Path Contents
.env Deployment configuration and secrets
prisma/ SQLite database, migrations, and private database backups
public/uploads/ Original uploads and generated image variants
data/ Content version history

For a complete instance backup, preserve all four locations. Editor history is useful for rolling back content mistakes, but it does not replace a full backup of the database, uploads, and secrets.

You can create and restore database snapshots from Admin → Site settings → Backups. The restore flow verifies SQLite integrity and migration compatibility and creates a recovery snapshot before replacing the live database.

For long-running deployments, schedule:

npm run maintenance

It removes expired sessions, stale login-attempt records, and analytics events older than the configured retention period, then creates a validated database backup.

Project structure

my-carrd/
├── prisma/
│   ├── migrations/        # Committed database migrations
│   └── schema.prisma      # Application data model
├── public/uploads/        # Persistent managed media
├── scripts/
│   ├── backup.ts          # Manual backup command
│   ├── maintenance.ts     # Retention and scheduled backup tasks
│   └── seed.ts            # Admin and starter-content seed
└── src/
    ├── app/               # Pages, layouts, and API routes
    ├── components/
    │   ├── admin/         # Editor, panels, analytics, and order UI
    │   └── site/          # Public site renderer and portfolio pages
    ├── hooks/             # Site-builder state and client hooks
    ├── lib/               # Auth, data, media, analytics, and validation
    ├── presets/           # Theme presets
    ├── templates/         # Section templates
    └── types/             # Shared TypeScript models

Production checklist

  • Use unique values for SEED_ADMIN_PASSWORD and ANALYTICS_SALT
  • Set APP_ORIGIN, NEXT_PUBLIC_SITE_URL, and NEXT_PUBLIC_APP_URL to the HTTPS production origin
  • Put the application behind a TLS-enabled reverse proxy
  • Persist .env, prisma/, public/uploads/, and data/
  • Run npx prisma migrate deploy during releases
  • Schedule npm run maintenance
  • Test database restores and off-site backups before relying on them
  • Configure and verify the Stripe webhook if payments are enabled

Why I built it

Partner Carrd explores what sits behind a deceptively simple creator website: flexible content modeling, a usable visual editor, secure authentication, upload processing, recoverable persistence, privacy-conscious analytics, and a payment workflow. The result is intentionally small enough to self-host while still demonstrating the engineering concerns of a real, stateful product.


Built with Next.js, TypeScript, Prisma, and a strong preference for owning your content.