diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1170717 --- /dev/null +++ b/.gitignore @@ -0,0 +1,136 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# vitepress build output +**/.vitepress/dist + +# vitepress cache directory +**/.vitepress/cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* diff --git a/bin/package-lock.json b/bin/package-lock.json new file mode 100644 index 0000000..e386322 --- /dev/null +++ b/bin/package-lock.json @@ -0,0 +1,243 @@ +{ + "name": "bin", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "ajv": "^8.17.1", + "yargs": "^17.7.2" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/bin/package.json b/bin/package.json new file mode 100644 index 0000000..b97f6ae --- /dev/null +++ b/bin/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "ajv": "^8.17.1", + "yargs": "^17.7.2" + } +} diff --git a/bin/validate.js b/bin/validate.js new file mode 100644 index 0000000..9c17729 --- /dev/null +++ b/bin/validate.js @@ -0,0 +1,54 @@ +// Given a schema validate any given data files against the schema +// Validate a single file: +// node validate.js --schema ../events/events.schema.json --data ../events/data/fossdem.org.json +// Validate an entire collection: +// node validate.js --schema ../events/events.schema.json --data ../events/data/*.json + +const fs = require('fs'); +const args = require('yargs') + .command('schema', 'schema to use for validation') + .option('data', {type: 'array', desc: 'data files to validate'}) + .option('verbose', {type: 'boolean'}) + .demand(['data','schema']) + .argv; + +const Ajv = require("ajv/dist/2020"); // https://ajv.js.org/guide/schema-language.html#draft-2019-09-and-draft-2020-12 +const ajv = new Ajv({ strict: false }) + +// Load schema +const schema = JSON.parse(fs.readFileSync(args.schema, 'utf8')); +const validate = ajv.compile(schema); + +let report = { + valid: 0, + invalid: 0, + review: [] +} + +// Iterate over each data file to validate it +args.data.forEach(item => { + log(item); + const asset = JSON.parse(fs.readFileSync(item, 'utf8')); + if (validate(asset)) { + log("Valid"); + report.valid++; + } else { + log("Invalid"); + report.invalid++; + report.review.push(item); + log(validate.errors); + console.warn(`${item} => ${JSON.stringify(validate.errors)}`); + } +}); + +if (report.invalid > 0) { + console.error(`Failed to validate:\n${report.review.join('\n')}`) +} +console.log(`Validated ${report.valid} out of ${args.data.length} resources checked.`) + + +function log(msg) { + if (args.verbose) { + console.log(msg) + } +} diff --git a/events/data/ces.tech.json b/events/data/ces.tech.json new file mode 100644 index 0000000..71d846a --- /dev/null +++ b/events/data/ces.tech.json @@ -0,0 +1,5 @@ +{ + "url": "https://www.ces.tech", + "name": "CES", + "aliases": ["Consumer Electronics Show"] +} \ No newline at end of file diff --git a/events/data/cmxhub.com.json b/events/data/cmxhub.com.json new file mode 100644 index 0000000..d2884dd --- /dev/null +++ b/events/data/cmxhub.com.json @@ -0,0 +1,4 @@ +{ + "url": "https://cmxhub.com/summit", + "name": "CMX Summit" +} \ No newline at end of file diff --git a/events/data/developerrelations.com.json b/events/data/developerrelations.com.json new file mode 100644 index 0000000..369c550 --- /dev/null +++ b/events/data/developerrelations.com.json @@ -0,0 +1,4 @@ +{ + "url": "https://developerrelations.com/devrelcon", + "name": "DevRelCon" +} \ No newline at end of file diff --git a/events/data/developerweek.com.json b/events/data/developerweek.com.json new file mode 100644 index 0000000..45b694a --- /dev/null +++ b/events/data/developerweek.com.json @@ -0,0 +1,7 @@ +{ + "url": "https://developerweek.com", + "name": "DeveloperWeek", + "schema": { + "version": "1.0" + } +} \ No newline at end of file diff --git a/events/data/fosdem.org.json b/events/data/fosdem.org.json new file mode 100644 index 0000000..0172898 --- /dev/null +++ b/events/data/fosdem.org.json @@ -0,0 +1,68 @@ +{ + "url": "https://fosdem.org", + "name": "FOSDEM", + "description": "FOSDEM is a free event for software developers to meet, share ideas and collaborate. Every year, thousands of developers of free and open source software from all over the world gather at the event in Brussels. You don't need to register. Just turn up and join in!", + "aliases": ["Free and Open Source Developers European Meeting"], + "topics": ["open source", "android", "apis", "ada", "cloud native", "containers", "analytics", "embedded", "java", "geospatial", "golang", "security", "javascript", "web", "mysql", "postgresql", "python", "quantum", "real-time communications", "robotics", "rust", "swift", "ios", "cicd", "docs", "WebAssembly"], + "social": { + "discord": "", + "facebook": "https://facebook.com/fosdem", + "instagram": "https://www.instagram.com/fosdem/", + "linkedin": "", + "bluesky": "", + "mastodon": "https://fosstodon.org/@fosdem", + "slack": "", + "x": "https://x.com/fosdem" + }, + "frequency": "annual", + "series": [ + { + "start": "2025-02-01", + "end": "2025-02-02", + "type": "in-person", + "city": "Brussels", + "state": "", + "country": "Belgium", + "venue": { + "name": "ULB Solbosch Campus", + "address": "Av. F. D. Roosevelt 50\n1050 Bruxelles" + } + } + ], + "engagement": [ + "talks", + "keynotes", + "lightning talks", + "booths", + "birds of a feather", + "meeting rooms" + ], + "speakers": { + "cfp": { + "url": "", + "deadline": "" + }, + "tracks": 2, + "range": {"min": 1054, "max": 1054} + }, + "attendees": { + "range": {"min": 4000, "max": 8000}, + "code-of-conduct": "https://fosdem.org/2025/practical/conduct/", + "accessibility": { + "closed-captions": false, + "sign-language": false + }, + "personas": [] + }, + "organizer": { + "org": "FOSEM VZW", + "type": "non-profit", + "email": "info@fosdem.org", + "phone": "+32 2 788 74 74", + "sponsorship": { + "contact": "sponsors@fosdem.org", + "range": {"min": 1, "max": 100}, + "minimum": 0 + } + } +} \ No newline at end of file diff --git a/events/design.md b/events/design.md new file mode 100644 index 0000000..df32dac --- /dev/null +++ b/events/design.md @@ -0,0 +1,138 @@ +# Event Directory Design + +The event directory should support a variety of use cases. + +## Data Description + +To maintain the event directory we want to define and collect structured data. This means a certain amount of validation is needed to ensure data integrity so that it can reliably be used in sensible ways. + +- json-schema: standardized representation of how data is to be specified +- ajv: another JSON validator is a CLI to validate JSON against a schema +- schema.org: a semantic reference for property specification + +### JSON-Schema + +https://json-schema.org/ +> While JSON is probably the most popular format for exchanging data, JSON Schema is the vocabulary that enables JSON data consistency, validity, and interoperability at scale. + +### AJV + +https://ajv.js.org/ +> It allows implementing complex data validation logic via declarative schemas for your JSON data, without writing code. Out of the box, Ajv supports JSON Schema (drafts 04, 06, 07, 2019-09 and 2020-12) and JSON Type Definition (RFC8927). + +### Schema.org + +The data definition has some influences from RDF and JSON-LD for semantic meaning within web applications. The schema does not have strict adherence to the community but it serves as inspiration. + +https://schema.org/Event +>Schema.org is a collaborative, community activity with a mission to create, maintain, and promote schemas for structured data on the Internet, on web pages, in email messages, and beyond. + +## Architecture + +The objective is not to build end-user experiences but provide a reference implementation for how others might use the aggregated data to build them or exchange data with other existing tools. + +### Overview + + ┌────────────────┐ + │ │ + │ GitHub Action │ + │ │ + └────────┬───────┘ + ┌────────────────┐ │ ┌────────────────┐ ┌────────────────┐ + │ │ │ │ │ │ │ + │ /data │ │ │ /indexers │ │ /exchange │ + │ │ │ │ │ │ │ + └────────────────┘ │ └────────────────┘ └────────────────┘ + ┌───────┐ │ + │ .json │ ┌────────▼───────┐ + └───┬───┘ │ │ +┌───────┐│┌───────┐ │ validate.js │ +│ .json │││ .json ◄────────┼ │ +└───┬───┘│└────┬──┘ └────────────────┘ ┌────────────────┐ ┌────────────────┐ + │ │ │ │ │ │ │ + │ │ │ │ to_csv.js │ │ conftech.js │ + │ │ │ │ │ │ │ + │ │ │ └────────┬───────┘ └────────────────┘ + └────┼─────┘ │ + │ │ + ┌──▼────┐ │ + │ .csv │ ◄─────────────────────────────────────────────┘ + └───────┘ + ┌────────────────┐ ┌────────────────┐ + │ │ │ │ + │ to_md.js │ │ devpost.js │ + │ │ │ │ + └────────────────┘ └────────────────┘ + ┌────────────────┐ + │ │ + │ to_airtable.js │ + │ │ + └────────────────┘ + ┌────────────────┐ + │ │ + │ to_...js │ + │ │ + └────────────────┘ + + +### Validation + +GitHub Actions provide a hook that submissions are validated or checked against the schema to insure a base level of data integrity. + +### Indexing + +To assist with providing value, indexers gather all of the data into a format that is transferrable to other systems and uses. + +* Comma-separated Values (CSV) can be a useful representation for all JSON records in a tabular record appropriate to be imported into Google Sheets, AirTable, or Excel. +* Markdown can be a useful representation for casual review of events that share certain properties in a simple linear list, such as viewing a list of all events in January of 20xx. + +Indexing is the mechanism that can make the list of events valuable for multiple use cases by also filtering out certain criteria based on the underlying data. + +### Exchange + +Given the existence of other event repositories, an exchange or synchronization step may be a natural byproduct to export and import data between our aggregation and their system. + +See [events.md](./events.md) for a list of example aggregators that may exchange data contributions. + +## Guidelines + +### File Naming Convention + +The name of individual records will follow the naming convention of being the domain name for the event. + +Rationale: +- avoids collisions when events share a similar name +- can be computed or validated based on the `url` in the event data itself +- promotes fairness when sorting a filesystem directory +- avoids ambiguity when identifying the topics of an event as an organizing principle +- improves discoverability by not ordering by date or when event dates change + +Examples: +- Developer Week is stored in developerweek.com.json. +- Techcrunch Disrupt 2024 is stored in techcrunch.com.json. If it followed the pattern 2024.techcrunch.com it would still be the same. + +### Single File Per Event + +Events that occur with non-overlapping dates are stored in a single file and represented as a series. + +Rationale: +- allows for discovering of events before official dates or locations have been set +- helps manage frequently recurring events getting same attention as annual events + +Examples: +- CES is a single file, but has a series as part of the data that allows for each year to be set with dates and optional unique URL +- Tracy Devs Meetup group does not have twelve separate files to manage for a monthly recurring event + +# Appendix + +## Future Work + +Additional ideas under consideration + +- [ ] external reference to personas library for attendees +- [ ] index to airtable +- [ ] index to rss feed +- [ ] index to public google calendar +- [ ] exchange with confs.tech +- [ ] exchange with sessionize +- [ ] exchange with devpost diff --git a/events/events.md b/events/events.md new file mode 100644 index 0000000..90957d7 --- /dev/null +++ b/events/events.md @@ -0,0 +1,125 @@ +# Events Directory + +Community is an important part of many Developer Relations programs. Events allow a community to come together to exchange ideas, whether in-person or virtually. Some events may have a single topic while others may have a diverse set of tracks that cover a variety of subjects. Events may be run by a private commercial company, an individual hobbyist, or an event management company. As part of a go-to-market motion, Developer Relations professionals often seek out events that provide speaking calls for papers (CFP) or other sponsorship activities. + +An objective of the working group is to aggregate these types of community events. Existing solutions are available but there is a gap between what they provide and the needs of the broader Developer Relations community. + +- [design.md](./design.md): discusses design influences for the data model and reference implementations +- [how-to.md](./how-to.md): provides examples for how to accomplish tasks with the event directory data + + +## Use Cases + +The aim for this events directory is to service the broader needs of developer advocates, developer marketing, community managers, event managers, product managers, and more. Events may also include professional development opportunities. + +### Events by Location + +The geographic region is a common and important dimension for events. +- sponsors may focus segmentation of go-to-market activities +- participants may seek local events to attend + +### Events by Topic + +The topics and technology themes of an event: +- the programming language such as Python, Ruby, JavaScript, etc. +- the technical methodology such as DevOps, Data Science, UX, AI, etc. +- the platform such as Android, iOS, etc. +- the technology or software vendor + +### Events by Speaking Opportunity + +Seeking opportunities to speak and share information is common. +- when is the CFP deadline +- stipend availability to support speakers + +### Events by Attendee Persona and Demographics + +The persona or profiles of attendees may influence participation: +- their job titles +- their company or organization +- size of the event +- good for students +- valuable for job seekers + +### Open-ended Opportunities + +For recurring events, there is often an open opportunity to participate. The event directory can help facilitate the matching problem of speakers to audiences. +- flexible dates + +### Event Costs + +There are associated costs with events for attendees and sponsors. +- minimum sponsorship +- free events vs. ticketed events + +### Co-located and Event Series + +There are some events that are not isolated occurrences. +- series such as with meetups +- annual events +- hackathons attached to a conference + +### Hosting Events + +DevRel professionals often are planning events and may want to coordinate with other events that are important to their community. +- avoid overlapping dates + +# Existing Solutions + +Given the use cases, there are many fine examples of aggregated event listings but none that provide a comprehensive list to solve all the needs of the developer relations professional. + +## https://confs.tech/ +Open-source and crowd-sourced list of conferences around software development. +- website repository: https://github.com/tech-conferences/confs.tech +- data repository: https://github.com/tech-conferences/conference-data + +"We only accept software development related conferences. We do not accept meetups, company sponsored or business events." + +## https://devpost.com +We power most of the world’s software competitions (hackathons) on our platform. + +Only considers hackathons. + +## http://www.wikicfp.com/cfp/ +WikiCFP is a semantic wiki for Calls For Papers in science and technology fields. + +Only considers CFPs. + +## https://www.eventbrite.com/ +Bringing the world together through live experiences. +- acquired lanyard.com + +## https://www.meetup.com/ +Meetup creates possibilities to find and build local communities. + +## https://sessionize.com/ +The smart way to do Call for Papers, Schedule and Speaker Management. + +## https://joind.in/ +Joind.in brings attendee feedback to speakers at events, quickly and transparently. Getting feedback lets speakers improve, attendees be heard, and organisers find out what really works (and doesn't!) at their events. + +## https://www.papercall.io/ +PaperCall enables event organizers to easily manage their call for papers and talk submissions. + +## https://callingallpapers.com/ +List of currently open Calls for Papers (CFP). To retrieve the list we crawl these sites on a daily basis to find new CfPs: joind.in, confs.tech, papercall.io, Sessionize. + +Only considers CFPs. + +## https://www.cfpland.com/ +CFP Land exists to help speakers find the best opportunities. +- api docs: https://cfpland.github.io/api-docs/ + +## https://seecfp.com/ +CFPs to browse or directly in your inbox. + +## https://developers.events/ +A community-driven platform listing developer/tech conferences and Calls for Papers (CFPs) worldwide with a list, a calendar and a map view. +- https://github.com/scraly/developers-conferences-agenda + +## https://www.devresources.info/conferences +A curated list of the developer conferences for 2025 and beyond. + +## https://www.bizzabo.com/blog/technology-events +This carefully curated conference directory features more than 100 tech conferences happening worldwide in 2025, with a focus on North America. + diff --git a/events/events.schema.json b/events/events.schema.json new file mode 100644 index 0000000..e14b649 --- /dev/null +++ b/events/events.schema.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/DevRel-Foundation/wg-resource-aggregation/blob/main/events/schema/events.schema.json", + "title": "Event", + "description": "Developer Relations Foundation event description.", + "version": "1.0", + "type": "object", + "properties": { + "url": { + "description": "The canonical URL to learn more about the event.", + "type": "string" + }, + "name": { + "description": "The name used to identify the event.", + "type": "string" + }, + "aliases": { + "description": "Additional names that may be used to identify this event.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "schema": { + "description": "Details about the schema the document follows.", + "type": "object", + "properties": { + "url": { + "description": "The location of the schema.", + "type": "string" + }, + "version": { + "description": "The version of the schema.", + "type": "string" + } + } + } + }, + "required": ["url", "name"], + "additionalProperties": false +} \ No newline at end of file diff --git a/events/how-to.md b/events/how-to.md new file mode 100644 index 0000000..b0d712e --- /dev/null +++ b/events/how-to.md @@ -0,0 +1,36 @@ + +## How-to Run a Pre-Commit Validation Check + +TODO + + +## How-to Fix an additionalProperties Error + +You may see something similar to the following when validating data. + +``` +Invalid Resource +[ + { + instancePath: '', + schemaPath: '#/additionalProperties', + keyword: 'additionalProperties', + params: { additionalProperty: 'alias' }, + message: 'must NOT have additional properties' + } +] +``` + +There are many properties that are optional and can be excluded, but additional properties that have not been defined by the schema cannot be added. + +This particular instance actually catches an error, where the data used `alias` instead of `aliases` when specifying additional names that represent the event. + +## How-to Get Sessionize Talk Details For Exchange + +This is not a goal of the exchangers, but a Chrome extension can be helpful for speakers who are looking to quickly reuse their +talk details with multiple submission tools. + +https://github.com/jerdog/cfp-chrome-extension + + + diff --git a/personas/data/chief-technology-officer.json b/personas/data/chief-technology-officer.json new file mode 100644 index 0000000..e69de29 diff --git a/personas/data/community-manager.json b/personas/data/community-manager.json new file mode 100644 index 0000000..e69de29 diff --git a/personas/data/developer-advocate.json b/personas/data/developer-advocate.json new file mode 100644 index 0000000..e69de29 diff --git a/personas/data/developer-advocate.security.json b/personas/data/developer-advocate.security.json new file mode 100644 index 0000000..c913010 --- /dev/null +++ b/personas/data/developer-advocate.security.json @@ -0,0 +1,8 @@ +{ + "url": "https://mogics.com/super-bagel", + "name": "MOGICS Super Bagel", + "description": "Travel power adapter for US, EU, UK, AU", + "labels": ["power adapter"], + "task": ["how-to work while on the go"], + "personas": ["business traveller"] +} \ No newline at end of file diff --git a/personas/data/developer-evangelist.json b/personas/data/developer-evangelist.json new file mode 100644 index 0000000..e69de29 diff --git a/personas/data/developer-marketing-manager.json b/personas/data/developer-marketing-manager.json new file mode 100644 index 0000000..e69de29 diff --git a/personas/data/developer-relations-engineer.json b/personas/data/developer-relations-engineer.json new file mode 100644 index 0000000..e69de29 diff --git a/personas/data/growth-hacker.json b/personas/data/growth-hacker.json new file mode 100644 index 0000000..e69de29 diff --git a/personas/data/head-of-developer-relations.json b/personas/data/head-of-developer-relations.json new file mode 100644 index 0000000..e69de29 diff --git a/personas/data/product-marketing-manager.json b/personas/data/product-marketing-manager.json new file mode 100644 index 0000000..e69de29 diff --git a/personas/data/student.computer-science.json b/personas/data/student.computer-science.json new file mode 100644 index 0000000..e69de29 diff --git a/personas/data/student.json b/personas/data/student.json new file mode 100644 index 0000000..e69de29 diff --git a/personas/industries.schema.json b/personas/industries.schema.json new file mode 100644 index 0000000..e69de29 diff --git a/personas/personas.schema.json b/personas/personas.schema.json new file mode 100644 index 0000000..d468628 --- /dev/null +++ b/personas/personas.schema.json @@ -0,0 +1,54 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/DevRel-Foundation/wg-resource-aggregation/blob/main/personas/personas.schema.json", + "title": "Personas", + "description": "Developer Relations Foundation persona descriptions.", + "version": "1.0", + "type": "object", + "properties": { + "url": { + "description": "The canonical URL to learn more about the persona.", + "type": "string" + }, + "title": { + "description": "The primary job title used to identify the persona.", + "type": "string" + }, + "industry": { + "description": "The industry in which the persona works.", + "type": "string" + }, + "aliases": { + "description": "Additional job titles that may be used to identify this persona.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "tags": { + "description": "Labels that help categorize the type of persona.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "schema": { + "description": "Details about the schema the document follows.", + "type": "object", + "properties": { + "url": { + "description": "The location of the schema.", + "type": "string" + }, + "version": { + "description": "The version of the schema.", + "type": "string" + } + } + } + }, + "required": ["url", "name"], + "additionalProperties": false +} \ No newline at end of file diff --git a/tools/data/discourse.org.json b/tools/data/discourse.org.json new file mode 100644 index 0000000..5a15299 --- /dev/null +++ b/tools/data/discourse.org.json @@ -0,0 +1,8 @@ +{ + "url": "https://discourse.org", + "name": "Discourse", + "description": "Open-source, community-minded forum software.", + "labels": ["community forums"], + "task": ["how-to provide q&a online"], + "personas": ["community manager"] +} \ No newline at end of file diff --git a/tools/data/jonobacon.com.json b/tools/data/jonobacon.com.json new file mode 100644 index 0000000..492daf0 --- /dev/null +++ b/tools/data/jonobacon.com.json @@ -0,0 +1,10 @@ +{ + "url": "https://www.jonobacon.com/books/artofcommunity", + "name": "The Art of Community by Jono Bacon", + "description": "Book about building communities.", + "labels": ["book", "community"], + "task": [ + "how-to build a strategy", + "how-to manage a community"], + "personas": ["community manager", "new professional", "social media"] +} \ No newline at end of file diff --git a/tools/data/mogics.com.json b/tools/data/mogics.com.json new file mode 100644 index 0000000..c913010 --- /dev/null +++ b/tools/data/mogics.com.json @@ -0,0 +1,8 @@ +{ + "url": "https://mogics.com/super-bagel", + "name": "MOGICS Super Bagel", + "description": "Travel power adapter for US, EU, UK, AU", + "labels": ["power adapter"], + "task": ["how-to work while on the go"], + "personas": ["business traveller"] +} \ No newline at end of file diff --git a/tools/data/readme.com.json b/tools/data/readme.com.json new file mode 100644 index 0000000..30aaf91 --- /dev/null +++ b/tools/data/readme.com.json @@ -0,0 +1,8 @@ +{ + "url": "https://readme.com", + "name": "Readme", + "description": "Content management system for developer documentation.", + "labels": ["documentation", "api spec"], + "task": ["how-to host documentation", "how-to write api specs"], + "personas": ["doc writer", "website creator"] +} \ No newline at end of file diff --git a/tools/tools.md b/tools/tools.md new file mode 100644 index 0000000..ddb69d7 --- /dev/null +++ b/tools/tools.md @@ -0,0 +1,81 @@ +# Tools Catalog + +Developer Relations professionals must use a diverse set of software and tools to accomplish the mission of the role. The value of having a catalog of software and tools is to support the discoverability of resources that help solve day-to-day operational challenges. The problems which a tool may solve can be varied including customer relationship management, ticketing, content authoring, video editing, communication, software development, etc. Those tools may take the form of open-source projects, software-as-a-service, mobile applications, travel accessories, commercial off-the-shelf software, edcuational materials, etc. + +## Scope + +An objective of the working group is to aggregate a variety of tools that a majority of devrel professionals would consider valuable for completing the expectations of their role. This should not extend infinitely to catalog every tool that may have marginal utility to all technology roles. + +Consider some examples: + +- a book on building community +- a framework or process for prioritization +- a backpack that is great for travel +- a python debugger for good sample code +- a specific computer monitor +- an agency or consultant that can help plan a devrel program + +Each of these could be considered related to the work tasks of a developer relations professional and should be included. Conversely, it may not be particularly helpful if the tool catalog included thirty different variety of keyboards unless there was a qualifier such as "suitable for travel". + +Is there a sniff test we can apply to designate what is or is not a tool? It should solve a problem that is applicable to the developer relations roles and profession. + +## Categories + +Defining categories for tools would be a natural conclusion for the catalog but introduces ambiguity. + +- do some tools appear in more than one category? +- do categories change depending on your role or perspective? +- how do we determine if a tool should be in a category or not? +- would a person using the catalog understand the categories? +- how nested would categories need to be to improve searchability? + +As an alternative to categories, the catalog can present solutions to tasks. + +## Use Cases + +### Tools by Persona + +The aim for the tools catalog is to service the broader needs of developer advocates, developer marketing, community managers, event managers, product managers, and more. Despite a variety of job titles, there are certain skills or activities that are common in the job description of a developer relations professional that can help guide identification of tools. + +- public speaker +- business traveller +- content writer +- video producer +- audio show producer +- workshop instructor +- community builder +- graphics designer +- event planner +- contenet marketer +- ux researcher +- new professional +- website creator +- coordinator +- social media +- demo builder +- doc writer + +### Tools by Task + +Some tasks are common across personas, so tools can be categorized by the solutions they provide. + +- how-to provide q&a online +- how-to gather feedback +- how-to build a strategy +- how-to manage a community +- how-to travel light +- how-to work while on the go +- how-to host documentation + +# Existing Solutions + +Given the problem of finding the right tool for a task, there are some examples of aggregated listings of tools but none that provide a comprehensive list to solve all the needs of the developer relations professional. + +## https://github.com/devrelcollective/awesome-devrel +Awesome Developer Relations resources curated by the DevRel Collective. + +## misc. + +- https://github.com/mindee/devrel/blob/main/resources/devrel.md +- https://dev.to/fernandezbaptiste/13-tools-for-increased-productivity-as-a-devrel-3m19 + diff --git a/tools/tools.schema.json b/tools/tools.schema.json new file mode 100644 index 0000000..af71a4e --- /dev/null +++ b/tools/tools.schema.json @@ -0,0 +1,84 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/DevRel-Foundation/wg-resource-aggregation/blob/main/tools/tools.schema.json", + "title": "Tools", + "description": "Developer Relations Foundation tool description.", + "version": "1.0", + "type": "object", + "properties": { + "url": { + "description": "The canonical URL to learn more about the tool.", + "type": "string" + }, + "name": { + "description": "The primary name used to identify the tool.", + "type": "string" + }, + "aliases": { + "description": "Additional names that may be used to identify this tool.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "tags": { + "description": "Labels that help categorize the type of tool.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "personas": { + "description": "The personas that commonly use the tool.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "public speaker", + "business traveller", + "content writer", + "video producer", + "audio show producer", + "workshop instructor", + "community manager", + "graphics designer", + "event planner", + "content marketer", + "ux researcher", + "new professional", + "coordinator", + "social media", + "demo builder" + ] + } + }, + "task": { + "description": "The problem the tool can solve for a practioner.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "how-to store a list of qualified leads" + ] + } + }, + "schema": { + "description": "Details about the schema the document follows.", + "type": "object", + "properties": { + "url": { + "description": "The location of the schema.", + "type": "string" + }, + "version": { + "description": "The version of the schema.", + "type": "string" + } + } + } + }, + "required": ["url", "name"], + "additionalProperties": false +} \ No newline at end of file