10 Commits

Author SHA1 Message Date
Oliver 3627c2c73d build: add .gitignore, npm scripts, fix font-brand token, clear audit warnings 2026-03-27 16:30:07 -03:00
Oliver 4d2f57c20c Checked AGENTS.md 2026-03-27 16:23:57 -03:00
Oliver 05719aae4e INIT Blogs 2026-03-27 13:37:03 -03:00
Web_Designer b2a41d1a7b Add blog post: ODOO has 1,000,000 NGOs online! 2026-03-27 16:29:07 +00:00
Web_Designer 4bdef11b3c Publish: localisation-in-practice-shifting-power-and-funding-to-local-partners-effectively 2026-03-27 16:25:10 +00:00
Web_Designer aafb99460c Update homepage title and H1 to 'OPENCODEis NOICE' 2026-03-27 15:10:00 +00:00
Oliver a74de43248 Update README.md 2026-03-25 18:21:03 -03:00
Web_Designer 819665225f Add blog post: Reduce NGO Admin by 20–40%: 7 Workflows You Can Automate This Month 2026-03-25 20:55:58 +00:00
Oliver 3dd49559ac 0 2026-03-25 16:14:17 -03:00
Oliver c81565749a 0 2026-03-25 16:12:40 -03:00
9 changed files with 264 additions and 85 deletions
+21
View File
@@ -0,0 +1,21 @@
# Dependencies
node_modules/
# Tailwind build temp
tmp.json
# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# OS
.DS_Store
Thumbs.db
# Editor
.vscode/
.idea/
*.swp
*.swo
+207
View File
@@ -0,0 +1,207 @@
# AGENTS.md — NGO Landing Page
Read this file fully before taking any action.
---
## Project Context
Single-page static landing page for an NGO ERP product.
| Item | Detail |
|---|---|
| Pages | `index.html` — the only HTML file |
| Styling | Tailwind CSS v3 · source `src/input.css` → compiled `assets/site.css` |
| Data | `blog.json` — flat array of blog posts, loaded at runtime by inline JS |
| i18n | Inline `translations` object inside `index.html` (EN / ES / DE) |
| Blog renderer | Inline `<script>` in `index.html` — no external JS files |
| Dev server | `./start` (runs `live-server`) |
| Git remote | `git@git.odoo4projects.com:Oliver/NGO.git` |
### File map
```
index.html ← only HTML file — layout + all inline JS + i18n
src/input.css ← Tailwind source (edit here, then rebuild)
assets/site.css ← compiled output — DO NOT edit by hand
blog.json ← blog post data array
tailwind.config.js ← design tokens (colors, fonts, shadows)
```
### Design tokens (from `tailwind.config.js`)
| Token | Hex | Usage |
|---|---|---|
| `brand-ink` | `#201824` | default text / dark backgrounds |
| `brand-primary` | `#603F57` | section labels, bullet accents |
| `brand-accent` | `#F762B4` | CTA buttons, links |
| `brand-sunrise` | `#F8B84A` | hero highlights, hover states |
| `brand-emerald` | `#39B982` | positive indicators |
| `brand-snow` | `#F5F2F7` | page background |
| `brand-smoke` | `#E5DCE8` | borders, subtle dividers |
NEVER use raw hex values in HTML — always use the token class names above.
---
## 🎯 Goal
- Deliver an **SEO-optimised, fast-loading, responsive** single-page site.
- Keep all edits **minimal and targeted** — preserve design, structure, and functionality.
- NEVER introduce new frameworks, libraries, or external dependencies.
### Quality bar for every change
| Concern | Rule |
|---|---|
| SEO | Keep all existing meta tags, `ld+json`, `alt` attributes, and heading hierarchy |
| Performance | No comments in production HTML, no unused CSS classes, no render-blocking additions |
| Responsive | Every element must work on mobile (375 px), tablet (768 px), and desktop (1280 px+) |
| Consistency | Use only brand token classes; match existing spacing and rounding patterns |
---
## Commands
```bash
# Build CSS after editing src/input.css or tailwind.config.js
npm run build:css
# Watch CSS during active development
npm run watch:css
# Validate blog.json
jq empty blog.json && echo "JSON valid"
# Start dev server
./start
```
---
## Git Rules
- ALWAYS work on **`main`** branch.
- Pull before every session:
```bash
git pull origin main
```
- Commit messages must follow the pattern:
- `blog: add post <title>`
- `fix: <short description>`
- `content: <short description>`
- Push immediately after committing — never leave unpushed commits.
- Branch creation is permitted ONLY under the **Branch Handling Exception** (see bottom).
---
## File Safety Rules
- ONLY modify files required for the task.
- NEVER delete or restructure content unrelated to the task.
- NEVER remove existing blog posts from `blog.json`.
- NEVER edit `assets/site.css` directly — always rebuild from `src/input.css`.
---
## Blog Post Schema
`blog.json` is a root-level JSON array. Every post object contains **exactly these five fields**:
```json
[
{
"area": "Automation",
"date": "2026-03-25",
"title": "Article title as plain text",
"teaser": "<p>One or two sentences visible before 'Read more'.</p>",
"content": "<h3>Section</h3><p>Full article as HTML.</p>"
}
]
```
| Field | Type | Constraint |
|---|---|---|
| `area` | plain string | Category label rendered above the title |
| `date` | ISO 8601 (`YYYY-MM-DD`) | Used by `Intl.DateTimeFormat` |
| `title` | plain string | Rendered as `<h3>` — no HTML |
| `teaser` | HTML string | Always visible — wrap in `<p>` tags |
| `content` | HTML string | Revealed by "Read more" toggle — use `<h3>`, `<p>`, `<ul>`, `<li>` |
NEVER add extra fields (`slug`, `author`, `tags`, `excerpt`, `hero_image`, etc.) — they are ignored by the renderer and pollute the file.
### Adding a new blog post (jq method)
```bash
# 1. Pull latest
git pull origin main
# 2. Backup (once per session)
mkdir -p /backup && cp blog.json /backup/blog.json.$(date +%Y%m%d%H%M%S)
# 3. Prepend new post — $NEW_JSON must be a valid single post object
jq --argjson new "$NEW_JSON" '. = [$new] + .' blog.json > tmp.json && mv tmp.json blog.json
# 4. Validate
jq empty blog.json && echo "JSON valid"
# 5. Commit and push
git add blog.json
git commit -m "blog: add post <title>"
git push origin main
```
NEVER use Python, Node scripts, or manual text editing to modify `blog.json`.
---
## Execution Workflow
Follow this order for every task:
1. `git pull origin main`
2. Identify the exact files to change — nothing else.
3. Apply minimal edits.
4. If `src/input.css` or `tailwind.config.js` were changed → rebuild CSS.
5. Validate: `jq empty blog.json` for JSON; visual check for HTML.
6. Commit with a descriptive message.
7. `git push origin main`
---
## Success Criteria
- Changes are minimal, validated, and committed.
- `blog.json` is a valid array with exactly five fields per post.
- `assets/site.css` reflects any CSS changes (rebuilt, not hand-edited).
- HTML passes a visual check — layout and design unchanged except for the intended edit.
- All commits pushed to `main`.
---
## Failure Conditions
These actions constitute a failure:
- Refusing to act due to perceived access restrictions.
- Failing to push after committing.
- Adding undeclared fields to `blog.json`.
- Removing or overwriting existing blog posts.
- Editing `assets/site.css` by hand.
- Modifying files outside the scope of the task.
- Leaving a branch open without merging.
---
## Branch Handling Exception
Branch creation is permitted **only** when:
- The task explicitly requires a feature branch, **or**
- A direct push to `main` is blocked by branch protection.
If a branch is created it **must**:
- Follow the naming convention `<type>/<short-description>` (e.g. `fix/blog-json-schema`).
- Be merged into `main` via PR immediately after the task is complete.
- Be deleted after merge — never abandoned.
@@ -1,26 +0,0 @@
Rollback and Recovery Changelog
Timestamp: ${TS}
Actions performed:
- Reset main branch (working tree and HEAD) to commit 6127867d51c9f0e4e86d1d8390081208f45136ab and force-pushed to origin/main.
- Confirmed README.md content matches version at commit 6127867d51.
- Investigated deleted backups: located backups in parent commit 5189b23 and extracted available files into recovered_backups/ directory in the working tree (not yet committed).
- Created this changelog and saved recovered backup files under recovered_backups/ for review.
Recovered backup files:
- backups/index.html.20260324164129.bak -> recovered_backups/index.html.20260324164129.bak (extracted from commit 5189b23)
- backups/index.html.bak.20260324164053 -> recovered_backups/index.html.bak.20260324164053 (extracted from commit 5189b23)
Notes on recovery:
- The deleted backup files were present in previous commits and have been extracted from git history into recovered_backups/.
- Additional backup files referencing other timestamps exist in git history (e.g., backups/index.html.20260324164556.bak and backups/index.html.20260324164626.bak). These can be extracted on request.
Suspicious findings:
- Commit 6127867d51 (message: "Deleted Backups and changed readme") removed backup files. Author: Oliver. This commit may be responsible for missing backups. Please confirm whether this deletion was authorized.
Remaining tasks / recommendations:
- Decide whether to reintroduce recovered backups into main branch. Restoring them to main will create a new commit on top of 6127867d51 (this changelog can be used), or they can be provided in a separate branch or as artifacts.
- If you want me to commit the recovered_backups/ content and this changelog to the repository and push, confirm and I will proceed.
- If you prefer the repository to remain exactly at 6127867d51 (no additional commits), I will not commit recovered files; instead I will provide them separately (download/attach) and leave main at the rollback state.
+16 -26
View File
@@ -5,12 +5,24 @@
**Stack:** Static HTML · Tailwind CSS · Vanilla JS **Stack:** Static HTML · Tailwind CSS · Vanilla JS
--- ---
## BLOG POSTS
Blog posts live in `blog.json` — do not create separate backup files.
To add a blog post customize this command
jq '.arrays[0] = [$NEW_JSON] + .arrays[0]' blog.json > tmp.json && mv tmp.json blog.json
## Repository Rules ## Repository Rules
- Do not touch this readme
- Blog posts live in `blog.json` — do not create separate backup files. - Keep the seperation of Site and the blogposts in blog.json
- No backup files in the repo. Example of JSON structure for blog.json
- Update this README with every commit. {
"area": "Transparency",
"title": "Every Peso on the Page: Ana's Ledger Story",
"teaser": "<p>Ana replaced five notebooks with a four-stop impact ledger and now answers donor questions in seconds.</p>",
"content": "<h3>Every peso needs a map</h3>\n<p>Ana used to juggle five notebooks and still felt blind when a donor asked where their coin landed.</p>\n<h3>Pressure points</h3>\n<p without late nights.</p>\n",
"date": "2026-03-22"
},
--- ---
@@ -26,22 +38,6 @@
--- ---
## CI Checks (required on every push)
- **HTML lint** — valid markup, no broken anchors
- **JS lint** — no errors, no `console.error` left in production paths
- **Tailwind build** — `npx tailwindcss -i ./src/input.css -o ./assets/site.css --minify` must exit 0
- **Corporate design compliance:**
- No CSS gradients — `gradient`, `bg-*-gradient`, `linear-gradient`, `radial-gradient` are forbidden
- No CSS animations or keyframes — `animate-*`, `@keyframes`, transform-based `hover:translate-*` are forbidden
- No blur or glassmorphism effects — `backdrop-blur`, `backdrop-filter` are forbidden
- Colors must use the approved brand palette only: `brand-ink · brand-primary · brand-accent · brand-sunrise · brand-emerald · brand-snow · brand-smoke`
- Images must be served from `odoo4projects.com`, `images.unsplash.com`, or local `assets/`
- **Accessibility** — heading hierarchy (one `<h1>` per page), `alt` on all images, sufficient contrast (WCAG AA)
- **Performance budget** — total page weight ≤ 200 KB (excluding cached fonts); critical render path ≤ 1 s on fast 3G
- **SEO** — `<title>`, `<meta name="description">`, `<h1>`, canonical `<link>`, and JSON-LD structured data must be present
---
## Languages ## Languages
@@ -52,9 +48,3 @@
| `de` | Deutsch | | `de` | Deutsch |
All UI strings are managed via the inline `translations` object in `index.html`. All UI strings are managed via the inline `translations` object in `index.html`.
---
## Focus Keywords
`NGO donor management` · `transparent donations` · `Odoo for NGOs` · `donor communication` · `minimal admin for charities`
+5 -18
View File
@@ -1,22 +1,9 @@
[ [
{ {
"area": "Donor Management", "area": "Donor Communication",
"title": "From Notebooks to Night Off: How One NGO Cut Reconciliation Time in Half", "title": "How Maya Turned Donor Chaos into Clear Connections",
"teaser": "<p>Ana replaced stacks of notebooks with a single shared ledger and reclaimed her evenings.</p>", "teaser": "<p>Maya transformed scattered donor messages into a smooth, trustworthy flow that grows support.</p>",
"content": "\"Ana used to sit under a single lamp with three notebooks stacked and the weight of every donor question on her shoulders. When a donor called she fumbled through pages and felt her chest tighten.\"\n\nAn ERP creates a single source of truth for every donation: each peso is recorded once and linked to allocations, program expenses, receipts, and impact notes, eliminating duplicated spreadsheets and manual cross-checks. Shared dashboards, ownership fields, and due-date tracking make reconciliation predictable and reduce the time teams spend hunting for evidence.\n\nWith Odoo and n8n, donors submit a simple webform that triggers an n8n workflow to create the donation card in Odoo, attach receipts, apply tags, and notify the approver. Approval buttons in Odoo, automated reminder sequences, and scheduled exports or AI summaries transform reconciliation into a short weekly routine and let audit packets assemble automatically.\n\n\"Now Ana closes her laptop at 7 p.m., answers donor queries in seconds from a shared dashboard, and walks home without the knot in her chest — the night no longer belongs to reconciliation but to rest.\"\n\nGet a free trial: https://ngo.odoo4projects.com", "content": "<h3>From scattered emails to a single view</h3>\n<p>Maya used to juggle spreadsheets, inbox threads, and sticky notes, trying to track donor interactions. Messages were missed, thank-yous delayed, and trust wavered.</p>\n<h3>Organizing the donor journey</h3>\n<p>She mapped every donor touchpoint: initial contact, donation, follow-ups, renewals, and special campaigns.</p>\n<p>Each interaction got a card in Odoo showing donor, date, preferred channel, and notes.</p>\n<h3>Automated touchpoints</h3>\n<p>n8n automates reminders: thank donors, confirm gifts, and ping staff before renewals. No one misses a beat, and personalization stays intact.</p>\n<h3>Transparency everywhere</h3>\n<p>Donors can see updates on projects they supported. Status labels on campaigns show funds allocated, impact stories, and upcoming events.</p>\n<p>Staff leave notes visible to colleagues, so no duplicate outreach or awkward overlaps happen.</p>\n<h3>Visual dashboards</h3>\n<p>A live dashboard shows donor activity, upcoming renewals, and campaign health. Color codes indicate priority: green for confirmed gifts, yellow for pending pledges, red for urgent follow-ups.</p>\n<h3>Communication rhythm</h3>\n<p>Weekly donor check-ins keep the team aligned. Monthly newsletters highlight wins, donor impact, and upcoming opportunities. Special campaigns trigger micro-emails personalized by giving level.</p>\n<ul>\n <li>Monday: review new donors and pending follow-ups.</li>\n <li>Wednesday: confirm campaign progress and donor notes.</li>\n <li>Friday: send thank-you emails and impact updates.</li>\n</ul>\n<h3>Metrics & impact</h3>\n<p>Donor retention improved by 25%.</p>\n<p>Response times dropped from days to hours.</p>\n<p>Staff report feeling less stressed because communication is predictable and visible.</p>\n<h3>Rollout plan</h3>\n<ul>\n <li>Import all donor records into Odoo cards and tag owners.</li>\n <li>Set n8n alerts for gifts, follow-ups, and renewals.</li>\n <li>Create dashboards showing active donors, pledges, and campaign status.</li>\n <li>Automate thank-you emails and impact updates.</li>\n</ul>\n<p>This replaces weeks of scattered emails and missed opportunities.</p>\n<p><strong>Micro-CTA:</strong> Want Mayas donor management template? Reply “connect” and well send the setup guide.</p>\n<h3>Story beats returned</h3>\n<p>The organization still hustles, but now each donor feels seen, valued, and in the loop. Maya smiles at every timely thank-you that lands without chasing anyone.</p>\n<h3>Your invitation</h3>\n<p>Subscribe to the NGO ops newsletter or book a donor communication clinic. Well map your donor flow, load it into Odoo, wire n8n alerts, and leave you with clear, trustworthy connections you can maintain effortlessly.</p>",
"date": "2026-03-24", "date": "2026-03-25"
"slug": "from-notebooks-to-night-off",
"author": "Odoo4Projects NGO",
"categories": [
"Donor Management",
"Efficiency"
],
"tags": [
"Odoo",
"n8n",
"reconciliation",
"donor-management"
],
"meta_description": "How one NGO replaced stacked notebooks with a shared ledger and cut reconciliation time in half using Odoo + n8n."
} }
] ]
+2 -2
View File
@@ -6,7 +6,7 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<title> NGO ERP Landingpage | ODOO4projects</title> <title>OPENCODEis NOICE</title>
<meta name="description" content="Purpose-built ERP platform for NGOs. Centralize programs, automate donor and grant reporting, and launch in weeks with ODOO4projects." /> <meta name="description" content="Purpose-built ERP platform for NGOs. Centralize programs, automate donor and grant reporting, and launch in weeks with ODOO4projects." />
<meta name="keywords" content="NGO ERP system, nonprofit management software, ERP for NGOs, NGO operations platform, ODOO for nonprofits" /> <meta name="keywords" content="NGO ERP system, nonprofit management software, ERP for NGOs, NGO operations platform, ODOO for nonprofits" />
<link rel="icon" href="https://odoo4projects.com/web/image/website/1/favicon?unique=725c3af" /> <link rel="icon" href="https://odoo4projects.com/web/image/website/1/favicon?unique=725c3af" />
@@ -69,7 +69,7 @@
<div class="max-w-6xl mx-auto px-6 py-16 grid md:grid-cols-2 gap-12 items-center"> <div class="max-w-6xl mx-auto px-6 py-16 grid md:grid-cols-2 gap-12 items-center">
<div> <div>
<p class="text-brand-sunrise font-semibold mb-4" data-i18n="hero-pill"></p> <p class="text-brand-sunrise font-semibold mb-4" data-i18n="hero-pill"></p>
<h1 class="text-4xl md:text-5xl font-semibold leading-tight mb-6"><span class=\"emoji\" aria-hidden=\"true\"></span> <span data-i18n=\"hero-headline\"></span></h1> <h1 class="text-4xl md:text-5xl font-semibold leading-tight mb-6">OPENCODEis NOICE</h1>
<p class="text-lg text-white/80 mb-8" data-i18n="hero-subheadline"></p> <p class="text-lg text-white/80 mb-8" data-i18n="hero-subheadline"></p>
<div class="flex flex-wrap gap-4"> <div class="flex flex-wrap gap-4">
<a href="#trial" class="px-6 py-3 bg-brand-accent hover:bg-brand-sunrise text-brand-ink font-semibold rounded-full transition" data-i18n="cta-trial" data-event="cta:hero-trial"></a> <a href="#trial" class="px-6 py-3 bg-brand-accent hover:bg-brand-sunrise text-brand-ink font-semibold rounded-full transition" data-i18n="cta-trial" data-event="cta:hero-trial"></a>
+6 -8
View File
@@ -537,11 +537,10 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/picomatch": { "node_modules/picomatch": {
"version": "2.3.1", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">=8.6" "node": ">=8.6"
}, },
@@ -968,11 +967,10 @@
} }
}, },
"node_modules/tinyglobby/node_modules/picomatch": { "node_modules/tinyglobby/node_modules/picomatch": {
"version": "4.0.3", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
+2
View File
@@ -4,6 +4,8 @@
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build:css": "tailwindcss -i src/input.css -o assets/site.css --minify",
"watch:css": "tailwindcss -i src/input.css -o assets/site.css --watch",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"repository": { "repository": {
+1 -1
View File
@@ -3,7 +3,7 @@
@tailwind utilities; @tailwind utilities;
body { body {
font-family: 'Inter', 'Segoe UI', system-ui, sans-serif; @apply font-brand;
} }
#lang-selector { #lang-selector {