diff --git a/.okf/build/hugo-build.md b/.okf/build/hugo-build.md index f67761933..27f6c9dcd 100644 --- a/.okf/build/hugo-build.md +++ b/.okf/build/hugo-build.md @@ -7,6 +7,7 @@ tags: [build, hugo, validation] generated: by: process:okf-migrate at: 2026-07-19T12:00:00Z +timestamp: 2026-08-13T00:00:00Z --- `bin/hugo-build` builds the site into `_dest/public-dev/` (repo-root @@ -41,3 +42,34 @@ safelist entries). Guards: bin/hugo-build runs a warm-up pass when production + stats missing; the deploy workflow has an explicit warm-up step. sr-only/skip-link also safelisted as defense-in-depth. Never trust a first cold production build's CSS. + +# Minified output has unquoted attributes (2026-08-13) + +`minifyOutput = true` makes Hugo drop quotes on attribute values with no +spaces: `rel=canonical`, `name=description`, `type=application/ld+json`. +Valid HTML5, and Google parses it correctly - but regex-based third-party +SEO/AEO audit tools require quotes and report the site as missing canonical +tags, meta descriptions, and structured data. All three are false. + +Diagnostic tell: checks reading ATTRIBUTE VALUES fail while checks reading +ELEMENT CONTENT (title, H1) pass. That split means parser artifact, not site +defect. Settle it in one call with GSC `inspect_url_enhanced`, which returns +`user_canonical` and the rich-results verdict - Google reporting what it +actually parsed. + +Note `config/test/hugo.toml` sets `minifyOutput = false`, so **the test suite +never sees minified output** and cannot catch minification-related regressions; +that needs a `hugo --environment production` build. Full write-up: +`docs/projects/2510-seo-content-strategy/seo-review-2026-08-13.md` §8. + +**Our own suite had the same defect** (2026-08-14). Turning `keepQuotes` on +broke three tests in `test/integration/hugo_pipeline_test.rb` (the CI "Asset +Pipeline" job) that matched unquoted attribute literals - +`include?("crossorigin=anonymous")`, `rel=stylesheet`, `as=style`. The +`integrity="sha256-..."` assertions kept passing because base64 forces quotes +either way. Same tell as the audit tool: attribute-VALUE matches break, +element-content matches survive. Fixed with an `attr(name, value)` helper +matching either form - assert the shape, not the minifier setting. If you +touch minify config, run `bundle exec ruby -Itest +test/integration/hugo_pipeline_test.rb` (~12s local, ~568s on CI because it +runs two full Hugo builds). diff --git a/.okf/build/index.md b/.okf/build/index.md index e708f184f..0d71ee65c 100644 --- a/.okf/build/index.md +++ b/.okf/build/index.md @@ -1,6 +1,6 @@ # Build & Test -* [Hugo build pipeline](hugo-build.md) - bin/hugo-build with the 8 course validators +* [Hugo build pipeline](hugo-build.md) - bin/hugo-build with the 8 course validators; also the PurgeCSS cold-start race and the minified-unquoted-attribute audit-tool trap * [Test gates](test-gates.md) - the local suites and when each is a commit blocker * [CI gates](ci-gates.md) - what GitHub Actions enforces: build, unit, path-scoped link check (visual regression is report-only), and what gates a PR never sees * [Template PDFs](pdf-templates.md) - regenerating the downloadable course PDFs diff --git a/.okf/build/test-gates.md b/.okf/build/test-gates.md index 6db1d40c8..3daaef4ca 100644 --- a/.okf/build/test-gates.md +++ b/.okf/build/test-gates.md @@ -28,6 +28,23 @@ extend it when adding components or critical files. The macOS full suite remains # Hard-won caveats +- **The 2% default tolerance hides small text/colour changes** (2026-08-14). + `DEFAULT_SCREENSHOT_CONFIG = {tolerance: 0.02}` + (`test/application_system_test_case.rb:87`). Turning a four-word phrase into + a link on the homepage changed ~0.24% of the frame, so the gate PASSED and + the baseline was never re-recorded - it still shows the pre-change render. + Consequence: a green visual suite does NOT mean "no visual change", only "no + change larger than 2% of the frame". For link/colour/short-text edits, + verify by reading the built HTML or the render, not by trusting green. This + is the false-green class documented in + `docs/20-29-testing-qa/test-architecture-anti-masking.md`. +- **`FORCE_SCREENSHOT_UPDATE=1` re-records EVERYTHING** (2026-08-14). On + `bin/dtest` it also disables the `git checkout -- .../linux` guard that + normally discards sub-tolerance Rosetta drift, so a run rewrites all 45 + Linux baselines rather than the few your change moved. Procedure: run it, + copy out only the baselines your change legitimately moved, `git checkout -- + test/fixtures/screenshots/linux`, then copy your files back. On `bin/qtest` + the flag appears to be ignored entirely - the suite still compares. - **A `skip_area` selector that matches NOTHING costs 5s per screenshot** (2026-08-01). snap_diff resolves each mask via `all(sel, visible: true)`, and Capybara waits `default_max_wait_time` (5s) on a zero-match selector. diff --git a/.okf/log.md b/.okf/log.md index 6f80f01a7..d6705a327 100644 --- a/.okf/log.md +++ b/.okf/log.md @@ -1,5 +1,27 @@ # Bundle Update Log +## 2026-08-14 (claims) - the number nobody had a source for was wrong + +* **Update**: `.okf/build/test-gates.md` gains the 2% tolerance false-green and + the `FORCE_SCREENSHOT_UPDATE` re-record trap; + `docs/projects/2510-seo-content-strategy/seo-review-2026-08-13.md` §8 actions + 7-9 closed. +* **The finding**: the site published "4.8/5 by 32 clients" and + `reviewCount: 32` in schema on ~1,147 URLs. `reviewCount` had **no source + anywhere in the repo** - `data/company.yaml:11` cites a Clutch rating with no + count. The live Clutch profile shows **4.8 from 9 reviews**. The rating was + right; the count was overstated ~3.5x. `data/course_banned_strings.yaml:65` + had already banned "4.8/5" in course content as a "volatile third-party + review score" - the course side learned this and the marketing side did not. +* **The rule**: a number with no in-repo provenance is a defect, not a detail. + When a claims audit says "verify X", verify it before deciding what to do + with it - the earlier call to keep 32 was made assuming it was sourced. + Prefer a **linked** rating over a bigger unlinked one; the link is the proof. +* **Also closed**: fabricated `Review` objects ("Technology Executive", + "Startup Founder") deleted from `comprehensive-service-schema.html`, and + `keepQuotes = true` added (verified in a production build; homepage + 124,256 -> 125,988 bytes, +1.4%). + ## 2026-08-13 (LinkedIn exhibits) - purpose-built post images consume the house spec * **Update**: `linkedin-posts/README.md` §"Every post carries a visual" rewritten @@ -24,6 +46,29 @@ MBP-14), image column 460px, image is a click-to-open-new-tab link (drag-to-attach preserved); prev/next nav now traverses in board order (chronological by effective date), not Hugo section order. +## 2026-08-13 (build) - a failing audit tool is not a failing site + +* **Update**: `.okf/build/hugo-build.md` gains "Minified output has unquoted + attributes"; full write-up in + `docs/projects/2510-seo-content-strategy/seo-review-2026-08-13.md` §8. +* **The finding**: a third-party AI-SEO tool scored the site 60/100 "Multiple + Organ Failure" and reported no canonical tags, no structured data, and + placeholder meta descriptions. **All false.** `minifyOutput = true` drops + quotes on space-free attribute values (`rel=canonical`, + `type=application/ld+json`), and the tool's regex parser requires quotes. + GSC confirms Google parses all of it correctly. +* **The tell**: checks reading ATTRIBUTE VALUES failed; checks reading ELEMENT + CONTENT (title, H1) passed. Read the failure *shape* before the failure + *text* - that split is a parser artifact every time. +* **The rule**: before acting on any external audit, run GSC + `inspect_url_enhanced`. It returns `user_canonical` plus the rich-results + verdict - Google reporting what it actually parsed - and settles it in one + call. Also note `config/test/hugo.toml` sets `minifyOutput = false`, so the + test suite is blind to minification regressions by construction. +* **What was real**: the same audit's copy criticism. And what it missed + entirely - the site publishes fabricated review schema (invented "Technology + Executive" reviews + two contradictory ratings). Asking "is schema missing?" + never asks "is the schema honest?". ## 2026-08-13 (visual gate) - a new component needs cold eyes, not the implementer's diff --git a/config/_default/hugo.toml b/config/_default/hugo.toml index 1074f4dde..0101c4886 100644 --- a/config/_default/hugo.toml +++ b/config/_default/hugo.toml @@ -63,6 +63,13 @@ disableKinds = [] [minify] minifyOutput = true + # Regex-based third-party audit crawlers cannot match unquoted attributes + # (rel=canonical, name=description, type=application/ld+json), and report the + # site as missing canonical tags and structured data. Both are present and + # Google parses them fine - see seo-review-2026-08-13.md §8. This is a + # cosmetic hedge for those tools, NOT an SEO fix. + [minify.tdewolff.html] + keepQuotes = true [[redirects]] from = "/tags/:slug/" @@ -111,7 +118,7 @@ disableKinds = [] parent = "services" identifier = "fractional-cto" title = "Fractional CTO" - name = "Get on-demand access to a CTO to help guide your technical vision, accelerate team-building, and improve development team operations." + name = "A senior engineer reviews your codebase and your team, then tells you in plain English what to fix first. $5K-$15K/month, starting in days." pageRef= "/services/fractional-cto/" weight = 1 @@ -119,7 +126,7 @@ disableKinds = [] parent = "services" identifier = "fractional-product" title = "Fractional Product Management" - name = "Get on-demand access to a product expert to help design UX, plan & prioritize your roadmap, and manage development schedules." + name = "A product lead who runs your roadmap and writes the specs, so your developers stop guessing what to build next." pageRef= "/services/fractional-product-management/" weight = 2 @@ -127,7 +134,7 @@ disableKinds = [] parent = "services" identifier = "app-web" title = "App/Web Development" - name = "Whether you’re a startup building new products or an established business upgrading existing systems, we help deliver positive outcomes." + name = "Rails and React builds, test-driven from the first commit. You own the code after every milestone." pageRef= "/services/app-web-development/" weight = 3 @@ -135,7 +142,7 @@ disableKinds = [] parent = "services" identifier = "outsourced-developer" title = "Outsourced Developer Staffing" - name = "Increase your development capacity & reduce administrative workloads with pre-trained engineers that are ready to deploy within weeks." + name = "Senior Rails and React engineers join your team in weeks. They follow your process, and you keep control of the code." pageRef= "/services/outsourced-developer-staffing/" weight = 4 @@ -143,7 +150,7 @@ disableKinds = [] parent = "services" identifier = "software-qa" title = "Software AQA & Testing" - name = "Accelerate development, streamline release cycles, and eliminate roadblocks with fully-managed software testing & QA services." + name = "We write the tests your app never had, then send you a bug report you can actually read - what broke and what it costs to fix." pageRef= "/services/software-qa-cat/" weight = 5 @@ -151,7 +158,7 @@ disableKinds = [] parent = "services" identifier = "talent-recruiting" title = "Talent Recruiting & Training" - name = "Scale your development team & simplify the talent acquisition process with top-caliber candidates that are pre-vetted by our team." + name = "We screen Rails and React candidates the way we screen our own hires - take-home code and a live pairing session. You interview the short list." pageRef= "/services/talent-recruiting-training/" weight = 6 @@ -165,7 +172,7 @@ disableKinds = [] parent = "usecases" identifier = "startup-mvp" title = "Startup MVP Prototyping & Development" - name = "Whether creating an interactive prototype to validate the user experience or building out a Minimum Viable Product (MVP) for initial customers, we help startups accelerate the path from idea to revenue." + name = "A clickable prototype you can test with real users, or a working MVP your first customers can pay for. You see a demo every week." pageRef= "/use-cases/startup-mvp-prototyping-development/" weight = 1 @@ -173,15 +180,15 @@ disableKinds = [] parent = "usecases" identifier = "salvage-project" title = "Salvage an Existing Project" - name = "The sooner a software project is salvaged, the better chance it has of being a viable long-term investment. We can help transform your product, providing the visibility, clarity, and control you need to get your project on track." + name = "A senior engineer audits your codebase in 48 hours and writes you a recovery plan with costs attached." pageRef= "/use-cases/salvage-existing-project/" weight = 2 [[menu.main]] parent = "usecases" identifier = "empower-team" - title = "Empower an Existing Engineering Team" - name = "The easiest & fastest way to grow software development capacity is by using a trusted technology partner that can deploy pre-trained developers on-demand without the need for additional supervision." + title = "Extend an Existing Engineering Team" + name = "Add senior Rails and React engineers without adding management overhead. They ship inside your existing process." pageRef= "/use-cases/empower-existing-engineering-team/" weight = 3 @@ -189,7 +196,7 @@ disableKinds = [] parent = "usecases" identifier = "emergency-cto" title = "Emergency CTO Leadership" - name = "To maintain visibility, accountability, and control over technology outcomes when a critical team member leaves, companies need on-demand access to technical leadership to help keep the status quo for IT intact." + name = "Your lead developer just quit. We step in, take stock of what actually exists, and keep the product shipping." pageRef= "/use-cases/emergency-cto-leadership/" weight = 4 @@ -197,7 +204,7 @@ disableKinds = [] parent = "usecases" identifier = "automate-product" title = "Automate Product QA & Testing" - name = "To enable faster product development while eliminating the risks of costly mistakes, companies need access to a reliable product testing & QA resource that can ensure quality at any scale." + name = "Automated tests that catch the break before your users do, plus a weekly report on what they caught." pageRef= "/use-cases/automate-product-qa-testing/" weight = 5 @@ -205,7 +212,7 @@ disableKinds = [] parent = "usecases" identifier = "accelerate-dev" title = "Accelerate Development & Maximize Capacity" - name = "Our developers are ready to deploy within weeks (not months), giving companies the ability to accelerate their software development process while still maintaining control over engineering quality." + name = "Senior engineers start in weeks, not months. Every milestone ships with tests and a written progress report." pageRef= "/use-cases/accelerate-development-maximize-capacity/" weight = 6 diff --git a/content/pages/about-us/index.md b/content/pages/about-us/index.md index f505b6f94..07eebb4d4 100644 --- a/content/pages/about-us/index.md +++ b/content/pages/about-us/index.md @@ -24,7 +24,7 @@ founder_expertise: value: "Our leadership team averages 12+ years of industry experience, with specializations in Ruby on Rails, React, startup MVP development, and fractional CTO services. We've contributed to 50+ open-source projects and published 540+ technical articles sharing our expertise with the developer community." - name: Industry Recognition - value: "Clutch Top Ruby on Rails Developers (2023-2024), featured in Forbes and Inc. Magazine for technical leadership excellence, recognized for 95% client retention rate—highest in the industry for development agencies." + value: "Clutch Top Ruby on Rails Developers (2023-2024), featured in Forbes and Inc. Magazine for technical leadership, with 95% of clients continuing past their first engagement." - name: Proven Track Record value: "Delivered 200+ successful projects for startups and growing companies across healthcare, education, SaaS, and e-commerce sectors. Our clients achieve 89% fundraising success rate and 3x faster time-to-market compared to traditional development approaches." @@ -32,7 +32,7 @@ founder_expertise: about_us_block1: headline: Our Mission items: - - In the software development world, two world-class developers can outperform an army of sub-par engineers. + - Two strong developers will outbuild a room full of average ones, and cost less. - At JetThoughts, we believe in the power of curating technical talent and strive to differentiate ourselves on the quality of our work. - To ensure we deliver the best outcomes every time, we choose to work with only a few clients at a time and make them our primary focus. - By giving each client more attention in the spotlight, we're able to improve alignment, make more progress, and create better long-term relationships. diff --git a/content/services/app-web-development/index.md b/content/services/app-web-development/index.md index 464271628..5c0177331 100644 --- a/content/services/app-web-development/index.md +++ b/content/services/app-web-development/index.md @@ -11,7 +11,7 @@ cover_image: service-app-web-development.jpg menu_custom: icon: submenu-web.svg title: App/Web Development - description: Whether you’re a startup building new products or an established business upgrading existing systems, we help deliver positive outcomes. + description: Rails and React builds, test-driven from the first commit. You own the code after every milestone. metatags: image: og-services-app-web-development.jpg @@ -26,7 +26,7 @@ faqs: - question: "What's your development process?" answer: "We follow an agile development methodology with regular sprint cycles, continuous integration, and frequent client communication. Our process includes discovery and planning, design and prototyping, iterative development with weekly demos, testing and QA, deployment, and ongoing support." - question: "Can you work with our existing team or systems?" - answer: "Absolutely. We seamlessly integrate with existing development teams, work with legacy systems, and can augment your in-house capabilities. Our team acts as an extension of your organization, adapting to your processes, tools, and communication preferences. If you need to scale your team quickly, our [outsourced developer staffing](/services/outsourced-developer-staffing/) service can provide additional Ruby on Rails developers. We also ensure quality through our comprehensive [software QA testing services](/services/software-qa-cat/) integrated into the development process." + answer: "Absolutely. We join existing development teams and work with legacy systems, adapting to your processes, tools, and communication preferences. If you need to scale your team quickly, our [outsourced developer staffing](/services/outsourced-developer-staffing/) service can provide additional Ruby on Rails developers. We also ensure quality through our comprehensive [software QA testing services](/services/software-qa-cat/) integrated into the development process." overview: headline: From idea to production MVP in 8 weeks diff --git a/content/services/fractional-cto-cost/index.md b/content/services/fractional-cto-cost/index.md index d67873cc0..315ffa75e 100644 --- a/content/services/fractional-cto-cost/index.md +++ b/content/services/fractional-cto-cost/index.md @@ -224,6 +224,6 @@ Our fractional CTO cost-effective solutions support businesses across multiple i ## Ready to Get Expert CTO Leadership at Fraction of the Cost? -Understanding fractional CTO cost is the first step toward accessing world-class technology leadership for your business. Our transparent pricing and flexible engagement models make strategic CTO expertise accessible to companies of all sizes. +Understanding fractional CTO cost is the first step toward getting senior technology leadership for your business. Our transparent pricing and flexible engagement models make strategic CTO expertise accessible to companies of all sizes. [Contact us today](/contact/) for a free consultation and customized fractional CTO cost proposal tailored to your specific needs and growth objectives. diff --git a/content/services/fractional-cto/index.md b/content/services/fractional-cto/index.md index 3e9280b8b..47fb36734 100644 --- a/content/services/fractional-cto/index.md +++ b/content/services/fractional-cto/index.md @@ -36,7 +36,7 @@ overview: headline: The power of a CTO at a fraction of the cost list: - name: The Situation - value: Today's business world is driven by technology. Whether it's launching a software product, building a website, or managing digital infrastructure, organizations rely on technical leadership to stay competitive & keep operations running smoothly. With access to a CTO, companies can better navigate the waters of cutting-edge technology while reducing risks & increasing the adaptability of the organization. + value: Today's business world is driven by technology. Whether it's launching a software product, building a website, or managing digital infrastructure, organizations rely on technical leadership to stay competitive & keep operations running smoothly. With access to a CTO, companies can make better calls on new technology while reducing risks & increasing the adaptability of the organization. - name: The Problems value: Unfortunately, the cost of a CTO is significant and access to this type of experienced technical talent can be very competitive. Because a CTO is often necessary for early-stage software startups, founders often have to choose between giving up serious equity or drastically increasing operating costs. - name: Our Experiences diff --git a/content/services/fractional-product-management/index.md b/content/services/fractional-product-management/index.md index 6d24da562..3a00acfc4 100644 --- a/content/services/fractional-product-management/index.md +++ b/content/services/fractional-product-management/index.md @@ -25,7 +25,7 @@ faqs: - question: "What type of companies benefit from Fractional Product Management?" answer: "Startups needing senior product guidance without full-time costs, established companies launching new products, organizations undergoing digital transformation, businesses needing temporary product leadership during transitions, and companies wanting to validate product concepts before major investments." - question: "How do you ensure alignment with our business goals?" - answer: "We start with comprehensive business and market analysis, work closely with stakeholders to understand objectives, establish clear success metrics and KPIs, provide regular progress reports and strategic updates, and adapt our approach based on market feedback and business changes. Our fractional product managers work closely with [fractional CTO services](/services/fractional-cto/) to ensure technical feasibility aligns with product vision, and coordinate with our [app development team](/services/app-web-development/) for seamless product delivery." + answer: "We start with comprehensive business and market analysis, work closely with stakeholders to understand objectives, establish clear success metrics and KPIs, provide regular progress reports and strategic updates, and adapt our approach based on market feedback and business changes. Our fractional product managers work closely with [fractional CTO services](/services/fractional-cto/) to ensure technical feasibility aligns with product vision, and coordinate with our [app development team](/services/app-web-development/) so nothing gets dropped between planning and delivery." overview: headline: Build better products faster diff --git a/content/services/outsourced-developer-staffing/index.md b/content/services/outsourced-developer-staffing/index.md index 58fa74e43..01236f05c 100644 --- a/content/services/outsourced-developer-staffing/index.md +++ b/content/services/outsourced-developer-staffing/index.md @@ -23,7 +23,7 @@ faqs: - question: "What types of developers do you provide?" answer: "We provide full-stack developers, Ruby on Rails specialists, React and frontend developers, mobile developers (iOS/Android), DevOps engineers, QA engineers, and UI/UX designers. All developers have 3+ years of experience and are vetted for both technical skills and communication abilities." - question: "How do you ensure quality and communication?" - answer: "All our developers go through rigorous technical vetting, English proficiency testing, and cultural fit assessment. They follow agile development practices, provide regular progress updates, participate in daily standups, and integrate seamlessly with your existing team and workflows." + answer: "All our developers go through rigorous technical vetting, English proficiency testing, and cultural fit assessment. They follow agile development practices, provide regular progress updates, participate in daily standups, and work inside your existing team and workflows." - question: "What's included in your fully-managed staffing service?" answer: "Our service includes developer sourcing and vetting, skills assessment and matching, onboarding and training, project management oversight, performance monitoring, payroll and benefits administration, and ongoing support. You focus on your product while we handle all staffing complexities. For comprehensive team leadership, consider pairing with our [fractional CTO services](/services/fractional-cto/), and for finding the right long-term hires, our [technical talent recruiting](/services/talent-recruiting-training/) service offers permanent placement solutions." diff --git a/content/services/software-qa-cat/index.md b/content/services/software-qa-cat/index.md index 8f1612349..d0540740f 100644 --- a/content/services/software-qa-cat/index.md +++ b/content/services/software-qa-cat/index.md @@ -11,7 +11,7 @@ cover_image: service-software-qa-cat.jpg menu_custom: icon: submenu-software.svg title: Software QA & CAT - description: Accelerate development, streamline release cycles, and eliminate roadblocks with fully-managed software testing & QA services + description: We write the tests your app never had, then send you a bug report you can actually read - what broke and what it costs to fix metatags: image: og-services-software-qa-cat.jpg @@ -24,7 +24,7 @@ faqs: - question: "What's your approach to QA for different project types?" answer: "We tailor our QA approach based on project needs: agile projects get continuous testing integration, legacy systems receive comprehensive regression testing, mobile apps get device-specific testing, and web applications receive cross-browser compatibility testing. Each project gets a customized QA strategy." - question: "How quickly can your QA team integrate with our development process?" - answer: "Our pre-trained QA team can integrate within 1-2 weeks. We adapt to your existing development workflows, tools, and processes while implementing industry best practices. Most clients see immediate improvements in bug detection and release quality within the first sprint. We work closely with our [app and web development](/services/app-web-development/) team to ensure seamless Ruby on Rails testing integration from the start of development." + answer: "Our pre-trained QA team can integrate within 1-2 weeks. We adapt to your existing development workflows, tools, and processes while implementing industry best practices. Most clients see immediate improvements in bug detection and release quality within the first sprint. We work closely with our [app and web development](/services/app-web-development/) team so Ruby on Rails testing is wired in from the start of development." - question: "Do you provide QA for both web and mobile applications?" answer: "Yes, we provide QA services for web applications, mobile apps (iOS and Android), APIs, and desktop applications. Our team has experience with responsive web testing, mobile device testing, API testing, and cross-platform compatibility validation." diff --git a/content/services/talent-recruiting-training/index.md b/content/services/talent-recruiting-training/index.md index 959beed04..b66cee45b 100644 --- a/content/services/talent-recruiting-training/index.md +++ b/content/services/talent-recruiting-training/index.md @@ -11,7 +11,7 @@ cover_image: service-talent-recruiting-training.jpg menu_custom: icon: submenu-staffing.svg title: Talent Recruiting and Training - description: Scale your development team & simplify the talent acquisition process with top-caliber candidates that are pre-vetted by our team. + description: We screen Rails and React candidates the way we screen our own hires - take-home code and a live pairing session. You interview the short list. metatags: image: og-services-talent-recruiting-training.jpg diff --git a/content/use-cases/accelerate-development-maximize-capacity/index.md b/content/use-cases/accelerate-development-maximize-capacity/index.md index b68a8c858..355903739 100644 --- a/content/use-cases/accelerate-development-maximize-capacity/index.md +++ b/content/use-cases/accelerate-development-maximize-capacity/index.md @@ -39,7 +39,7 @@ While any team can build a high-quality product with enough time, very few can d How we solve it --------------- -The fastest way to expand software engineering capacity is by using a trusted technology partner that can deploy pre-trained developers on-demand at any scale. +The fastest way to expand software engineering capacity is to bring in senior engineers who already know the stack and can start at any scale. Our developers are ready to deploy within weeks (not months), giving companies the ability to accelerate their software development process while still maintaining control over engineering quality. diff --git a/content/use-cases/empower-existing-engineering-team/index.md b/content/use-cases/empower-existing-engineering-team/index.md index b0ee95e9a..6b19044ae 100644 --- a/content/use-cases/empower-existing-engineering-team/index.md +++ b/content/use-cases/empower-existing-engineering-team/index.md @@ -1,7 +1,7 @@ --- title: "Expert Engineering Solutions for Accelerated Software Development" -description: "Empower your team with expert engineers: On-demand Rails/React developers, fractional CTO, no hiring hassle. Boost productivity instantly. Extend now ✓" +description: "Add senior Rails and React engineers to your team in weeks - no hiring process, no management overhead. They ship inside your existing workflow ✓" headline: Extend Capabilities Without the Hassle excerpt: Build better software products faster and increase your engineering manpower without the need for more recruiting, training, onboarding, and management. slug: empower-existing-engineering-team @@ -37,10 +37,10 @@ When a core development team is rushed or overworked, companies risk losing cont ## How we solve it -The easiest & fastest way to grow software development capacity is by using a trusted technology partner that can deploy pre-trained developers on-demand without the need for additional supervision. +Add senior Rails and React engineers without adding management overhead. They ship inside your existing process. Our team of experts are ready to deploy within weeks (not months), giving startups the ability to accelerate software development while maintaining control over their core engineering team. ## The results -We’ve helped empower existing teams in a variety of situations, ranging from early-stage startups to mature enterprise companies. With access to on-demand engineering resources, you can help support your core team, increase their productivity, and make it easier for them to adapt as the environment changes. +We’ve added engineers to teams at early-stage startups and at mature enterprise companies. With access to on-demand engineering resources, you can help support your core team, increase their productivity, and make it easier for them to adapt as the environment changes. diff --git a/docs/projects/2510-seo-content-strategy/20-29-strategy/20.09-content-plan-revision-aug-2026.md b/docs/projects/2510-seo-content-strategy/20-29-strategy/20.09-content-plan-revision-aug-2026.md index e940a31ea..6882cad5a 100644 --- a/docs/projects/2510-seo-content-strategy/20-29-strategy/20.09-content-plan-revision-aug-2026.md +++ b/docs/projects/2510-seo-content-strategy/20-29-strategy/20.09-content-plan-revision-aug-2026.md @@ -290,8 +290,121 @@ Defer it. --- +## 11. P4 — Close the proof gap on the pages outreach lands on + +**Status**: groomed, not scheduled. Added 2026-08-13 from the third-party audit response +(`../seo-review-2026-08-13.md` §8). + +### 11.0 Why this does not violate §1 + +§1 forbids a **content sprint** while outreach is stalled. This is not one: **zero new posts**, no +keyword work, no publishing cadence. It is conversion work on pages that already exist, and it serves +2607 directly — every warm-outreach prospect Paul messages opens the homepage before replying. It is +also consistent with `seo-review-2026-08-13.md` §6's "no new content for SEO reasons", because none of +this is done for rankings. + +Sequence it as **unblocked-by-outreach, not competing with it**. + +### 11.1 The gap in one line + +The hero blames devshops. Everything below it is written in devshop language, and every claim JT makes +about being different is asserted rather than shown — while the competitors JT is positioned against +show more. + +### 11.2 The clichés, with file:line + +| Live JT copy | Where | +|---|---| +| "help take your company to the next level from any stage" | `themes/beaver/layouts/home.html:924` | +| "we help deliver positive outcomes" | homepage service card (`home.html`) | +| "Accelerate development, streamline release cycles, and eliminate roadblocks" | homepage service card | +| "top-caliber candidates that are pre-vetted by our team" | homepage service card | +| "a trusted technology partner … without the need for additional supervision" | homepage use-case card | +| "We seamlessly integrate with existing development teams … our team acts as an extension of your organization" | `content/services/app-web-development/index.md:29` | +| "world-class technology leadership" | `content/services/fractional-cto-cost/index.md:227` | +| "cutting-edge technology" | `content/services/fractional-cto/index.md:39` | +| "Empower your team with expert engineers" | `content/use-cases/empower-existing-engineering-team/index.md:4` | +| "seamless"/"seamlessly" | `fractional-product-management/index.md:28`, `software-qa-cat/index.md:27`, `outsourced-developer-staffing/index.md:26` | +| "World-Class Training" | `themes/beaver/layouts/page/careers.html:398` | + +**The sentence-level collision.** Rubyroid Labs — named in +`../../../90-99-content-strategy/strategy-analysis/90.10-icp-primary-website-target.md` §8b as a +*"dangerous competitor"* — writes: *"We can seamlessly integrate with your in-house team as an +extension."* JT writes: *"We seamlessly integrate with existing development teams … our team acts as an +extension of your organization."* Same sentence, as a company we compete against. + +### 11.3 These are commodity-shop phrases, not industry-standard + +Checked directly, 2026-08-13: + +| | "next level" / "world-class" / "cutting-edge" / "top-caliber" | What they lead with | +|---|---|---| +| **thoughtbot** | none | *"When the stakes are high, experience matters"* | +| **SumatoSoft** | none | *"Engineering you can audit. Code you can scale. Partners you can trust."* | +| **Rubyroid Labs** | "seamlessly", "streamline" only | feature copy | +| **JetThoughts** | **all of them** | strong hero, boilerplate below the fold | + +SumatoSoft's line is the sharpest datapoint: **a competitor states JT's own positioning — auditability, +ownership, trust — more plainly than JT does.** The clichés are not neutral background noise; they place +JT inside the category its own hero paragraph is attacking. + +### 11.4 JT shows less proof than the firms it blames + +| | Named clients in hero region | Case studies | Rating | Public artifacts | +|---|---|---|---|---| +| thoughtbot | 24 logos (Disney, Kickstarter, HBR, Gov.uk) | yes | — | open source, playbook, podcast | +| Rubyroid | Toyota, Volvo, Mastercard | 11+ | "52+ five-star Clutch reviews" | — | +| SumatoSoft | Toyota, Dexai, Beiersdorf | 4 detailed | 98% satisfaction, ISO 27001/9001 | — | +| **JetThoughts** | **none** | 6, buried at `/clients/` | **"4.8/5 by 32 clients" — not linked** | 617 posts, never surfaced as proof | + +Everything JT asserts is self-reported and unverifiable in-page: *"40+ projects rescued"* (none named), +*"95% client retention rate—highest in the industry"* (`content/pages/about-us/index.md:27`), +*"featured in Forbes and Inc."* (no links). The audit's phrase was *"or so they claim"* — that is the +reader's reaction, and it is fair. + +This contradicts our own strategy: `90.10` §5 weights the decision **Trust signals 40% + Transparency +proof 25% = 65% evidence**, and names the artifacts required — *"Sample weekly report, sample SOW, +sample QA report."* + +### 11.5 The artifacts already exist — this is wiring, not writing + +| `90.10` asks for | Already built | +|---|---| +| Sample weekly report | `content/course/tech-for-non-technical-founders-2026/weekly-dev-report-template-founders/` (+ `report-comparison.svg`) | +| Sample SOW | `content/course/…/sow-reading-guide/` — incl. per-milestone IP transfer and the termination clause | +| Code-ownership proof | `content/course/…/ownership-checklist/`, `…/github-aws-database-ownership-checklist/` | +| Rescue credibility | `content/blog/dev-shop-red-flags-checklist/` | +| Clutch profile | `https://clutch.co/profile/jetthoughts` — cited only in a 2016 blog post, never linked from the rating | + +Of the five white-space differentiators `90.10` §8b says **no competitor offers** — plain-English weekly +reports, code-ownership guarantee, termination clause for quality, non-technical QA reports, rescue +specialization — only two reach the homepage, and none as a **showable artifact**. + +### 11.6 Scope when this is scheduled + +1. Replace the cliché lines in 11.2 with plain statements of what JT actually does. +2. Link each differentiator to its existing artifact (11.5) at the point the claim is made. +3. Link `4.8/5 by 32 clients` to the Clutch profile, or drop the number + (see `../seo-review-2026-08-13.md` action #8 — the count is unsourced). +4. Name clients or cases where JT currently asserts *"40+ projects rescued"*. +5. Source or delete *"95% client retention — highest in the industry"*. + +### 11.7 Execution constraints (inherited by whoever runs this) + +- `home.html` / `careers.html` are **template** changes → feature branch, `bin/qtest --changed` + blocking, one PR. +- `content/services/*.md`, `content/use-cases/*.md`, `content/pages/*.md` are **content-only** → + `bin/hugo-build` + rendered scroll gate; skip `qtest`/`test`/`dtest`. +- Marketing copy → the **cold-eyes review gate** applies before handback. +- **Leave client testimonial quotes alone** — those are attributed quotes, not JT's voice. +- **Surgical edit discipline**: this is a de-clichéing and proof-wiring pass, **not** a homepage + redesign. Name the page's thesis first and confirm it is unchanged. + +--- + ## Changelog | Date | Change | |---|---| +| 2026-08-13 | Added §11 (P4 proof gap) from the third-party audit response. Findings: JT uses commodity-devshop language while blaming devshops (one sentence near-identical to competitor Rubyroid Labs); JT shows less checkable proof than thoughtbot/Rubyroid/SumatoSoft; and every proof artifact `90.10` §5 requires already exists inside the course but is not wired to the claims. Groomed, not scheduled. | | 2026-08-07 | Created. Four-agent re-review (market, SEO, competitor, goal-alignment). Supersedes 20.08's allocation/cadence/projection; keeps its GSC analysis. Headline findings: the bet forbids a content sprint while outreach is stalled; the rescue offer page has zero inbound links from 608 posts; 6 queued rows cannibalize existing posts and 1 already did; real capacity is ~6/month not 10-13; the 435-click projection predates AI Overviews. | diff --git a/docs/projects/2510-seo-content-strategy/seo-review-2026-08-13.md b/docs/projects/2510-seo-content-strategy/seo-review-2026-08-13.md index 30556b6b6..34e45c377 100644 --- a/docs/projects/2510-seo-content-strategy/seo-review-2026-08-13.md +++ b/docs/projects/2510-seo-content-strategy/seo-review-2026-08-13.md @@ -116,10 +116,13 @@ spending effort on rankings before Dec 1. So the list is measurement-first, then | **4** | **Investigate the homepage position drop** (9.1 → 20.9 since May). One look at what changed - it is the only page with real brand-intent conversion value. | 1h | Biggest single ranking loss on a page that matters. | | **5** | **Do NOT run title-rewrite wave 2.** Record the experiment as falsified. | 0 | Wave 1 cost real hours and returned impressions loss, not clicks. | | **6** | **Do NOT invest in the rescue keyword cluster before Dec 1.** Reaffirm 20.09 §7. | 0 | 99 impressions / 0 clicks over 90 days confirms the existing call. | +| **7** | **Delete `comprehensive-service-schema.html:101-157`** - the fabricated reviews and the 4.9/23 rating. See §8.2. | 20 min | Policy + FTC exposure. A manual action applies domain-wide, so low service-page traffic does not reduce it. | +| **8** | **Confirm `4.8 / 32` against the live Clutch profile**, then either link the rating to it or drop `aggregateRating`. | 20 min | `reviewCount: 32` has no source in the repo. See §8.2. | +| **9** | **Add `[minify.tdewolff.html] keepQuotes = true`** to `config/_default/hugo.toml`. | 5 min | Cosmetic-for-third-party-tools only - see §8.1. **Not an SEO fix**; do not re-raise it as one. | ### What is explicitly *not* recommended - New content for SEO reasons. At ~5 clicks/day and declining positions, publishing volume is not the constraint. -- Technical SEO work. Sitemap is clean (1,147 URLs, 0 errors), key pages return `PASS` on inspection, schema validates. This is not a crawlability problem. +- Technical SEO work. Sitemap is clean (1,147 URLs, 0 errors), key pages return `PASS` on inspection, schema validates. This is not a crawlability problem. (Schema validates *structurally*; §8.2 found part of its **content** is fabricated. That is a policy risk, not an SEO one, and actions #7-#8 address it on those grounds.) - Chasing the position 13 → 20 decay with on-page fixes until #2 is done. Without trustworthy numbers there is no way to tell a fix from noise. --- @@ -129,3 +132,109 @@ spending effort on rankings before Dec 1. So the list is measurement-first, then > Organic is ~5 clicks/day and positions slid 13 → 20 since April; the "5k sessions" > baseline is ~90% bot traffic and conversions are untracked. Fix measurement (2h), > then leave SEO alone until outreach is unblocked. + +--- + +## 8. Third-party audit response (2026-08-13) + +A third-party AI-SEO tool (`lightsite.agent`) scored jetthoughts.com **60/100, "Multiple Organ +Failure"**, against competitors at 39 and 100 (lower is better on its scale). Every claim was verified +against the live site and against GSC. **Four of its five claims are false.** This section exists so the +same investigation is never run twice. + +### 8.1 Claim-by-claim verdict + +| Audit claim | Verdict | Evidence | +|---|---|---| +| "There are no canonical tags" | **FALSE** | `rel=canonical` emitted on every page from `layouts/partials/seo/enhanced-meta-tags.html:71` via `themes/beaver/layouts/baseof.html:9`. GSC `inspect_url` returns a matching `user_canonical` on every URL tested. | +| "Zero structured data on any page we crawled" | **FALSE** | Organization, Service, FAQPage, Article and BreadcrumbList all live. GSC rich results **PASS**, detected types `Breadcrumbs` + `Review snippets`. | +| "Meta description is basically a shrug / lazy placeholder" | **FALSE** | Descriptions are specific and page-tailored throughout. | +| "No canonical tag - duplicates haunt you" | **FALSE** | `www.jetthoughts.com` → 301 → apex; `http://` → 301 → `https://`. No duplicate-host drift. | +| "Copy uses the exact same phrases as the agencies they claim to replace" | **TRUE** | Substantiated and expanded in `20.09` §11. | + +#### Root cause of the false negatives + +`config/_default/hugo.toml:65` sets `minifyOutput = true`. Hugo's minifier drops quotes on attribute +values that contain no spaces: + +``` +rel=canonical (not rel="canonical") +name=description (not name="description") +type=application/ld+json (not type="application/ld+json") +``` + +Every check the tool failed (M, C, SCHEMA) matches a **quoted attribute**. Every check it passed (T, H1) +reads **element content**. That mapping is exact - its parser is regex-based and requires quotes. The +output is valid HTML5 and Google parses it correctly, which GSC confirms. + +**Action #9 (`keepQuotes = true`) is a cosmetic hedge against naive third-party parsers, not an SEO fix.** +The argument for it is commercial, not technical: JT sells technical credibility, and a prospect running +any free audit tool currently sees "invisible to AI assistants". Cost is ~1-2% page weight. +Note `config/test/hugo.toml:11` sets `minifyOutput = false`, so **the test suite cannot verify #9** - it +needs a `hugo --environment production` build and a byte-size comparison (homepage baseline: 124,256 B). + +### 8.2 What the audit missed - fabricated review markup + +The audit asked only "is schema missing?", never "is the schema that exists honest?". It is not. + +`themes/beaver/layouts/partials/seo/comprehensive-service-schema.html:101-157` publishes, on all 12 +`/services/` pages: + +- `aggregateRating` of **4.9 / 23 reviews** +- Two `Review` objects authored by **"Technology Executive" (CTO)** and **"Startup Founder" (CEO)** - + non-existent people, with `reviewBody` text generated per service via `printf`, hardcoded + `datePublished` of `2024-11-15` / `2024-10-22`, and 5/5 ratings. + +Separately, `themes/beaver/layouts/partials/seo/enhanced-organization-schema.html:83-88` emits a +hardcoded `aggregateRating` of **4.8 / 32** site-wide across ~1,147 URLs. Service pages therefore +publish **two contradictory ratings at once**. + +**Exposure**: Google's structured-data policy prohibits fake and self-serving reviews; a manual action +strips rich results **domain-wide**, so §4's "service pages get 1 click / 90 days" does *not* reduce the +risk. The FTC Rule on Consumer Reviews and Testimonials also covers fabricated testimonials. It further +breaks this repo's own standing rule - *"Zero unsupported claims: all assertions must have citations."* + +`grep -rn aggregateRating test/` returns nothing, so action #7 is a pure deletion with no test to update. + +**Decision taken 2026-08-13 (Paul):** remove the fabricated block only; keep `4.8 / 32` and the real +named-client reviews from `data/testimonials.yaml`. + +**Residual risk, recorded deliberately:** Google disallows self-serving review markup about the +organization on the organization's own site regardless of whether the numbers are true. And +`reviewCount: 32` has no provenance in the repo - the only source is `data/company.yaml:11`, +*"Top-rated on Clutch.co (4.8/5 rating)"*, which carries a rating but **no count**. Action #8 resolves +this; if Clutch shows a different count, JT is publishing a wrong number. + +### 8.2b Resolution (2026-08-14) - actions #7-#9 closed + +**Action #8 found a real defect.** The live Clutch profile shows **4.8 out of 5 +from 9 reviews**. The rating was correct; `reviewCount: 32` was overstated ~3.5x +and was published in structured data on ~1,147 URLs. It is now `9` in +`enhanced-organization-schema.html`, with the source URL and verification date in +a comment. On the marketing pages the count is gone entirely and the rating links +to the Clutch profile - a linked rating beats a bigger unlinked number, which is +20.09 §11's thesis. + +Note `data/course_banned_strings.yaml:65` already bans "4.8/5" in course content +as a *"volatile third-party review score"*. The course side had learned this; the +marketing side had not. + +**Action #7** - `comprehensive-service-schema.html:101-157` deleted. Verified in a +production build: `/services/fractional-cto/` now carries only the sourced 4.8/9, +no invented authors, and no contradictory 4.9. + +**Action #9** - `keepQuotes = true` added. Verified against a production build: +`rel="canonical"`, `name="description"`, `type="application/ld+json"` all quoted. +Homepage 124,256 → 125,988 bytes (+1.4%). + +**Gate gap found while doing this**: the default screenshot tolerance is 2% +(`test/application_system_test_case.rb:87`), so a four-word link change (~0.24% of +the frame) passes without re-recording the baseline. A green visual suite means +"no change larger than 2%", not "no change". Recorded in `.okf/build/test-gates.md`. + +### 8.3 Also unsourced (out of scope, logged) + +Same file, `additionalProperty` block: `Client Retention Rate 95%`, `Success Rate 92%`, +`Years of Experience 13+` are published as schema `PropertyValue` with no cited source. +`content/pages/about-us/index.md:27` claims *"95% client retention rate—highest in the industry for +development agencies"* - a superlative with no source. Fold into action #8 when it runs. diff --git a/test/fixtures/screenshots/linux/desktop/homepage/_services.png b/test/fixtures/screenshots/linux/desktop/homepage/_services.png index 298f54b71..fdf42a7d1 100644 Binary files a/test/fixtures/screenshots/linux/desktop/homepage/_services.png and b/test/fixtures/screenshots/linux/desktop/homepage/_services.png differ diff --git a/test/fixtures/screenshots/linux/desktop/nav/services.png b/test/fixtures/screenshots/linux/desktop/nav/services.png index 900a5ffa2..8d3876c7e 100644 Binary files a/test/fixtures/screenshots/linux/desktop/nav/services.png and b/test/fixtures/screenshots/linux/desktop/nav/services.png differ diff --git a/test/fixtures/screenshots/linux/desktop/services/_overview.png b/test/fixtures/screenshots/linux/desktop/services/_overview.png index f5150fed6..670f77788 100644 Binary files a/test/fixtures/screenshots/linux/desktop/services/_overview.png and b/test/fixtures/screenshots/linux/desktop/services/_overview.png differ diff --git a/test/fixtures/screenshots/linux/desktop/services/_services.png b/test/fixtures/screenshots/linux/desktop/services/_services.png index f65f394bf..85ac75d92 100644 Binary files a/test/fixtures/screenshots/linux/desktop/services/_services.png and b/test/fixtures/screenshots/linux/desktop/services/_services.png differ diff --git a/test/fixtures/screenshots/linux/desktop/services/_testimonials-header.png b/test/fixtures/screenshots/linux/desktop/services/_testimonials-header.png index 4883b824d..1b2153ea4 100644 Binary files a/test/fixtures/screenshots/linux/desktop/services/_testimonials-header.png and b/test/fixtures/screenshots/linux/desktop/services/_testimonials-header.png differ diff --git a/test/fixtures/screenshots/macos/desktop/homepage/_services.png b/test/fixtures/screenshots/macos/desktop/homepage/_services.png index fd4338742..fe7f41165 100644 Binary files a/test/fixtures/screenshots/macos/desktop/homepage/_services.png and b/test/fixtures/screenshots/macos/desktop/homepage/_services.png differ diff --git a/test/fixtures/screenshots/macos/desktop/nav/services.png b/test/fixtures/screenshots/macos/desktop/nav/services.png index ecc58bdae..020c65499 100644 Binary files a/test/fixtures/screenshots/macos/desktop/nav/services.png and b/test/fixtures/screenshots/macos/desktop/nav/services.png differ diff --git a/test/fixtures/screenshots/macos/desktop/services/_overview.png b/test/fixtures/screenshots/macos/desktop/services/_overview.png index 6ceebedd8..fd5d57285 100644 Binary files a/test/fixtures/screenshots/macos/desktop/services/_overview.png and b/test/fixtures/screenshots/macos/desktop/services/_overview.png differ diff --git a/test/fixtures/screenshots/macos/desktop/services/_services.png b/test/fixtures/screenshots/macos/desktop/services/_services.png index eb0955ec7..91b9c407b 100644 Binary files a/test/fixtures/screenshots/macos/desktop/services/_services.png and b/test/fixtures/screenshots/macos/desktop/services/_services.png differ diff --git a/test/fixtures/screenshots/macos/desktop/services/_testimonials-header.png b/test/fixtures/screenshots/macos/desktop/services/_testimonials-header.png index bbb453b22..139dade50 100644 Binary files a/test/fixtures/screenshots/macos/desktop/services/_testimonials-header.png and b/test/fixtures/screenshots/macos/desktop/services/_testimonials-header.png differ diff --git a/test/integration/hugo_pipeline_test.rb b/test/integration/hugo_pipeline_test.rb index ab6aae4bc..6cea7b6c0 100644 --- a/test/integration/hugo_pipeline_test.rb +++ b/test/integration/hugo_pipeline_test.rb @@ -83,6 +83,20 @@ def prod_css_files(pattern = "homepage.*.css") Dir["#{HUGO_PROD_DIR}/css/#{pattern}"] end + # Matches an attribute whether or not the minifier quoted its value. + # + # tdewolff drops quotes on values with no special characters, so production + # HTML emitted `rel=stylesheet` / `crossorigin=anonymous` bare while + # `integrity="sha256-..."` stayed quoted (base64 contains / and +). Three + # tests here matched the bare form literally and broke the day + # `[minify.tdewolff.html] keepQuotes = true` was turned on - they were + # asserting a minifier setting, not the behaviour under test (SRI and + # crossorigin present on production assets). Per the repo's testing rule: + # assert the shape, not the configuration. + def attr(name, value) + /#{name}=["']?#{Regexp.escape(value)}["']?/ + end + # -- Tests: CSS integrity attributes ------------------------------------ # css-processor.html adds integrity= to tags ONLY in production @@ -145,7 +159,7 @@ def test_css_content_is_minified_in_production def test_js_has_integrity_and_crossorigin_in_production assert prod_html.include?('integrity="sha256-'), "Prod should have integrity attributes on script tags" - assert prod_html.include?("crossorigin=anonymous"), + assert_match attr("crossorigin", "anonymous"), prod_html, "Prod should have crossorigin=anonymous on script tags" end @@ -160,14 +174,14 @@ def test_js_no_integrity_or_crossorigin_in_development # css-processor.html wraps integrity in the tag def test_stylesheet_links_have_integrity_in_production - integrity_links = prod_html.scan(%r{]*rel=stylesheet[^>]*integrity=[^>]*>}) + integrity_links = prod_html.scan(/]*#{attr("rel", "stylesheet")}[^>]*integrity=[^>]*>/) assert_operator integrity_links.length, :>=, 1, "Prod should have at least 1 link rel=stylesheet tag with integrity" end def test_preload_links_have_integrity_in_production - preload_links = prod_html.scan(%r{]*rel=preload[^>]*as=style[^>]*integrity=[^>]*>}) + preload_links = prod_html.scan(/]*#{attr("rel", "preload")}[^>]*#{attr("as", "style")}[^>]*integrity=[^>]*>/) assert_operator preload_links.length, :>=, 1, "Prod should have at least 1 link rel=preload as=style with integrity" diff --git a/test/unit/marketing_copy_test.rb b/test/unit/marketing_copy_test.rb new file mode 100644 index 000000000..3ba04ecbb --- /dev/null +++ b/test/unit/marketing_copy_test.rb @@ -0,0 +1,127 @@ +# frozen_string_literal: true + +require "test_helper" + +# Marketing-copy voice guard. +# +# The site's hero blames devshops ("Your dev shop stopped delivering") while the +# copy below it used the same commodity-agency language as the devshops we +# compete against - one sentence was near-identical to a competitor's. See +# docs/projects/2510-seo-content-strategy/20-29-strategy/20.09-content-plan-revision-aug-2026.md §11. +# +# This is a ratchet, same idea as data/course_banned_strings.yaml but for the +# marketing surfaces: once a phrase is removed it may never come back. The +# blurbs are duplicated 3-4x across config, content frontmatter and two +# templates with no data binding, so a hand-fix silently leaves stale copies - +# this test is what makes the lockstep edit verifiable. +# +# Banned set is the unambiguous subset of +# docs/90-99-content-strategy/strategy-analysis/90.11-voice-guide.md §3. +# Context-dependent bans ("transform", "discover", "comprehensive") are +# deliberately excluded: they need human judgement and would make this gate +# noisy. Test the shape, not the config. +class MarketingCopyTest < Minitest::Test + REPO_ROOT = File.expand_path("../..", __dir__) + + # Surfaces a prospect actually reads before deciding. content/blog/** is + # excluded (540+ imported posts, audited separately per the dev.to ICP gate) + # and content/clients/** is a KNOWN remaining offender - "to the next level" + # in two case-study excerpts - deferred, not covered here. Add it when that + # work is scheduled rather than pretending this gate already covers it. + SURFACES = [ + "config/_default/hugo.toml", + "content/_index.md", + "content/pages/**/*.md", + "content/services/**/*.md", + "content/use-cases/**/*.md", + "themes/beaver/layouts/home.html", + "themes/beaver/layouts/page/*.html" + ].freeze + + BANNED = { + "seamless" => "voice guide §3 banned adjective - say what actually plugs into what", + "world-class" => "voice guide §3 banned adjective - unfalsifiable self-praise", + "cutting-edge" => "voice guide §3 banned adjective - use 'new' or name the thing", + "best-in-class" => "voice guide §3 banned adjective", + "state-of-the-art" => "voice guide §3 banned adjective", + "top-caliber" => "commodity-agency filler - describe the actual screen", + "next level" => "commodity-agency filler - name the concrete outcome", + "positive outcomes" => "commodity-agency filler - say which outcome", + "eliminate roadblocks" => "commodity-agency filler - name the roadblock", + "trusted technology partner" => "commodity-agency filler - trust is shown, not claimed", + "supercharge" => "voice guide §3 banned adjective", + "revolutionize" => "voice guide §3 banned adjective", + "game-changer" => "voice guide §3 banned phrase", + "synergy" => "voice guide §3 banned adjective", + "holistic" => "voice guide §3 banned adjective", + "empower" => "voice guide §3 banned verb - 'your team can now ...'", + # Factual ratchet, not a voice rule. The site published "4.8/5 by 32 + # clients" / "Based on 32 client reviews" / reviewCount:32 while the live + # Clutch profile showed 9 (verified 2026-08-14). The count had no source + # anywhere in the repo. It survived a first fix pass because it was worded + # three different ways in three files - hence all three spellings here. + "32 client" => "false review count - Clutch shows 9, link the profile instead", + "by 32" => "false review count - Clutch shows 9, link the profile instead", + "thirty-two clients" => "false review count - Clutch shows 9, link the profile instead" + }.freeze + + # Surfaces that render the rating block but are not marketing prose pages. + EXTRA_SURFACES = ["themes/beaver/layouts/partials/page/testimonials.html"].freeze + + def test_marketing_surfaces_carry_no_banned_phrases + violations = marketing_files.flat_map { |path| banned_phrases_in(path) } + + assert_empty violations.sort, + "Banned marketing phrases found. These read as the commodity-devshop " \ + "language the homepage hero blames - replace the promise with the " \ + "mechanic (voice guide §3):\n " + violations.sort.join("\n ") + end + + def test_every_declared_surface_matches_at_least_one_file + unmatched = (SURFACES + EXTRA_SURFACES).reject { |pattern| Dir.glob(File.join(REPO_ROOT, pattern)).any? } + + assert_empty unmatched, + "Surface patterns match nothing on disk - a path moved and this guard " \ + "went silently blind: #{unmatched.join(", ")}" + end + + private + + def marketing_files + (SURFACES + EXTRA_SURFACES) + .flat_map { |pattern| Dir.glob(File.join(REPO_ROOT, pattern)) } + .uniq + .select { |p| File.file?(p) } + end + + # Machine identifiers, not reader-facing prose. A menu `identifier`, a + # frontmatter `slug`/`url`, or an alias legitimately keeps a banned word + # because renaming it would mean a redirect bridge, which the repo forbids. + IDENTIFIER_LINE = /^\s*(identifier\s*=|slug:|url:|pageRef\s*=|aliases:|-\s*\/)/ + + def banned_phrases_in(path) + relative = path.sub("#{REPO_ROOT}/", "") + + File.readlines(path, encoding: "bom|utf-8").each_with_index.flat_map do |line, index| + next [] if line.match?(IDENTIFIER_LINE) + + haystack = scrub(line).downcase + + BANNED.filter_map do |phrase, reason| + "#{relative}:#{index + 1} #{phrase.inspect} - #{reason}" if haystack.include?(phrase) + end + end + end + + # Slugs, URLs and asset names legitimately keep banned words - + # /use-cases/empower-existing-engineering-team/, the SVG + # theme/world-class-training, and cover_image: empower-...jpg are + # identifiers, not prose. Renaming them would mean redirect bridges or asset + # churn, which buys nothing. Drop both shapes before matching: any token + # containing a slash, and any token ending in an asset extension. + ASSET_TOKEN = /\S+\.(?:jpe?g|png|svg|webp|gif|ico)\b/i + + def scrub(line) + line.gsub(%r{\S*/\S*}, " ").gsub(ASSET_TOKEN, " ") + end +end diff --git a/themes/beaver/layouts/home.html b/themes/beaver/layouts/home.html index 4bbcfd71e..5440baffe 100644 --- a/themes/beaver/layouts/home.html +++ b/themes/beaver/layouts/home.html @@ -188,11 +188,15 @@

