Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 89 additions & 22 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -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: `<Layout>` wrapper, canonical-compatible `title` and `description` props, JSON-LD structured data (`WebApplication`, `FAQPage`, `BreadcrumbList`), breadcrumb nav, privacy assurance badge, educational content sections, FAQ, `<RelatedTools>`
- [ ] 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.
186 changes: 122 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.

---

Expand All @@ -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` |

---

Expand All @@ -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
Expand All @@ -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 `<link rel="canonical">` in `Layout.astro`

---

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
See [CONTRIBUTING.md](CONTRIBUTING.md).

---

Expand Down
Loading