diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cd1597c..8377c5f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,35 +1,102 @@ # Contributing to ConfigDev -First off, thank you for considering contributing to ConfigDev! +Thank you for your interest in contributing. ConfigDev is a local-first tool suite β€” every contribution must preserve the core guarantee: no user data ever leaves the browser. -Since our primary focus is providing completely secure, local-first environments for developers, we value bug reports, security audits, and feature requests immensely. +--- -## πŸ› Reporting Bugs +## Core Rule -If you find a bug, a regex false-positive in our PII scrubber, or a UI issue, please open an issue in our repository. +No tool may make any outbound network request after the page has loaded. All processing must use browser-native APIs only. If a proposed feature requires a server call, it does not fit this project's architecture. -**When reporting a bug, please include:** -1. A clear and descriptive title. -2. The exact steps to reproduce the issue. -3. What you expected to happen vs what actually happened. -4. If applicable, the browser and OS you are using. +--- -*Note: Please **do not** include actual sensitive logs or real PII in your bug reports. Always use dummy data!* +## Reporting Bugs -## πŸ’‘ Suggesting Features +Open an issue and include: -We love new ideas for local-first developer tools! If you have a suggestion: -1. Check existing issues to see if it has already been suggested. -2. Open a new issue with the label `enhancement`. -3. Describe the problem your tool would solve and how it fits into the "Local-First, Privacy-First" philosophy. +1. A clear title describing the problem +2. Steps to reproduce +3. What you expected vs. what happened +4. Your browser and OS -## πŸ› οΈ Pull Requests +When reporting issues with specific tools (e.g. a regex false-positive in the PII scrubber, a Base64 edge case in the K8s sanitizer), include a minimal reproduction input using dummy data. Do not paste real secrets, logs, or PII into issue reports. -While we might not be accepting large feature pull requests from the community just yet, if you spot a typo or a minor bug fix, feel free to open a PR! +--- -1. Fork the repo. -2. Create a new branch (`git checkout -b fix/your-fix`). -3. Make your changes (ensure they do not violate the local-first ruleβ€”no external API calls!). -4. Push to your branch and submit a Pull Request. +## Suggesting New Tools -Thank you for helping keep developers secure! +A good candidate tool for ConfigDev: + +- Solves a real, recurring DevOps or infrastructure problem +- Can be implemented entirely in the browser using standard APIs +- Produces a deterministic output from a given input (no randomness, no external dependencies) +- Is not a thin wrapper around an existing browser feature + +To suggest a tool, open an issue with the label `enhancement` and describe the problem the tool solves, the expected input/output format, and how it fits the local-first constraint. + +--- + +## Pull Requests + +For bug fixes and minor improvements: + +1. Fork the repository +2. Create a branch: `git checkout -b fix/your-fix-description` +3. Make your changes +4. Run `npm run lint` β€” must pass with zero errors +5. Run `npm run build` β€” must complete successfully +6. Push and open a pull request against `main` + +For new tools or significant features, open an issue first to discuss the approach before writing code. + +### Branch naming + +| Type | Pattern | Example | +|---|---|---| +| New tool | `feature/tool-name` | `feature/jwt-decoder` | +| Bug fix | `fix/description` | `fix/cidr-broadcast-edge-case` | +| Documentation | `docs/description` | `docs/update-readme` | +| Chore / config | `chore/description` | `chore/bump-astro-version` | + +### Commit format + +Use [Conventional Commits](https://www.conventionalcommits.org/): + +``` +feat: add JWT decoder tool page +fix: correct base64 trailing newline in k8s sanitizer +docs: update README with CIDR programmatic routes +chore: bump astro to v7.1 +``` + +### Adding a new tool β€” checklist + +- [ ] React component in `src/components/tools/YourTool.tsx` +- [ ] Astro page in `src/pages/your-tool-slug.astro` +- [ ] Component imported with `client:load` in the page +- [ ] Page includes: `` wrapper, canonical-compatible `title` and `description` props, JSON-LD structured data (`WebApplication`, `FAQPage`, `BreadcrumbList`), breadcrumb nav, privacy assurance badge, educational content sections, FAQ, `` +- [ ] Tool added to `toolsConfig`, `toolsPrivacy`, or `toolsNetwork` array in `src/pages/index.astro` +- [ ] Tool added to the correct category in `toolCategories` in `src/components/shared/Navbar.astro` +- [ ] Tool added to hero tools list in `astro.config.mjs` for sitemap priority 1.0 +- [ ] `robots.txt` requires no changes (tool pages should be crawlable) +- [ ] Stats counter in `index.astro` incremented +- [ ] `npm run lint` passes with zero errors +- [ ] `npm run build` completes successfully + +--- + +## Code Style + +The project does not use a separate ESLint config β€” `astro check` (`npm run lint`) handles type checking across `.astro` and `.tsx` files. Match the existing style: + +- Tailwind utility classes for all styling β€” no inline `style` attributes, no CSS modules +- Functional React components with TypeScript, no class components +- `useId()` for form element ID/label associations +- `aria-label`, `aria-labelledby`, and semantic HTML on all interactive elements +- No `console.log` left in committed code + +--- + +## License + +By contributing, you agree that your contributions will be licensed under the MIT License. diff --git a/README.md b/README.md index 66c0035..d4f6bb3 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,8 @@ # ConfigDev -**[https://configdev.com/](https://configdev.com/)** +**Live site: [https://configdev.com](https://configdev.com)** -**Modern, client-side developer utilities for DevOps engineers, cloud architects, and SREs.** - -ConfigDev is a suite of zero-latency, privacy-first tools that solve everyday infrastructure problems without compromising data security. All processing runs 100% inside your browser β€” no uploads, no server round-trips, no logs. - ---- - -## The Local-First, Privacy-First Philosophy - -Pasting sensitive data β€” stack traces, Kubernetes manifests, API keys, server logs β€” into random online utilities is a real security risk. Most tools process your input on a backend server, meaning your production secrets transit infrastructure you don't control. - -ConfigDev eliminates this entirely: - -- **Zero Ingress** β€” Data never leaves your machine. All parsing, encoding, and scrubbing runs inside your browser's V8 sandbox. -- **No Backend** β€” No databases, no history, no analytics on your input. -- **Offline Capable** β€” Once the page loads, disconnect from the internet. Every tool keeps working. -- **Verifiable** β€” Open DevTools β†’ Network tab while using any tool. Zero outbound requests. +A collection of free, client-side infrastructure utilities for DevOps engineers, cloud architects, SREs, and backend developers. Every tool runs entirely inside the browser β€” no uploads, no server round-trips, no data egress. --- @@ -27,55 +12,44 @@ ConfigDev eliminates this entirely: | Tool | URL | Description | |---|---|---| -| PII Masker & Log Scrubber | [/pii-masker-log-scrubber](https://configdev.com/pii-masker-log-scrubber) | Strip emails, IPs, JWTs, credit cards, and secrets from raw logs locally before sharing with LLMs or issue trackers | -| K8s Manifest Sanitizer | [/k8s-manifest-sanitizer](https://configdev.com/k8s-manifest-sanitizer) | Base64 encode/decode Kubernetes Secret data blocks, convert stringData to data, and scrub manifests for safe Git commits | +| PII Masker & Log Scrubber | `/pii-masker-log-scrubber` | Redact emails, IPs, JWTs, API keys, and secrets from raw log dumps using local regex execution | +| K8s Manifest Sanitizer | `/k8s-manifest-sanitizer` | Base64 encode and decode Kubernetes Secret data blocks, convert `stringData` to `data`, and scrub manifests for safe Git commits | ### Infrastructure & Config | Tool | URL | Description | |---|---|---| -| Crontab to Systemd Converter | [/cron-to-systemd-converter](https://configdev.com/cron-to-systemd-converter) | Translate legacy crontab expressions into production-ready systemd `.service` and `.timer` unit files | -| Env to JSON Converter | [/env-to-json](https://configdev.com/env-to-json) | Parse standard `.env` key-value files into clean, formatted JSON objects ready for any pipeline | -| JSON to Env Converter | [/json-to-env](https://configdev.com/json-to-env) | Flatten nested JSON objects into standard `.env` key-value lines with configurable delimiter formatting | +| Crontab to Systemd Converter | `/cron-to-systemd-converter` | Translate legacy crontab expressions into production-ready systemd `.service` and `.timer` unit files | +| Env to JSON Converter | `/env-to-json` | Parse standard `.env` key-value assignment files into clean, formatted JSON objects | +| JSON to Env Converter | `/json-to-env` | Flatten nested JSON objects into standard `.env` key-value lines with configurable delimiter formatting | ### Networking & Data | Tool | URL | Description | |---|---|---| -| CIDR Subnet Calculator | [/cidr-subnet-calculator](https://configdev.com/cidr-subnet-calculator) | Compute subnet boundaries, usable host ranges, broadcast addresses, and network masks for any IPv4 block | -| CSV to JSON Schema Builder | [/csv-to-json-schema](https://configdev.com/csv-to-json-schema) | Inspect CSV column structures and auto-generate a valid JSON Schema Draft-07 specification file | +| CIDR Subnet Calculator | `/cidr-subnet-calculator` | Compute subnet boundaries, usable host ranges, broadcast addresses, and network masks for any IPv4 block | +| CSV to JSON Schema Builder | `/csv-to-json-schema` | Inspect CSV column structures and auto-generate a valid JSON Schema Draft-07 specification file | --- -## Tech Stack +## Architecture -| Layer | Technology | -|---|---| -| Framework | [Astro](https://astro.build/) v7 β€” static output, zero-JS by default | -| UI Components | React 19 (islands, `client:load`) | -| Styling | Tailwind CSS v4 | -| Deployment | Cloudflare Pages | -| Sitemap | `@astrojs/sitemap` | - ---- - -## Development - -```bash -# Install dependencies -npm install +All tools follow the same pattern: a static Astro page wraps a React component mounted with `client:load`. The Astro layer handles all static output β€” layout, SEO metadata, JSON-LD structured data, educational content, and FAQ sections. The React component handles all interactive state β€” inputs, transformations, copy/download actions. -# Start dev server -npm run dev +No tool makes any outbound network request after page load. Transformations use only browser-native APIs: `btoa`, `atob`, `TextEncoder`, `URL`, `FileReader`, `Blob`. You can verify this by opening DevTools Network tab while using any tool. -# Type-check and lint -npm run lint +--- -# Production build -npm run build -``` +## Tech Stack -The project uses flat file routing (`build.format: 'file'`), so pages emit as `/page-name.html` rather than `/page-name/index.html`. This eliminates the trailing-slash duplicate-URL issue in Google Search Console. +| Layer | Choice | +|---|---| +| Framework | Astro v7, static output mode | +| Interactive components | React 19 with `client:load` hydration | +| Styling | Tailwind CSS v4 | +| Deployment | Cloudflare Pages | +| Sitemap | `@astrojs/sitemap` with per-page priority config | +| Type checking | TypeScript via `@astrojs/check` | --- @@ -85,9 +59,9 @@ The project uses flat file routing (`build.format: 'file'`), so pages emit as `/ src/ β”œβ”€β”€ components/ β”‚ β”œβ”€β”€ shared/ -β”‚ β”‚ β”œβ”€β”€ Navbar.astro # Site-wide navigation with grouped tool categories +β”‚ β”‚ β”œβ”€β”€ Navbar.astro # Site-wide nav, tools grouped by category β”‚ β”‚ β”œβ”€β”€ Footer.astro -β”‚ β”‚ └── RelatedTools.astro # Cross-linking widget used on all tool pages +β”‚ β”‚ └── RelatedTools.astro # Cross-linking widget on every tool page β”‚ └── tools/ β”‚ β”œβ”€β”€ CIDRCalculator.tsx β”‚ β”œβ”€β”€ CronToSystemd.tsx @@ -96,45 +70,129 @@ src/ β”‚ β”œβ”€β”€ JsonToEnv.tsx β”‚ β”œβ”€β”€ K8sManifestSanitizer.tsx β”‚ └── PiiScrubber.tsx +β”œβ”€β”€ data/ +β”‚ └── cidr-subnets.json # Pre-computed specs for all /3-/32 prefixes β”œβ”€β”€ layouts/ -β”‚ └── Layout.astro # Base HTML shell, meta, canonical, JSON-LD +β”‚ └── Layout.astro # HTML shell, canonical URL, meta tags, GA/Yandex β”œβ”€β”€ pages/ -β”‚ β”œβ”€β”€ index.astro # Homepage with category grid and search/filter +β”‚ β”œβ”€β”€ index.astro # Homepage: category grid, search/filter tabs +β”‚ β”œβ”€β”€ cidr-subnet-calculator.astro +β”‚ β”œβ”€β”€ cidr-subnet-calculator/ +β”‚ β”‚ └── [subnet]-subnet.astro # Programmatic CIDR detail pages (/8-subnet, etc.) β”‚ β”œβ”€β”€ k8s-manifest-sanitizer.astro β”‚ β”œβ”€β”€ pii-masker-log-scrubber.astro -β”‚ β”œβ”€β”€ cidr-subnet-calculator.astro β”‚ β”œβ”€β”€ cron-to-systemd-converter.astro β”‚ β”œβ”€β”€ csv-to-json-schema.astro β”‚ β”œβ”€β”€ env-to-json.astro β”‚ β”œβ”€β”€ json-to-env.astro -β”‚ └── ... +β”‚ β”œβ”€β”€ about-us.astro +β”‚ β”œβ”€β”€ contact.astro +β”‚ β”œβ”€β”€ privacy.astro +β”‚ β”œβ”€β”€ terms.astro +β”‚ β”œβ”€β”€ 404.astro +β”‚ └── 500.astro └── styles/ └── global.css public/ -β”œβ”€β”€ robots.txt # Crawl directives β€” error/legal pages blocked -β”œβ”€β”€ llms.txt # LLM-readable site manifest -└── _redirects # Cloudflare Pages redirect rules -astro.config.mjs # Site config, sitemap priorities, build format +β”œβ”€β”€ robots.txt # Crawl directives, error/legal pages blocked +β”œβ”€β”€ llms.txt # LLM-readable tool manifest +β”œβ”€β”€ _redirects # Cloudflare Pages redirect rules +β”œβ”€β”€ favicon.svg +└── icon.png +astro.config.mjs # Site URL, sitemap priorities, build format, integrations ``` --- -## Deployment +## Development -Configured for Cloudflare Pages. Set environment variables in your Pages dashboard before deploying: +**Prerequisites:** Node.js >= 20.0.0 + +```bash +# Install dependencies +npm install + +# Start local dev server (http://localhost:4321) +npm run dev + +# Type-check all Astro and TSX files +npm run lint + +# Production build (outputs to dist/) +npm run build + +# Preview production build locally +npm run preview +``` + +The build emits flat `.html` files (`/page-name.html`, not `/page-name/index.html`) because `build.format` is set to `file` in `astro.config.mjs`. This eliminates the trailing-slash duplicate URL problem in Google Search Console. + +--- + +## Environment Variables + +Copy `.env.example` to `.env` and fill in values as needed. Both variables are optional β€” the site builds and runs fully without them. + +```bash +cp .env.example .env +``` | Variable | Purpose | |---|---| -| `PUBLIC_GA_ID` | Google Analytics measurement ID (optional) | -| `PUBLIC_YANDEX_VERIFICATION` | Yandex Webmaster verification (optional) | +| `PUBLIC_GA_ID` | Google Analytics 4 measurement ID (e.g. `G-XXXXXXXXXX`) | +| `PUBLIC_YANDEX_VERIFICATION` | Yandex Webmaster verification token | + +These are injected into `Layout.astro` at build time via `import.meta.env`. Prefix `PUBLIC_` makes them safe for client-side exposure in Astro. + +--- + +## Deployment + +The project deploys to Cloudflare Pages. + +- Build command: `npm run build` +- Output directory: `dist/` +- Node version: 22 + +Set `PUBLIC_GA_ID` and `PUBLIC_YANDEX_VERIFICATION` in the Cloudflare Pages environment variables dashboard if needed. + +Manual deploy via Wrangler: + +```bash +npm run deploy +``` + +This runs `wrangler pages deploy dist --project-name configdev --commit-dirty=true`. + +--- + +## CI Pipeline + +GitHub Actions runs on every push to `main` and every pull request targeting `main`. + +Two jobs run sequentially: + +1. **Lint** β€” runs `npm run lint` (`astro check`) to catch type errors and Astro diagnostics +2. **Build** β€” runs `npm run build` after lint passes; uploads `dist/` as an artifact (7-day retention) + +Both jobs use Node 22 and `npm ci` for reproducible installs. In-progress runs for the same branch are cancelled when new commits arrive. + +--- + +## SEO & Crawlability -Deploy command: `npm run build` β†’ output directory: `dist/` +- Sitemap generated at `/sitemap-index.xml` by `@astrojs/sitemap` +- All 7 tool pages: `priority 1.0`, `changefreq weekly` +- Homepage and about: `priority 0.8`, `changefreq monthly` +- Error pages (`/404`, `/500`) and legal pages (`/terms`, `/privacy`, `/contact`) excluded from sitemap and blocked in `robots.txt` +- Every tool page includes JSON-LD structured data: `WebApplication`, `FAQPage`, and `BreadcrumbList` +- Canonical URLs set via `` in `Layout.astro` --- ## Contributing -See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. +See [CONTRIBUTING.md](CONTRIBUTING.md). ---