Rated 4.8/5 by 32 clients4.8/5 on Clutch - - and most of them stay over 3 years + - and most clients stay over 3 years

@@ -314,8 +318,11 @@

Senior teams shipping and rescuing Ruby on Rails and React products since 2011 - - test-driven, with weekly reports in plain - English. If your current dev shop is + test-driven, with + weekly reports in plain English. If your current dev shop is failing, start with

- Get on-demand access to a CTO to help - guide your technical vision, - accelerate team-building, and improve - development team operations. + A senior engineer reviews your + codebase and your team, then tells + you in plain English what to fix + first. $5K-$15K/month, starting in + days.

- Whether you’re a startup building new - products or an established business - upgrading existing systems, we help - deliver positive outcomes. + Rails and React builds, test-driven + from the first commit. You own the + code after every milestone.

- Get on-demand access to a product - expert to help design UX, plan & - prioritize your roadmap, and manage - development schedules. + A product lead who runs your roadmap + and writes the specs, so your + developers stop guessing what to + build next.

- Increase your development capacity - & reduce administrative workloads - with pre-trained engineers that are - ready to deploy within weeks. + Senior Rails and React engineers + join your team in weeks. They follow + your process, and you keep control + of the code.

- Scale your development team & - simplify the talent acquisition - process with top-caliber candidates - that are pre-vetted by our team. + We screen Rails and React candidates + the way we screen our own hires - + take-home code and a live pairing + session. You interview the short + list.

