diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index dd62f76..6da0a63 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,8 +14,10 @@ staging: stage: deploy image: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_BRANCH} script: - - echo "Building the project with Quarto..." + - echo "Building the main website with Quarto..." - quarto render --to html --output-dir public + - echo "Building Ghost-optimized version..." + - quarto render --profile ghost --to html --output-dir public/ghost-content artifacts: paths: - public diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..a5608b3 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,80 @@ +# Agent Instructions for Anson's Projects + +This repository contains a multi-language technical blog with Rust automation tools, Julia data analysis notebooks, and Quarto documentation. + +## Build/Lint/Test Commands + +### Rust (ghost-upload/) +- **Build**: `cd ghost-upload && cargo build` +- **Run**: `cd ghost-upload && cargo run` +- **Test**: `cd ghost-upload && cargo test` +- **Lint**: `cd ghost-upload && cargo clippy` +- **Format**: `cd ghost-upload && cargo fmt` +- **Single test**: `cd ghost-upload && cargo test ` + +### Julia (posts/*/ and root) +- **Run notebook**: `julia .jl` +- **Package management**: `julia -e "using Pkg; Pkg.instantiate()"` +- **Precompile**: `julia -e "using Pkg; Pkg.precompile()"` + +### Quarto (Documentation) +- **Build site**: `quarto render --to html --output-dir public` +- **Preview**: `quarto preview` +- **Check**: `quarto check` + +### Docker +- **Build**: `docker build -t projects .` +- **Run**: `docker run projects` + +## Code Style Guidelines + +### Rust +- **Formatting**: Use `cargo fmt` (4-space indentation, standard Rust style) +- **Linting**: Use `cargo clippy` and fix all warnings +- **Imports**: Group by standard library, external crates, then local modules +- **Error Handling**: Prefer `?` operator over `unwrap()`, use custom error types for complex cases +- **Naming**: snake_case for functions/variables, PascalCase for structs/enums +- **Documentation**: Use `///` for public APIs, `//` for implementation details +- **Async**: Use `async fn` for async functions, avoid blocking operations in async contexts + +### Julia +- **Formatting**: 4-space indentation, spaces around operators +- **Imports**: Use `using` for packages, group at top of file +- **Naming**: snake_case for functions and variables +- **Types**: Use descriptive names, consider performance implications +- **Plotting**: Use Plots.jl with consistent themes (e.g., `theme(:ggplot2)`) +- **DataFrames**: Use pipe operators `|>` for data transformations +- **Error Handling**: Use try-catch blocks for expected errors + +### Quarto (.qmd files) +- **YAML frontmatter**: Include title, date, and relevant metadata +- **Code chunks**: Use appropriate language engines (`{rust}`, `{julia}`, `{python}`) +- **Output**: Set `echo: false` for clean output, `warning: false` to suppress warnings +- **Figures**: Use descriptive captions and alt text +- **Citations**: Use `@citekey` format with bibliography files + +### General +- **Git**: Write clear commit messages, use conventional commits when possible +- **Documentation**: Update README.md for significant changes +- **Dependencies**: Keep dependencies minimal and up-to-date +- **Security**: Never commit API keys or sensitive credentials +- **Performance**: Profile code before optimizing, focus on readability first + +## Project Structure +- `ghost-upload/`: Rust automation for blog post publishing +- `posts/`: Individual blog posts (Quarto markdown + Julia/Python code) +- Root: Quarto website configuration and shared assets + +## Environment Variables +- `kagi_api_key`: For Kagi API summarization (Rust) +- `admin_api_key`: For Ghost CMS API (Rust) + +## Testing Strategy +- **Rust**: Unit tests for core functionality, integration tests for API interactions +- **Julia**: Visual validation of plots and data transformations +- **Quarto**: Manual review of rendered output and links + +## Deployment +- Uses GitLab CI/CD with Docker +- Deploys to static hosting after Quarto build +- Rust component runs separately for content synchronization \ No newline at end of file diff --git a/_quarto.yml b/_quarto.yml index 330911d..41f3e48 100644 --- a/_quarto.yml +++ b/_quarto.yml @@ -1,25 +1,42 @@ project: type: website -website: - title: "Anson's Projects" - site-url: https://projects.ansonbiggs.com - description: A Blog for Technical Topics - navbar: - left: - - text: "About" - href: about.html - right: - - icon: rss - href: index.xml - # - icon: gitlab - # href: https://gitlab.com/MisterBiggs - open-graph: true -format: - html: - theme: zephyr - css: styles.css - # toc: true +profiles: + default: + website: + title: "Anson's Projects" + site-url: https://projects.ansonbiggs.com + description: A Blog for Technical Topics + navbar: + left: + - text: "About" + href: about.html + right: + - icon: rss + href: index.xml + # - icon: gitlab + # href: https://gitlab.com/MisterBiggs + open-graph: true + format: + html: + theme: zephyr + css: styles.css + # toc: true + + ghost: + website: + title: "Anson's Projects" + site-url: https://projects.ansonbiggs.com + description: A Blog for Technical Topics + navbar: false + open-graph: true + format: + html: + theme: none + css: ghost-iframe.css + toc: false + page-layout: article + title-block-banner: false execute: freeze: true \ No newline at end of file diff --git a/ghost-iframe.css b/ghost-iframe.css new file mode 100644 index 0000000..2d4cd10 --- /dev/null +++ b/ghost-iframe.css @@ -0,0 +1,129 @@ +/* Ghost iframe optimized styles */ +body { + font-family: system-ui, -apple-system, sans-serif; + line-height: 1.6; + color: #333; + max-width: 100%; + margin: 0; + padding: 20px; + background: white; +} + +/* Remove any potential margins/padding */ +html, body { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +/* Ensure content flows naturally */ +#quarto-content { + max-width: none; + padding: 0; + margin: 0; +} + +/* Style headings for Ghost */ +h1, h2, h3, h4, h5, h6 { + margin-top: 1.5em; + margin-bottom: 0.5em; + font-weight: 600; + line-height: 1.3; +} + +h1 { font-size: 2em; } +h2 { font-size: 1.5em; } +h3 { font-size: 1.25em; } + +/* Code blocks */ +pre { + background: #f8f9fa; + border: 1px solid #e9ecef; + border-radius: 6px; + padding: 1rem; + overflow-x: auto; + font-size: 0.875em; +} + +code { + font-family: "SF Mono", Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace; + background: #f1f3f4; + padding: 0.2em 0.4em; + border-radius: 3px; + font-size: 0.875em; +} + +pre code { + background: none; + padding: 0; +} + +/* Images */ +img { + max-width: 100%; + height: auto; + border-radius: 4px; +} + +/* Tables */ +table { + border-collapse: collapse; + width: 100%; + margin: 1em 0; +} + +th, td { + border: 1px solid #ddd; + padding: 8px; + text-align: left; +} + +th { + background-color: #f2f2f2; + font-weight: 600; +} + +/* Links */ +a { + color: #0066cc; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +/* Blockquotes */ +blockquote { + border-left: 4px solid #ddd; + margin: 1em 0; + padding-left: 1em; + color: #666; + font-style: italic; +} + +/* Lists */ +ul, ol { + padding-left: 1.5em; +} + +li { + margin-bottom: 0.25em; +} + +/* Remove any navbar/footer elements that might leak through */ +.navbar, .nav, footer, .sidebar, .toc, .page-footer { + display: none !important; +} + +/* Ensure responsive behavior for iframe */ +@media (max-width: 768px) { + body { + padding: 15px; + font-size: 16px; + } + + h1 { font-size: 1.75em; } + h2 { font-size: 1.35em; } + h3 { font-size: 1.15em; } +} \ No newline at end of file