{"id":400914,"date":"2026-11-13T13:46:22","date_gmt":"2026-11-13T13:46:22","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/anwp-tennis-leagues\/"},"modified":"2026-11-13T13:45:52","modified_gmt":"2026-11-13T13:45:52","slug":"anwp-tennis-leagues","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/anwp-tennis-leagues\/","author":15755214,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.8.2","stable_tag":"0.8.2","tested":"7.1.4","requires":"6.5","requires_php":"7.4","requires_plugins":null,"header_name":"AnWP Tennis Leagues","header_author":"Andrei Strekozov <anwppro>","header_description":"Manage tennis, padel, squash, table tennis, pickleball and badminton competitions: players, matches with set scores, tournaments and draws, standings and rankings.","last_updated":"2026-11-13 13:45:52","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/anwp.pro\/docs\/tennis-leagues\/","header_author_uri":"https:\/\/anwp.pro","rating":0,"author_block_rating":0,"active_installs":0,"downloads":59,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.8.2":{"tag":"0.8.2","author":"anwppro","date":"2026-11-13 13:45:52","revision":3800500}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3800500,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3800500,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon.svg":{"filename":"icon.svg","revision":3800500,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3800500,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3800500,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{"blueprint.json":{"filename":"blueprint.json","revision":3800501,"resolution":false,"location":"assets","locale":"","contents":"{\"$schema\":\"https:\\\/\\\/playground.wordpress.net\\\/blueprint-schema.json\",\"meta\":{\"title\":\"AnWP Tennis Leagues - Live Preview\",\"description\":\"Installs AnWP Tennis Leagues with its sample data (a tennis club championship with a knockout draw and a league, a padel league, a pickleball box league) and opens the championship page.\",\"author\":\"anwppro\",\"categories\":[\"Sports\"]},\"landingPage\":\"\\\/tennis-competition\\\/club-championship\\\/\",\"preferredVersions\":{\"php\":\"8.3\",\"wp\":\"latest\"},\"login\":true,\"steps\":[{\"step\":\"setSiteOptions\",\"options\":{\"blogname\":\"Riverside Racket Club\",\"permalink_structure\":\"\\\/%postname%\\\/\"}},{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"anwp-tennis-leagues\"},\"options\":{\"activate\":true}},{\"step\":\"runPHP\",\"code\":\"<?php\\nrequire '\\\/wordpress\\\/wp-load.php';\\nwp_set_current_user( 1 );\\nanwp_tl()->setup->run(\\n\\tarray(\\n\\t\\t'sport'       => AnwpTL_Types::SPORT_TENNIS,\\n\\t\\t'club'        => array( 'mode' => AnwpTL_Options::CLUB_MODE_MULTI ),\\n\\t\\t'competition' => null,\\n\\t\\t'sample'      => AnwpTL_Sample_Data::BLOCKS,\\n\\t)\\n);\\nflush_rewrite_rules();\\n\"}]}"}},"all_blocks":{"anwp-tl\/draw":{"$schema":"https:\/\/schemas.wp.org\/trunk\/block.json","apiVersion":3,"name":"anwp-tl\/draw","title":"Competition draw","category":"anwp-tl","description":"One knockout stage as a bracket - the same draw the competition page shows.","keywords":["bracket","knockout","tournament"],"textdomain":"anwp-tennis-leagues","attributes":{"stage_id":{"type":"integer","default":0},"view":{"type":"string","enum":["focus","full"],"default":"focus"},"title":{"type":"string","default":""},"print":{"type":"boolean","default":true}},"supports":{"customClassName":true,"html":false},"editorScript":"anwp-tl-blocks","editorStyle":["anwp-tl-public","anwp-tl-blocks-editor"]},"anwp-tl\/matches":{"$schema":"https:\/\/schemas.wp.org\/trunk\/block.json","apiVersion":3,"name":"anwp-tl\/matches","title":"Match list","category":"anwp-tl","description":"Fixtures and results. Any mix of filters - leave them all empty to list every public match.","keywords":["matches","fixtures","results","calendar","schedule"],"textdomain":"anwp-tennis-leagues","attributes":{"competition_id":{"type":"integer","default":0},"season_id":{"type":"integer","default":0},"stage_id":{"type":"integer","default":0},"player_id":{"type":"integer","default":0},"pair_id":{"type":"integer","default":0},"club_id":{"type":"integer","default":0},"print":{"type":"boolean","default":true}},"supports":{"customClassName":true,"html":false},"editorScript":"anwp-tl-blocks","editorStyle":["anwp-tl-public","anwp-tl-blocks-editor"]},"anwp-tl\/player":{"$schema":"https:\/\/schemas.wp.org\/trunk\/block.json","apiVersion":3,"name":"anwp-tl\/player","title":"Player card","category":"anwp-tl","description":"One player or pair, with a link to their page.","keywords":["player","pair","profile","card"],"textdomain":"anwp-tennis-leagues","attributes":{"player_id":{"type":"integer","default":0},"pair_id":{"type":"integer","default":0},"title":{"type":"string","default":""}},"supports":{"customClassName":true,"html":false},"editorScript":"anwp-tl-blocks","editorStyle":["anwp-tl-public","anwp-tl-blocks-editor"]},"anwp-tl\/standings":{"$schema":"https:\/\/schemas.wp.org\/trunk\/block.json","apiVersion":3,"name":"anwp-tl\/standings","title":"Standings table","category":"anwp-tl","description":"One round robin or group stage as a table.","keywords":["standings","table","league","group"],"textdomain":"anwp-tennis-leagues","attributes":{"stage_id":{"type":"integer","default":0},"title":{"type":"string","default":""},"print":{"type":"boolean","default":true}},"supports":{"customClassName":true,"html":false},"editorScript":"anwp-tl-blocks","editorStyle":["anwp-tl-public","anwp-tl-blocks-editor"]}},"tagged_versions":["0.8.2"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3800500,"resolution":"1","location":"assets","locale":"","width":2560,"height":1600},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3800500,"resolution":"2","location":"assets","locale":"","width":2560,"height":1600},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3800500,"resolution":"3","location":"assets","locale":"","width":2560,"height":1600},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3800500,"resolution":"4","location":"assets","locale":"","width":2560,"height":1600},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3800500,"resolution":"5","location":"assets","locale":"","width":2560,"height":1600},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3800500,"resolution":"6","location":"assets","locale":"","width":2560,"height":1600}},"screenshots":{"1":"A competition page with its bracket.","2":"A public match page with the preview: form, head-to-head and workload.","3":"A player page with next matches, latest results and the match profile.","4":"A knockout draw on the admin screen, every card linked to its match.","5":"The Result box on a match: the grid follows the sport's rules.","6":"The Dashboard: what needs you first, what's left to play and the latest results."}},"plugin_section":[],"plugin_tags":[11108,233524,233525,11932,14116],"plugin_category":[],"plugin_contributors":[153106],"plugin_business_model":[],"class_list":["post-400914","plugin","type-plugin","status-publish","hentry","plugin_tags-league","plugin_tags-padel","plugin_tags-pickleball","plugin_tags-tennis","plugin_tags-tournament","plugin_contributors-anwppro","plugin_committers-anwppro"],"banners":{"banner":"https:\/\/ps.w.org\/anwp-tennis-leagues\/assets\/banner-772x250.png?rev=3800500","banner_2x":"https:\/\/ps.w.org\/anwp-tennis-leagues\/assets\/banner-1544x500.png?rev=3800500","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":"https:\/\/ps.w.org\/anwp-tennis-leagues\/assets\/icon.svg?rev=3800500","icon":"https:\/\/ps.w.org\/anwp-tennis-leagues\/assets\/icon.svg?rev=3800500","icon_2x":false,"generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/anwp-tennis-leagues\/assets\/screenshot-1.png?rev=3800500","caption":"A competition page with its bracket."},{"src":"https:\/\/ps.w.org\/anwp-tennis-leagues\/assets\/screenshot-2.png?rev=3800500","caption":"A public match page with the preview: form, head-to-head and workload."},{"src":"https:\/\/ps.w.org\/anwp-tennis-leagues\/assets\/screenshot-3.png?rev=3800500","caption":"A player page with next matches, latest results and the match profile."},{"src":"https:\/\/ps.w.org\/anwp-tennis-leagues\/assets\/screenshot-4.png?rev=3800500","caption":"A knockout draw on the admin screen, every card linked to its match."},{"src":"https:\/\/ps.w.org\/anwp-tennis-leagues\/assets\/screenshot-5.png?rev=3800500","caption":"The Result box on a match: the grid follows the sport's rules."},{"src":"https:\/\/ps.w.org\/anwp-tennis-leagues\/assets\/screenshot-6.png?rev=3800500","caption":"The Dashboard: what needs you first, what's left to play and the latest results."}],"raw_content":"<!--section=description-->\n<p>AnWP Tennis Leagues is for clubs, academies, federations and amateur leagues that run their own racket-sport competitions. You enter the players and the results. The plugin keeps the draws, tables and player records, and puts them on your site.<\/p>\n\n<h4>6 sports, scored properly<\/h4>\n\n<ul>\n<li>Tennis and padel score in sets of games, with tiebreaks, no-ad, golden point, a 10-point final-set tiebreak or a match tiebreak as the decider.<\/li>\n<li>Squash, table tennis, pickleball and badminton score in games to 11, 15 or 21, won by 2, with badminton capped at 30.<\/li>\n<li>A score that couldn't happen under the match's rules is refused, and the message names the set it's in. 8-6 in a set with a tiebreak won't save.<\/li>\n<li>Six match statuses: Scheduled, Finished, Retired, Walkover, Default and Cancelled. The winner of a finished match is worked out from the score.<\/li>\n<li>Team ties, for club leagues played over 1 to 9 rubbers.<\/li>\n<li>Each match keeps a copy of the rules it was created under, so changing a competition later doesn't rewrite matches that already exist.<\/li>\n<\/ul>\n\n<h4>Competitions and draws<\/h4>\n\n<ul>\n<li>Players, doubles pairs, clubs and their courts, with surfaces and indoor courts.<\/li>\n<li>Competitions with seasons. A new competition comes with this year's season and a draw, ready to use.<\/li>\n<li>A setup wizard: your sport, one club or several, and a first competition with its draw. Sample data for tennis, padel and pickleball shows the pages filled in, and comes off again from the Dashboard.<\/li>\n<li>Knockout draws: one click generates the bracket, with seeds on the ITF placement lines and byes to the top seeds, up to 128 lines. Winners move on by themselves. Add a 3rd place match if you want one.<\/li>\n<li>Round robin and group draws: one click writes every fixture, round by round. A box of 6 gets 15 matches in 5 rounds.<\/li>\n<li>League tables that rebuild themselves when a result changes. Set the points, and put the tiebreakers (wins, head-to-head, % sets won, % games won) in your own order.<\/li>\n<li>A Dashboard that shows what needs you first: tables out of date, draws waiting for a bracket, matches overdue.<\/li>\n<li>Single-club mode for a club running its own site.<\/li>\n<\/ul>\n\n<h4>On your site<\/h4>\n\n<ul>\n<li>Match pages with the score set by set, and a preview before and during the match: last 5 results, head-to-head, recent workload.<\/li>\n<li>Player and pair pages with the last 10 results, match and set profiles, year by year by surface, and rivalries, all counted from your own matches.<\/li>\n<li>Competition pages with season pills and a tab per draw. A knockout shows as a bracket that fits narrow screens, a round robin as its league table.<\/li>\n<li>Printable sheets for the club noticeboard: the draw, the round-robin grid and the day's order of play.<\/li>\n<li>A match list with a 7-day strip, a date picker and All \/ Live \/ Finished \/ Upcoming pills. It swaps content in place with JavaScript on, and every control is a plain link with it off.<\/li>\n<li>4 shortcodes and 4 blocks: draw, match list, standings table and player card. A Shortcodes page builds them from pickers and previews them in your theme.<\/li>\n<li>Built from div grids, so your theme's table and list styles don't leak in. Copy any template into your theme to change it.<\/li>\n<li>Change 39 of the words your public pages print under Settings &gt; Text.<\/li>\n<li>Search engines: bye matches and empty bracket slots stay out of the index and the sitemap, and filtered views point to the plain page. Works with Yoast SEO and Rank Math.<\/li>\n<li>Page cache clearing: when a match changes, its page and the pages around it are cleared. Works with W3 Total Cache, LiteSpeed Cache, SpinupWP, SiteGround Optimizer, FlyingPress, Hummingbird, WP Rocket, WP Fastest Cache and WP Super Cache.<\/li>\n<li>A read-only public REST API under <code>anwptl\/v1<\/code> for matches, competitions, players, pairs, clubs and standings.<\/li>\n<\/ul>\n\n<h4>Source code<\/h4>\n\n<p>Every minified file ships next to its unminified build: <code>admin\/js\/admin-core.js<\/code> beside <code>admin-core.min.js<\/code>, <code>public\/js\/tl-public.js<\/code> beside <code>tl-public.min.js<\/code>, <code>gutenberg\/blocks.js<\/code> beside <code>blocks.min.js<\/code>, and the same for every stylesheet. The admin screens are Vue 3 single-file components built with Vite, the public scripts are plain JavaScript modules bundled with Vite, the blocks are built with @wordpress\/scripts, and the stylesheets are compiled from SCSS.<\/p>\n\n<h4>Third-party code<\/h4>\n\n<p>All of it is bundled locally, and nothing is loaded from a CDN.<\/p>\n\n<ul>\n<li>Vue 3.5.42 (MIT), https:\/\/github.com\/vuejs\/core - admin screens, in <code>admin\/js\/admin-core.js<\/code>.<\/li>\n<li>Pinia 3.0.4 (MIT), https:\/\/github.com\/vuejs\/pinia - admin screens.<\/li>\n<li>vue-multiselect 3.5.0 (MIT), https:\/\/github.com\/shentao\/vue-multiselect - admin pickers.<\/li>\n<li>vue-draggable-plus 0.6.1 (MIT), https:\/\/github.com\/Alfred-Skyblue\/vue-draggable-plus, with SortableJS 1.15.2 (MIT), https:\/\/github.com\/SortableJS\/Sortable - drag-to-order rows in the admin.<\/li>\n<li>Country flags: HatScripts\/circle-flags (https:\/\/github.com\/HatScripts\/circle-flags), MIT licence - <code>public\/img\/flags.svg<\/code>.<\/li>\n<\/ul>\n\n<h4>Privacy<\/h4>\n\n<p>The plugin makes no remote requests and sends no data anywhere: no tracking, no telemetry, no cookies. Everything you enter stays in your own database. A player's date of birth is never printed on a public page or returned by the public REST API - player and match pages show the age in years. When a match changes, the plugin asks the page cache plugin you already run to clear the pages around it. What that plugin does next is up to its own settings.<\/p>\n\n<h4>Documentation<\/h4>\n\n<p>Guides for each sport, draws, fixtures and standings: <a href=\"https:\/\/anwp.pro\/docs\/tennis-leagues\/\">anwp.pro\/docs\/tennis-leagues<\/a><\/p>\n\n<!--section=installation-->\n<ol>\n<li>Install the plugin from Plugins &gt; Add New, or upload the <code>anwp-tennis-leagues<\/code> folder to <code>\/wp-content\/plugins\/<\/code>.<\/li>\n<li>Activate it. A Tennis Leagues menu appears in your admin.<\/li>\n<li>Add your players (and pairs, for doubles). Clubs are optional.<\/li>\n<li>Add a competition and pick its sport. It gets a season and a draw straight away.<\/li>\n<li>Open the draw, add the entries, then generate the bracket or the fixtures.<\/li>\n<li>Put the competition on a page with a block or a shortcode, or link to its own page.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"which%20sports%20does%20it%20support%3F\"><h3>Which sports does it support?<\/h3><\/dt>\n<dd><p>Tennis, padel, squash, table tennis, pickleball and badminton, singles and doubles. Each sport has its own scoring rules, and each competition can pick the variants its sport offers.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20my%20theme%3F\"><h3>Does it work with my theme?<\/h3><\/dt>\n<dd><p>It should. Public output is built from div grids with its own class names, so a theme's table and list styles don't reach it. Classic themes like Kadence or Astra use their own single post template. On a block theme (Twenty Twenty-Five and the like) with WordPress 6.7 or later, the plugin adds its own templates for player, pair, club, competition and match pages. They take over from the theme's Single Posts template, so a sidebar or ad you added there won't show on those pages. Edit them under Appearance &gt; Editor &gt; Templates (\"Single Player\", \"Single Match\" and the rest).<\/p><\/dd>\n<dt id=\"can%20i%20change%20the%20web%20addresses%3F\"><h3>Can I change the web addresses?<\/h3><\/dt>\n<dd><p>Yes. Player, pair, club, competition and match pages start with tennis-player, tennis-pair and so on, so they don't clash with Football Leagues or Sports Leagues. Change them in the Permalinks box under Tennis Leagues &gt; Settings.<\/p><\/dd>\n<dt id=\"can%20i%20run%20it%20for%20a%20single%20club%3F\"><h3>Can I run it for a single club?<\/h3><\/dt>\n<dd><p>Yes. Switch on single-club mode under Tennis Leagues &gt; Settings and pick or create your club. The club fields drop off the forms and the Clubs screen becomes \"Your Club\".<\/p><\/dd>\n<dt id=\"can%20i%20change%20a%20template%3F\"><h3>Can I change a template?<\/h3><\/dt>\n<dd><p>Copy the file from the plugin's <code>templates<\/code> folder into an <code>anwp-tennis-leagues<\/code> folder in your theme and edit it there. A child theme's copy wins over its parent's.<\/p><\/dd>\n<dt id=\"is%20there%20a%20premium%20version%3F\"><h3>Is there a Premium version?<\/h3><\/dt>\n<dd><p>A separate Premium plugin is in development at <a href=\"https:\/\/anwp.pro\">anwp.pro<\/a>.Everything in this plugin is free and stays free, and none of it needs Premium to work.<\/p><\/dd>\n<dt id=\"where%20do%20i%20get%20help%3F\"><h3>Where do I get help?<\/h3><\/dt>\n<dd><p>Ask in this plugin's support forum on WordPress.org. The guides are on <a href=\"https:\/\/anwp.pro\/docs\/tennis-leagues\/\">anwp.pro<\/a>.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20my%20data%20if%20i%20delete%20the%20plugin%3F\"><h3>What happens to my data if I delete the plugin?<\/h3><\/dt>\n<dd><p>Deleting the plugin from the Plugins screen removes its tables, posts and options, unless the Premium version is still installed - then your data stays. Deactivating it keeps everything.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.8.2 - 2026-11-11<\/h4>\n\n<p>First release on WordPress.org.<\/p>\n\n<ul>\n<li>Scoring for 6 sports, with impossible scores refused.<\/li>\n<li>Knockout brackets and round-robin fixtures generated in one click.<\/li>\n<li>League tables rebuilt on every result, with your own points and tiebreaker order.<\/li>\n<li>Public pages for matches, players, pairs and competitions, plus 4 shortcodes and 4 blocks.<\/li>\n<li>Setup wizard with sample data, a Next Steps box from Publish to the first result, printable sheets, Dashboard, single-club mode and a read-only public REST API.<\/li>\n<\/ul>\n\n<p>Pre-release history (0.1.0 to 0.7.0) is in changelog.txt.<\/p>","raw_excerpt":"Tennis, padel, pickleball, squash, table tennis and badminton leagues and tournaments: draws, brackets, set scores, fixtures and league tables.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/400914","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=400914"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/anwppro"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=400914"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=400914"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=400914"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=400914"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=400914"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=400914"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}