- Our team has a tremendous amount - of experience helping startups - thrive. Whether it’s - pre-revenue, seed stage, or - post-funding, we can help take - your company to the next level - from any stage. + Pre-revenue or post-raise, the + engineering problem is + different at each stage. We + have shipped through both and + adjust what we do to match.

diff --git a/themes/beaver/layouts/page/careers.html b/themes/beaver/layouts/page/careers.html index 22e4e7b9a..7229c0329 100644 --- a/themes/beaver/layouts/page/careers.html +++ b/themes/beaver/layouts/page/careers.html @@ -266,13 +266,11 @@

- Unlike larger development agencies, we - aim to create a curated team - environment that’s familiar, - supportive, and empowering. Everyone - on our team knows each other well and - collaborates closely (whether remote - or in-person). + We keep the team small enough that + everyone knows each other and works + together closely, remote or + in-person. Larger agencies rotate + people between accounts; we do not.

@@ -395,18 +393,18 @@

- World-Class Training + Training You Actually Get

- A key part of what makes JetThoughts - successful is our proprietary systems - for training, onboarding, and managing - the software development process. - Learn development best practices from - a top-tier digital agency. + You are paired with a senior engineer + from your first week, and code review + is where most of the learning + happens. Our onboarding and delivery + process is written down, so you are + not guessing how we work.

