- TypeScript 99.1%
- Shell 0.6%
- Makefile 0.1%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| .pi/skills/web-release | ||
| docs | ||
| e2e | ||
| scripts | ||
| src | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| .slugkit-site.json | ||
| docker-compose.yml | ||
| Dockerfile | ||
| eslint.config.js | ||
| garage.toml | ||
| Makefile | ||
| package-lock.json | ||
| package.json | ||
| playwright.config.ts | ||
| Procfile.dev | ||
| README.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
Erik Van Craddock
This is a standalone Slugkit-compatible website generated from the Slugkit source template. You own this repository and can customize its routes, templates, styles, assets, content model, and deployment while retaining the Slugkit API contract when you want to use the slug CLI.
Required first-run setup
Run these steps from this generated repository. The site remains private until you complete the owner setup flow.
1. Install dependencies
npm install
2. Configure the environment
cp .env.example .env
For local development, edit .env and set ADMIN_EMAIL to the owner email. Keep AUTH_DEV_MODE=true so sign-in links are written to the app logs. The included defaults use a local SQLite database, localhost URLs, and a local Garage container.
3. Initialize the database
npm run db:migrate
npm run db:status
4. Start local services
Install Overmind and Docker if needed, then start the app, Tailwind watcher, and local Garage container defined in Procfile.dev:
make dev
make dev-status
Configure the local media bucket after Garage starts, then restart the environment so the app loads the generated credentials:
make garage-setup
make dev-stop
make dev
Use make dev-logs to open the process logs. The site runs at http://localhost:3000 by default. Set APP_PORT in .env to use a different local port; the development process preserves that value.
5. Complete owner and actor setup
Open http://localhost:3000/login and sign in with ADMIN_EMAIL. With AUTH_DEV_MODE=true, copy the magic link from the app output available through make dev-logs.
Open http://localhost:3000/setup. Set the public site identity and create the primary actor. Choose the actor username carefully because it becomes part of public actor URLs and is difficult to change after federation begins. Completing this explicit first-run setup creates the actor and signing keys and makes the public site available.
6. Connect the Slugkit CLI
Use a clear local name for this target. The examples below use erikvancraddock.com, matching the generated package name.
slug --site erikvancraddock.com login http://localhost:3000/api/v1
slug --site erikvancraddock.com doctor
The browser-assisted login creates an API key for the named site. Every API-backed example below includes --site erikvancraddock.com so the target is explicit.
7. Verify the site
Open the following URLs and confirm that setup is complete:
http://localhost:3000/http://localhost:3000/feedhttp://localhost:3000/api/v1/healthhttp://localhost:3000/settings/actor
Run the local checks before changing or deploying the site:
npm run format
npm run lint
npm test
npm run build
Publish your first post with the CLI
Create an article. post create saves a draft; it does not publish automatically.
slug --site erikvancraddock.com post create \
--type article \
--slug hello-world \
--title "Hello world" \
--content "This is my first post."
Inspect the draft and confirm that its content and target site are correct:
slug --site erikvancraddock.com post show hello-world
Publish only after reviewing the draft:
slug --site erikvancraddock.com post publish hello-world
slug --site erikvancraddock.com post show hello-world
Publish your first post from Markdown
Create content/imported-hello.md with YAML frontmatter. slug, type, and—for an article—title are required. Omit date and publishedAt when you want the import to remain a new draft.
---
title: Imported hello
slug: imported-hello
type: article
excerpt: A first post imported from Markdown
tags:
- introduction
---
This post started in a Markdown file.
Import the file into the explicitly named site. The import creates or updates a draft when no publication date is supplied.
slug --site erikvancraddock.com post import ./content/imported-hello.md
Inspect the imported draft before publishing it:
slug --site erikvancraddock.com post show imported-hello
Publish explicitly, then inspect the published result:
slug --site erikvancraddock.com post publish imported-hello
slug --site erikvancraddock.com post show imported-hello
Both creation methods leave the post as a draft until the explicit post publish command succeeds.
Customize the site
This repository is intended to be changed. Start with:
src/config/site.tsfor fallback site identity, homepage copy, navigation, and footer links./settingsfor persisted site configuration./settings/actorfor actor profile details and images.src/templates/andsrc/styles/for public layout and styling.src/assets/for public images.src/routes/andsrc/api/for site-owned behavior.
The API documentation for a running site is available at /api/v1/docs.
Optional federation setup
Federation is not required for local use or ordinary publishing. Leave ACTIVITYPUB_ENABLED=false until the site has a stable public HTTPS origin and the actor identity is final.
Before enabling federation:
- Set the persisted site URL to the stable public HTTPS origin.
- Set
ACTIVITYPUB_PUBLIC_ORIGINwhen it must differ from the site URL. - Confirm the primary actor username, display metadata, and signing keys in
/settings/actor. - Set
ACTIVITYPUB_ENABLED=trueonly in the deployed environment. - Verify WebFinger, the actor URL, and
slug --site erikvancraddock.com doctorafter deployment.
Deployment checklist
Deployment is optional during first-run setup. Before making the site public:
- Replace localhost site and ActivityPub URLs with the stable public HTTPS origin.
- Set
AUTH_DEV_MODE=falseand configure SMTP for magic-link delivery. - Use persistent storage for
DATABASE_PATH=/app/data/slugkit.sqliteand include migrations in the release process. - Configure durable S3-compatible media storage with
S3_ENDPOINT,S3_BUCKET, credentials, andS3_PUBLIC_URL. - Store secrets in the deployment environment or secret manager, never in the image or repository.
- Run
npm run format,npm run lint,npm test, andnpm run build. - Back up the database and media storage.
Docker deployment
The included Dockerfile builds the CSS and application, installs production dependencies, exposes port 3000, and runs npm start.
docker build --build-arg APP_VERSION=local -t erikvancraddock.com:local .
docker run --rm -p 3000:3000 \
--env-file .env \
-e DATABASE_PATH=/app/data/slugkit.sqlite \
-v erikvancraddock.com-data:/app/data \
erikvancraddock.com:local
Run migrations against the same persistent volume before starting a new deployment or after updating the image. APP_VERSION is exposed as SLUGKIT_VERSION in the image so /health and /api/v1/health report the deployed version.
Publish a web release with Forgejo Actions
The publishing workflow at .forgejo/workflows/web-release.yml runs on the remote Debian CI runner and publishes evcraddock/erikvancraddock-web for linux/amd64 and linux/arm64 only for approved web-v* tags. Manual dispatch validates the remote Docker build with publishing disabled. Use /skill:web-release <version> to run the project release gates and request explicit approval before pushing a web-v<version> tag.
See docs/web-release.md for versioning, image tags, required repository secrets, and non-publishing validation.
Environment reference
The complete local defaults are documented in .env.example.
Required for local ownership and login:
DATABASE_PATHADMIN_EMAILAUTH_DEV_MODE
Optional runtime settings:
APP_PORTcontrols the application port and defaults to3000when unset.APP_HOSTcontrols the bind host and defaults to0.0.0.0when unset.
Required in production when AUTH_DEV_MODE=false:
SMTP_HOST,SMTP_PORT,SMTP_SECURE, andSMTP_FROM_EMAILSMTP_USERNAMEandSMTP_PASSWORDwhen required by the provider
Optional media settings include S3_ENDPOINT, S3_REGION, S3_BUCKET, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_FORCE_PATH_STYLE, and S3_PUBLIC_URL.
Optional federation settings include ACTIVITYPUB_ENABLED and ACTIVITYPUB_PUBLIC_ORIGIN.
Useful commands
make dev
make dev-status
make dev-logs
make dev-stop
make garage-setup
npm run db:migrate
npm run db:status
npm run format
npm run lint
npm test
npm run build