# Contributing to Amytis ## Getting Started 1. **Install Bun:** Ensure you have [Bun](https://bun.sh/) (1.3.4+) installed. 2. **Install Dependencies:** ```bash bun install ``` 3. **Run Development Server:** ```bash bun dev ``` Open [http://localhost:3000](http://localhost:3000). > **Search in dev:** The search index is generated by `pagefind` at build time. Run `bun run build:dev` once to generate `public/pagefind/`. After that, the search modal (Cmd/Ctrl+K) will work while `bun dev` is running. Re-run `bun run build:dev` whenever content changes. ## Writing Content For code-block features (line numbers, line highlighting, title bars, diff backgrounds, word-wrap toggle, notation comments, tabbed groups) and the per-format fence/directive syntax, see [`docs/CODE-BLOCKS.md`](./CODE-BLOCKS.md). For GitHub-flavored alert callouts (`> [!NOTE]`, `.. note::`, etc.) and the five supported alert types, see [`docs/ALERTS.md`](./ALERTS.md). Markdown links to other hosts (anything whose host differs from `siteConfig.baseUrl`) automatically render with a trailing `↗` icon and open in a new tab — don't write `` manually. Internal links, wikilinks, `mailto:`, and `tel:` are unaffected. ### Creating Posts Use the CLI to scaffold new content: ```bash # Create a flat file post bun run new "My New Post" # Create as a folder with index.mdx bun run new "Photography" --folder # Create post in a series bun run new "Getting Started" --series my-series # Create from a named template bun run new "My Review" --template default ``` Post scaffolds come from the `templates/` directory: `--template ` picks `templates/.mdx` (or `templates/.md` with `--md`, falling back to the `.mdx` variant). Without the flag, `templates/default.mdx` is used. Add your own `templates/.mdx` to create reusable frontmatter/body scaffolds; if no template file exists, the script falls back to a minimal built-in one. ### Creating Flows (Daily Notes) Flows are organized by date (`content/flows/YYYY/MM/DD.mdx`). ```bash # Create a new flow entry for today bun run new-flow ``` ### Creating Series ```bash bun run new-series "My Series Name" ``` Series are format-scoped: - Markdown series use `content/series//index.mdx` or `index.md` - Markdown series may also use `README.mdx` or `README.md` - rST series use `content/series//index.rst` or `README.rst` - Child posts inside the series must use the same format as the index file - Mixed Markdown and rST files in one series are treated as build errors - For full-fidelity rST rendering, install `docutils` (and `pygments` for code highlighting) in a Python environment available to the project - If needed, set `AMYTIS_RST_PYTHON=/absolute/path/to/python` so Amytis uses a specific interpreter - Without Python/docutils, Amytis falls back to a lightweight compatibility parser; that keeps loading/building working, but some legacy rST constructs will render with lower fidelity ### Creating Books Books are manually structured in `content/books/`. 1. Create a folder: `content/books/my-book/` 2. Add `index.mdx` with metadata and chapters configuration. 3. Create the chapter files (`welcome.mdx`, `conclusion.mdx`) in the same folder. ### Creating Notes (Digital Garden) Notes live in `content/notes/`. ```bash # Create a new note using the dedicated script bun run new-note "Zettelkasten Method" ``` ### Importing Content ```bash # PDF to post bun run new-from-pdf doc.pdf --title "My Doc" # Image folder to post bun run new-from-images ./photos --title "Gallery" # Chat logs to flows bun run new-flow-from-chat # VuePress 2 book → Amytis book directory. # Full walkthrough at docs/guides/importing-vuepress-books.md. bun run sync-vuepress-book --source /path/to/dmla/docs --dest content/books/dmla ``` ### Maintenance Tools ```bash # Sync book chapters with files in the folder bun run sync-book bun run sync-book # one book only # Bulk draft/publish a series bun run series-draft "my-series" bun run series-draft "my-series" --undraft # Add redirectFrom to series posts (for autoPaths / path migrations) bun run add-series-redirects # all series bun run add-series-redirects # one series only bun run add-series-redirects --dry-run # preview without writing # Reset build caches (when copy-assets or the image optimizer misbehave) bun run clean # removes .next, out, public/posts ``` ## Running Tests ```bash bun run test # Run all tests (NOT bare `bun test` — that sweeps in Playwright specs and fails) bun run typecheck # Type-check the repo with tsc --noEmit bun run test:unit # Run unit tests bun run test:int # Run integration tests bun run test:dom # Run DOM behavior tests (happy-dom + React Testing Library, tests/dom/) bun run test:e2e # Run end-to-end specs (need the site served at http://localhost:3000) bun run test:mobile # Run Playwright mobile compatibility tests bun run validate # Lint + typecheck + test + build:dev ``` The `test:e2e` specs fetch `http://localhost:3000` and skip when nothing responds, so serve a build first — e.g. `bun run build:dev && bunx serve out -l 3000` in one terminal, then `bun run test:e2e` in another. CI (`.github/workflows/ci.yml`) does this automatically after the build, and fails if the server doesn't come up. CI also runs `bun run typecheck`; the full production build (`bun run build`) is a manual `workflow_dispatch` job. `tests/dom/` holds client-behavior tests (state, events, keyboard interaction). They run with happy-dom registered via `--preload ./tests/dom/setup.ts` — only through `bun run test:dom`, so the DOM globals never leak into the SSR-oriented suites. Off the PR loop, CI also runs a Windows production build (npm-install path) and the Playwright mobile matrix on main pushes, manual dispatch, and a weekly schedule. ### Mobile Compatibility Tests `bun run test:mobile` uses [Playwright](https://playwright.dev/) to test the site across 17 real-device profiles: - **Apple:** iPhone SE, iPhone 14 Pro, iPhone 14 Pro Max, iPad Mini, iPad Pro 11 - **Google:** Pixel 5, Pixel 7 - **Samsung:** Galaxy S8, Galaxy S21 - **Huawei:** P50 Pro, Mate 60 - **Xiaomi:** Xiaomi 14, Redmi Note 13 - **Oppo:** Find X7, Reno 11 - **Vivo:** X100, Y100 **First-time setup** — install the browser binaries once: ```bash bunx playwright install chromium webkit ``` The test server starts automatically (`bun dev`) if one is not already running. Useful commands: ```bash bunx playwright test --project="iPhone SE" # Run one device bunx playwright test --project="iPhone SE" --headed # Headed (visible) browser bunx playwright show-report # Open HTML report ``` Tests cover: no horizontal overflow, navigation (hamburger on phones, desktop nav on tablets), mobile menu open/close, touch target sizing (≥44px), post sidebar visibility, scroll lock, font sizes, and image overflow. ## Building ```bash bun run build # Production build (includes image optimization and Pagefind index) bun run build:dev # Development build (faster, no image optimization; also generates Pagefind index) ``` ## Static Export Routing Rules Amytis relies on static export (`output: "export"`) with `trailingSlash: true`. - In `generateStaticParams()`, return raw segment values and let Next.js handle encoding. - Do not pre-encode route params with `encodeURIComponent`. - Do not link to placeholder routes such as `/posts/[slug]`; always link to concrete URLs. - When touching dynamic routes, verify both ASCII and Unicode slugs (decode params via `src/lib/route-params.ts`, never bare `decodeURIComponent`). - Alias/static-params logic for `[slug]`, `[slug]/[postSlug]`, and series redirects lives in `src/lib/route-aliases.ts` — routes are thin adapters over its providers and resolvers; don't reimplement collision checks in route files. - Paginated routes compute page math via `paginate()` / `paginationStaticParams()` from `src/lib/pagination.ts`. Keep `generateStaticParams` / `generateMetadata` / the page component as literal exports in each route file — Next.js statically analyzes them, so no route factories. ## Code Style - **Linting:** `bun run lint` - **TypeScript:** Use strict types. - **Tailwind:** Use utility classes. - **Localization:** Use `t()` helper for UI strings.