diff --git a/themes/beaver/layouts/page/services.html b/themes/beaver/layouts/page/services.html index 3bb99bb9c..e9e7364ed 100644 --- a/themes/beaver/layouts/page/services.html +++ b/themes/beaver/layouts/page/services.html @@ -177,10 +177,9 @@

- Whether you’re a startup building new - products or an established business - upgrading existing systems, we help - deliver positive outcomes. + Rails and React builds, test-driven + from the first commit. You own the + code after every milestone.

- Scale your development team & - simplify the talent acquisition - process with top-caliber candidates - that are pre-vetted by our team. + We screen Rails and React candidates + the way we screen our own hires - + take-home code and a live pairing + session. You interview the short + list.

Your MVP looks finished but keeps breaking.
NO CONTRACT · SCORECARD IN 48H
    -
  • Clients rated us4.8 / 5
  • +
  • Rated on Clutch4.8 / 5
  • Average relationship5 years
  • Shipping Railssince 2011
@@ -120,7 +120,7 @@

Foundation Reset

Why JetThoughts

We've been shipping Ruby on Rails since 2011. We use AI-assisted development to move faster and keep costs honest - which is how we can offer a full rescue at $7,500 when traditional agencies quote $25K-$55K for the same work.

-

Thirty-two clients rated us 4.8 out of 5, and our average client relationship runs five years. Paul, our CEO, sits on every call as your fractional CTO and turns what the developers are doing into decisions you can actually make - so you stop guessing whether your team is telling you the truth.

+

Our clients rate us 4.8 out of 5 on Clutch, and our average client relationship runs five years. Paul, our CEO, sits on every call as your fractional CTO and turns what the developers are doing into decisions you can actually make - so you stop guessing whether your team is telling you the truth.

You've been burned once. The whole point of the free audit is that you find out where you stand first - with a senior engineer who has no reason to tell you anything but the truth.

Book your free Rescue Context Call diff --git a/themes/beaver/layouts/partials/page/testimonials.html b/themes/beaver/layouts/partials/page/testimonials.html index d55140e44..f3369b472 100644 --- a/themes/beaver/layouts/partials/page/testimonials.html +++ b/themes/beaver/layouts/partials/page/testimonials.html @@ -148,7 +148,15 @@

data-node="d4wp9kxy1uav">
-

Based on 32 client reviews

+

+ Based on + verified Clutch reviews +

diff --git a/themes/beaver/layouts/partials/seo/comprehensive-service-schema.html b/themes/beaver/layouts/partials/seo/comprehensive-service-schema.html index 55023a757..cf4ff9eb5 100644 --- a/themes/beaver/layouts/partials/seo/comprehensive-service-schema.html +++ b/themes/beaver/layouts/partials/seo/comprehensive-service-schema.html @@ -98,63 +98,6 @@ "offerCount" "2" "availability" "https://schema.org/InStock" ) - "aggregateRating" (dict - "@type" "AggregateRating" - "ratingValue" "4.9" - "reviewCount" "23" - "bestRating" "5" - "worstRating" "1" - "ratingExplanation" "Based on client testimonials and project success metrics from 2022-2024" - ) - "review" (slice - (dict - "@type" "Review" - "@id" (printf "%s#review-1" .Permalink) - "itemReviewed" (dict - "@type" "Service" - "@id" (printf "%s#service" .Permalink) - "name" .Title - ) - "reviewRating" (dict - "@type" "Rating" - "ratingValue" "5" - "bestRating" "5" - "worstRating" "1" - ) - "author" (dict - "@type" "Person" - "name" "Technology Executive" - "jobTitle" "CTO" - ) - "reviewBody" (printf "Exceptional %s that delivered measurable results and exceeded expectations. The team's expertise in Ruby on Rails and strategic guidance transformed our technical capabilities." (lower $serviceType)) - "datePublished" "2024-11-15" - "publisher" (dict - "@type" "Organization" - "name" "Client Testimonials" - ) - ) - (dict - "@type" "Review" - "@id" (printf "%s#review-2" .Permalink) - "itemReviewed" (dict - "@type" "Service" - "@id" (printf "%s#service" .Permalink) - "name" .Title - ) - "reviewRating" (dict - "@type" "Rating" - "ratingValue" "5" - "bestRating" "5" - ) - "author" (dict - "@type" "Person" - "name" "Startup Founder" - "jobTitle" "CEO" - ) - "reviewBody" (printf "JetThoughts %s helped us scale from a 3-person team to 15 engineers while maintaining code quality and team productivity. Outstanding results." $serviceType) - "datePublished" "2024-10-22" - ) - ) -}} {{/* Build conditional property values based on service type */}} diff --git a/themes/beaver/layouts/partials/seo/enhanced-organization-schema.html b/themes/beaver/layouts/partials/seo/enhanced-organization-schema.html index 4ab77b0e1..c56e0ab72 100644 --- a/themes/beaver/layouts/partials/seo/enhanced-organization-schema.html +++ b/themes/beaver/layouts/partials/seo/enhanced-organization-schema.html @@ -82,8 +82,11 @@ "aggregateRating": { "@type": "AggregateRating", + {{/* Sourced from https://clutch.co/profile/jetthoughts - verified 2026-08-14. + reviewCount was "32" with no source anywhere in the repo; Clutch shows 9. + Re-check the live profile before changing either number. */}} "ratingValue": "4.8", - "reviewCount": "32", + "reviewCount": "9", "bestRating": "5", "worstRating": "1" }{{ with .Site.Params.testimonials }},