pshrmn / curi Goto Github PK
View Code? Open in Web Editor NEWA JavaScript router for single-page applications
Home Page: https://curi.js.org
License: MIT License
A JavaScript router for single-page applications
Home Page: https://curi.js.org
License: MIT License
For example https://github.com/sveltejs/awesome
set.redirect
seemingly only redirecting to ''
routeNot sure if I'm implementing something incorrectly, but I have this type of basic structure I am working with:
import {Home} from 'view/Screens/Home'
import {Account} from 'view/Screens/Account'
import {login, handleAuthentication, isAuthenticated} from 'auth'
export const routes = [
{
name: 'Callback',
path: 'callback',
match: {
every: ({params}) => handleAuthentication(),
response: ({set}) => {
console.log('Callback')
set.body(null)
set.redirect({name: 'Account'}, null)
}
}
},
{
name: 'Login',
path: 'login',
match: {
response: ({set}) => {
set.body(null)
login()
}
}
},
{
name: 'Account',
path: 'account',
match: {
response: ({set}) => {
console.log('Account')
if (!isAuthenticated()) {
set.body(null)
set.redirect({name: 'Home', status: 302})
} else {
set.body(Account)
}
}
}
},
{
name: 'Home',
path: '',
match: {
response: ({set}) => {
console.log('Home')
set.body(Home)
}
}
},
{
name: 'route/404',
path: '(.*)',
match: {
response: ({set}) => {
console.log('404')
set.body(Home)
}
}
}
]
Login is working great, however redirects back always console log Home
. I've also swapped the redirect on Account
to redirect to Login
if you aren't authenticated and that one as well simply loads Home
. I saw #39, any chance the pathname match in there isn't finding my routes for some reason?
Every example this page is broken.
I like your project very much, other routers feel bloated to me... but it is just a feeling, could you tell me why should I use it instead of react-router
? (if not now, in the future)
Thanks!
Back again. I love the update to the routes.
How do we add multiple optional parameters to a path in the routes? I couldn't find it in the docs.
Thanks!
Not exactly sure what is leading to this issue.
In a functional component, using useRouter
without useResponse leads to the state update not propogating to component.
Code:
import React, { useEffect } from 'react';
import { Link, useRouter, useResponse } from '@curi/react-dom';
const App = () => {
// const { response } = useResponse();
const router = useRouter();
const route = router.route(router.current().response.name);
useEffect(() => {
console.log('App useEffect');
}, [route]);
return (
<div>
App
<Link name="Some Link">Link</Link>
</div>
)
}
export default App;
App useEffect
is printed only once (component mount) and not when link is followed. If I unComment the useResponse
hook call then App useEffect
is also printed when following the link.
I wonder if it works on React Native too?
Right now, if a route's load
function contains side effects, those will still be run when navigation to that route is cancelled.
{
name: 'Test',
path: '/test/:id',
load: (...) => {
console.log('I will always be called.');
}
}
This can be an issue with global stores if the load
function is pushing state related to a location.
load: ({ params }) => {
// load some data
store.dispatch({
type: 'SET_DATA',
id: params.id,
data
});
}
If the user clicked a link to /test/123
, then while the data for that was loading clicked a link to /test/456
, the navigation to /test/123
would be cancelled, but the dispatch to the Redux store would still happen.
There are a few possible approaches to dealing with this.
load
functionThere isn't necessarily a way to prevent someone from including side effects, but the documentation would be updated to explicitly state that they should not be included. While not particularly effective, this would at least give something to point to.
finish
property to routesThis property could be used to run any side effects. It would be run right after "finish"ing a navigation (and right before the response is emitted). The plus side of this is that we could guarantee that the function is only called when the navigation is completed.
I'm not sure if this is the best approach. At least with Redux, there is a weird timing; first, the dispatch would happen just before the emit, so Redux would re-render using the current response, but with new data, then the response would be emitted and the expected content would be rendered.
For the time being, I'm not going to do anything. This is one of those issues that only occurs if the user navigates before a previous navigation finishes. This isn't necessarily "highly unlikely", but it is something that should be rather infrequent. I certainly would like for there to be a recommended way to deal with this, but I don't want to go adding to the route
API until I'm certain a finish
function would be useful.
I'm having some issues. What might I be doing wrong?
Could not generate pathname for / because it is not registered.
The Router Challenge aims to be to Routers what TodoMVC is to MV* frameworks. It offers the same Music Catalog application built in React using different Routers. For it to be successful I need the help of Router writers like you. Will you take the Router Challenge and implement the Music Catalog application using Curi, please?
Would be awesome if we can do router.history.navigate('About')
. Currently only router.history.navigate('/about')
works.
Title sums it up.
Tested on Chrome and Safari.
Console returns:
ReferenceError: Can't find variable: IntersectionObserver
Is there a way to pass response logic to children routes? The use case is I have one parent route then a bunch of children routes, say like:
album
album/1
album/2
album/3
album/etc
So I would like to block access to album
and all its children. The problem is, it seems the best I can do create a function and pass it to every child. However, I'm looking to only write and use a piece a logic once in the parent. Any ideas? Thanks.
I am integrating apollo into the routes file and am stumbling upon an issue with programmatically navigating. I have this code in my route, call it routeB.
resolve({ params }, client) {
return client.query({
query: GET_SOMETHING,
variables: { userId: params ? params.userId : userId } // if I don't send the userId, get the userId from the top of the file
});
},
respond({ error, resolved }) {
return {
body: ResponseBody,
data: resolved.data.getSomething[0].prop[0]
};
}
On one page (routeA), I submit a form and want to navigate to routeB programmatically using router.navigate
. My first instinct was to do as normal router.navigate({ url });
. But upon doing that, the resolve
for routeB above didn't get the data.
Then I finally found the prefetch
module but I'm stuck on how to use it. Basically, after the data has been pre-fetched, how do I send the data from the resolved
response to routeB without triggering the resolve
function in the route file?
This prefetch
code is in routeA but I don't know what to do after it resolves, and there is no documentation on it.
prefetch(
pRoute,
{ match: { params: { userId: userId }},
external: router.external
}).then((resolved: any) => {
console.log(resolved);
});
Or am I doing this all wrong? Thanks for the help!
So, I have an App which has a header and a drawer. Now, apart from that, I have a Content
component that renders some thing on the page. How can I use curi to render different components inside that Content
based on what was clicked in Drawer?
This is how my App looks like:
ReactDOM.render((
<MuiThemeProvider theme={theme}>
<Router>
{
({ response }) => {
const { body:Body } = response;
return (
<Body response={response} />
);
}
}
</Router>
</MuiThemeProvider>
), document.getElementById('root'));
And I have somed direct routes in routes.js
. The problem is: If I add a children route to, let's say the Home route, the entire page only displays the components I write inside that Route. (i.e., the Header and the drawer obviously disappear.)
This is how I'd do it with React-Router:
<HashRouter>
<Switch>
<Route
exact
path={match.path}
component={Messages}
/>
<Route
exact
path={`${match.path}/:message`}
component={Message}
/>
</Switch>
</HashRouter>
Currently, if the user clicks a link, then while the response for the new location is still resolving, clicks another link, the history array will include both locations.
// current behavior
history = ['/start']
// user clicks link to '/next'
history = ['/start', '/next']
// '/next' response still resolving and user clicks link to '/finally'
history = ['/start', '/next', '/finally']
With non-SPAs, clicking another link while the browser is loading a new location results in the new location being replaced.
// non-SPA behavior
history = ['/start']
// user clicks link to '/next'
history = ['/start', '/next']
// '/next' response still resolving and user clicks link to '/finally'
history = ['/start', '/finally']
This is only a problem for navigation that happens prior to a response resolving (which should trigger a re-render). Once a response has resolved, this is not an issue.
Replacing the location would be ideal, but is not possible with the current Curi/Hickory implementations. There are a couple possible approaches to getting this working.
history.(push|replace)State
until a response has resolved.This would require tighter integration between Curi and Hickory. Hickory would either have to have some special subscriber that is called prior to emitting (i.e. give Curi the location object, but don't emit until Curi has resolved a response) or emit a function that can be used to update the browser's history.
The biggest issue with this is that using the browser's buttons updates the browser's history outside of our control. There would either have to be behavior to "undo" and "redo" pop events or treat this type of navigation differently.
If a Hickory history instance can know whether or not the last location has resolved, it can change its behavior for new navigation. For example, while resolving, any push
calls will result in window.history.replaceState
calls. This will result in the non-SPA behavior described above.
This seems like a better approach, but there are possible edge cases that can complicate this. For example, a replace
call while a push
is resolvingwould leave an extra location in the browser's history unless we first undo the
PUSH.
POP` navigation shouldn't be as much of an issue because those should be using cached data.
Hickory could reject navigation (navigate
/push
/replace
calls) while a response is resolving. This might be the most simple solution, but it is also not ideal.
The second solution seems like the best bet. To start, replacing pushes should be good enough. While not correctly rolling back a replace is annoying, a lot of sites already don't allow replace anchor clicks to the same location. Eventually, if necessary, a transaction system could be implemented to roll back navigation.
OK thanks - not an issue
Trying not to bother you again but I'm trying to understand this issue I've run into.
I'm doing server-side-rendering and it's working well. But now I'm trying to render a child route and it's not loading correctly. Here's the scenario:
This works. However, if I refresh the child route ("posts/:post"), then only the elements load but not the styles. In my server file, I have (simplified)
const app = express();
app.use(express.static(path.join(__dirname, '/public')));
app.get('*', (req, res) => {
const history = InMemory({ locations: [req.url] });
const router = curi(history, routes);
router.respond(() => {
const pageMarkup = ReactDOMServer.renderToString(
<CuriProvider router={ router }>
{({ response }) => {
return <App response={ response } />;
}}
</CuriProvider>
);
res.send(`<html><head></head><body>${ pageMarkup }</body></html>`);
});
});
I suspect it has something to do with the routes, which is why I'm writing the issue. Has anyone run into this?
*Keep in mind that the parents routes are working just fine.
Thanks!
Just a question: Do children routes get the resolve
value from the parent?
Hi, I hope all is well.
Still using Curi and still loving it. I just ran into an error from Typescript while trying to using the component. The issue is is asking for props url
and canNavigate
and I have always only used name
in regular JSX. Is there something different I need to do when using in Typescript? I have a screenshot for reference. Thanks!
I would like to use curi and successfuly managed to setup the router for my webapp
But I am hitting an issue:
I would like my webapp to be hosted on various folder structure without requiring change in code.
It should work on <domain>/
but also on <domain>/folder/
where both are the index page.
An about
page would be <domain>/about
and <domain>/folder/about/
respectively
Since the path parameter has the dual role of regex and path to use, curi does not seem to support <domain>/folder/
case
when I added
pathOptions: {
match: {
start: false,
},
},
the matching worked (but I add to put "Home" last (because a slash with start: false
would match all rout ending with a slash)
But then navigation do not remember the folder and thus navigate back to the root.
I guess curi need to be updated to support that or I am missing something ?
Dug through the release notes and such, no mention, is the redux package discontinued moving forward?
Thanks for this package, I just start to use react to my current project and it's awesome to know this project.
Thanks alot.
I believe I have everything updated from the tutorial, but I may be doing something wrong. Here's my console error:
Warning: Failed context type: The context `curi.navigation` is marked as required in `Curious`, but its value is `undefined`.
in Curious
in Unknown (created by CuriBase)
in main (created by CuriBase)
in div (created by CuriBase)
in CuriBase
As soon as we clear this up, I'll get on to the highlighting ;)
Hi Paul! Long time, no talk man.
I'm finally coming around to Curi again and I love all the progress you've made. I'm just re-familiarizing myself with the library again and running through the docs. I already have a question:
Is there a way to prevent the default blue border around the aria focused element when using the useNavigationFocus
hook? I would like to incorporate this feature for screen readers, but handle the focus styles myself. This could be obvious for anyone with experience with these dom features, but this is a first for me.
Thank you for the great work!
PS: you should totally steal some of the marketing copy from `navi' for Curi. You have all those features and more.
Version - @curi/router: 1.0.4
Disclaimer, I'm using SSR so I'm not sure if that's related.
I'm trying to use redirectTo
in my routes file by doing this
{
name: 'CreateAccount',
path: 'signup',
resolve: {
authorized: hasPlanSelected //this is a separate function returning a promise
},
response({ resolved }) {
if (resolved.authorized) {
return { body: CreateAccount };
}
return {
redirectTo: { name: 'Pricing' },
status: 302
};
}
},
It's working, but once I'm redirected to Pricing
, the CSS is not loaded although I'm importing it at the top of the file. I took a look at @hickory/browser
and found finalizeReplace
(line 65), and I see that there's a try/catch block using window.history.replaceState
first. Would this have anything to do with CSS not loading for a new page?
It's my hunch because when I manually use window.location.replace
as the redirect tool, the CSS is normal.
Has anyone done server-side rendering with Curi in Create React App? I'm getting a little lost. Content is showing but the styles and data from the router isn't showing. This is my code, pretty much copied from https://github.com/pshrmn/curi/blob/2dca9d5b41fd6924d6221dd334710646f1c11ea5/examples/misc/server-rendering/renderer.js.
import React from 'react';
import { renderToString } from 'react-dom/server';
import InMemory from '@hickory/in-memory';
import curi from '@curi/core';
import { CuriProvider } from '@curi/react';
import App from '../../src/containers/App';
import routes from '../../src/routes';
export default function(req, res) {
const history = InMemory({ locations: [req.url] });
const router = curi(history, routes);
router.respond(() => {
const markup = renderToString(
<CuriProvider router={ router }>
{({ response }) => {
const { body: Body, params } = response;
return (
<App>
<Body response={ response } />
</App>
);
}}
</CuriProvider>
);
res.send(renderFullPage(markup));
});
}
function renderFullPage(html) {
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root">${ html }</div>
<script type="text/javascript" src="/static/js/bundle.js"></script>]
</body>
</html>
`;
}
Any help would be appreciated. Thanks!
Related to #74
Scenario:
User logs in and is directed to the next page (page requires authentication)
Problem:
My routes file contains the following function
const protectRoute = (route) => {
if (!isLoggedIn()) {
return () => ({ redirectTo: { name: 'Login' } });
}
return () => ({ body: route });
};
which is placed on all routes where a user is not allowed unless authenticated. The issue is navigating programmatically. If I try to do router.navigate({ name: 'Dashboard' });
, I am greeted by this error:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
However, if I refresh the page everything loads fine and I am able to click links to other pages. As I've been debugging, I noticed that when Dashboard is called programmatically, routes.js
is never hit again. So I tried placing a debugger on my ReactDOM.hydrate
call and it results in this object being passed from the response:
Notice the redirectTo
object at the bottom. This means, according to the protectRoute
function above, isLoggedIn()
is false which returns the redirect. At this point, I'm expecting the routes to be hit in order to determine if the user is logged in (which is true in this case).
Any idea what this could be? Are the routes being "cached" in Curi?
First of all, great router, I really like how it works ๐
But It seems like there's no way to pass response data from server to client, which is a bit sad :-( May be we could improve this. I'm more than happy to send a PR after some discussion.
So what I'm doing right now:
resolve
fn for route.respond
I return that as data
.Everything is good.
But what happens when I render my app on server?
resolve
is called.resolve
resolves, data is being passed to respond
. respond
returns that data.So it would be cool to have some way of passing that response from server to client. Aka "initial response". Not sure how that should work with regard to things which actually need to be resolved on client separately like route components or other things which can't be serialized. May be I am missing something? Do you have any ideas on how that could be implemented?
Might seem obvious but after reading all the docs I can't find a way to change the route via Javascript.
Help appreciated :)
According the the migration guide:
With Curi, when a nested route matches, only that route renders.
How to tackle the case of a fixed navbar in a parent component with injected components under the navbar? With React Router, it's possible to handle this by using this.props.children
in the parent component because nested routes also render parent components.
Thanks for help, that library seems pretty cool, looking forward to using it!
React Hooks will require React v16.7. The @curi/react-*
packages currently have a minimum version of v16.3 (when the new context was introduced).
There are two possible paths to take while introducing hooks to the @curi/react-*
packages.
@curi/react-*
packages would need a major version bump.I prefer the second approach and have mostly implemented the changes that would be required in #132. I'm still slightly hesitant about converting Link
s to hooks because of the need to create new event handlers every render.
With hooks, the build sizes are multiple KBs smaller, although the difference shrinks to a few hundred bytes when minified & gzipped.
If there is a major version bump, some other changes can be implemented.
Link
s use the name
prop to specify which route they link to, instead of to
.// v1
<Link to="Package" params={{ package: "react-dom" }}>React DOM</Link>
// v2
<Link name="Package" params={{ package: "react-dom" }}>React DOM</Link>
Link
s are the only place that a route is specified by to
instead of name
and I would prefer to be consistent.
Link
passing on props to the anchor. I might prefer the syntax to use an anchorProps
object.// v1
<Link to="Home" className="home" target="_blank">Home</Link>
// v2
<Link name="Home" anchorProps={{ className: "home", target: "_blank"}}>Home</Link>
Shallow prop comparison can be used so that the object doesn't force a re-render. This approach would provide a more obvious split between the Link
's props and the anchor's props.
Hello,
I would like to request a few things for caching. First I would like to get information if route was push-ed or pop-ed while inside of cache. Why would I like to have that is so I can delete cache entries while navigating. Basically I do not want to show cached data if somebody clicks a link. But if he presses back or forward button it should load cached data.
Next thing is I would like a way to say refresh data in cache.
@pshrmn Happy to see me again? I'm your number one fan!
So, I'm getting a little jealous from the examples provided for redux and mobx, because I'm using apollo and - as you can tell - I'm a complete newb to all of this (only 6 months in a coding bootcamp).
I've done some 'research' and I believe it shouldn't be a problem to use Curi with Apollo, but are there any pointers you could give me to set it up?
<script>
import Router from '@curi/svelte/components/Router.svelte';
// ...
</script>
Error:
/home/kleinmaximus/Projects/KleinMaximus/razzle-svelte/node_modules/@curi/svelte/components/Router.svelte:1
<script>
^
SyntaxError: Unexpected token <
I think that the components need automatically compile before publishing (or during the installation of the package).
Then there will be no dependency on a particular developer's environment.
At least that's what Vue does.
In addition, the components can be imported via import { Router } from '@curi/svelte';
if include them to index file.
P.S.: Sorry for my English ;)
Hi @pshrmn! Just about to get started with Curi and really want to use the prefetch functionality with Apollo's inMemoryCache.
Here's what I'm trying to do (with reference to: apollographql/react-apollo#417 (comment)):
Might you have some guidance for using Curi's prefetch addon with Apollo's inMemoryCache? I'm particularly interested in 'lazy' prefetching/loading, i.e., only prefetch the part of the state needed to render the linked pages/component(s) - with an async data request - when a user navigates to a page/component with relative or child routes/components. I plan on using Apollo for everything (e.g., sans Redux).
Would you recommend using Curi's prefetch or something like react-preloaded for these use cases? I'm such a newb. I'm sorry if this is a dumb question.
curi/packages/svelte/rollup.config.js
Line 13 in bbcc5d8
I'm not sure if this is a mistake, but I think need chang from include: "src/**/*.html"
to include: "src/**/*.svelte"
.
I'm in a process of rewriting legacy blog to webcomponents with i18n support. So, I want to preserve old links. Inside "catch all" route I check whether lang is url and if not then I want to redirect to the same url but with default lang
Currently I can redirect only to known route name (inside respond
method of route):
I want to have possibility to redirect to url.
const routes = [
{
path: '(.*)',
respond() {
if (/* lang is not in url */) {
return {
redirect: { url: `/${defaultLocale}${location.pathname}${location.search}${location.hash}` }
}
}
// show 404
}
}
]
Just a thought, if you would agree it's a selling-point, couldn't Curi work with the 'microfrontend' paradigm?
When I define optional route parameter /articles/:id?
and visit /articles
page, router.current().response.params
equals { id: 'undefined' }
.
There should not be id
field at all or at least it should equal to regular undefined
value
For example in Step 03
import Browser from '@hickory/browser';
const history = Browser();
would be nice if:
// src/index.js
import Browser from '@hickory/browser';
const history = Browser();
Hello @pshrmn
There's an issue with the latest beta of curi/react or hickory/browser. Whenever I try to click on a link generated with the Link component, I'm getting this error:
modules.js?hash=c481496c4b80ad5dc349408f89dc06dd3b4bbb34:1550 Uncaught TypeError: curi.history.update is not a function
at Link._this.clickHandler (modules.js?hash=c481496c4b80ad5dc349408f89dc06dd3b4bbb34:1550)
at HTMLUnknownElement.callCallback (modules.js?hash=c481496c4b80ad5dc349408f89dc06dd3b4bbb34:7733)
at Object.invokeGuardedCallbackDev (modules.js?hash=c481496c4b80ad5dc349408f89dc06dd3b4bbb34:7772)
at Object.invokeGuardedCallback (modules.js?hash=c481496c4b80ad5dc349408f89dc06dd3b4bbb34:7629)
at Object.invokeGuardedCallbackAndCatchFirstError (modules.js?hash=c481496c4b80ad5dc349408f89dc06dd3b4bbb34:7643)
at executeDispatch (modules.js?hash=c481496c4b80ad5dc349408f89dc06dd3b4bbb34:7866)
at Object.executeDispatchesInOrder (modules.js?hash=c481496c4b80ad5dc349408f89dc06dd3b4bbb34:7888)
at executeDispatchesAndRelease (modules.js?hash=c481496c4b80ad5dc349408f89dc06dd3b4bbb34:8403)
at executeDispatchesAndReleaseTopLevel (modules.js?hash=c481496c4b80ad5dc349408f89dc06dd3b4bbb34:8414)
at Array.forEach (<anonymous>)
I've also tried to follow the new tutorial in a blank project and I'm getting the same errors.
I am just getting started with Svelte and Curi. I setup everything as per the guides, but while running the app, I am getting the following error on borwser.
I worked around it by adding a window.process = window.process || { env: {} };
in my routes.js, but it looked like a bug and thought I should report it.
I'd like to use @curi/static to generate the index.html for each pages
I am using rollup to generate the bundle so I added a plugin function that call staticFiles
But for that I need to import the routes, which in turn import the component.
Since these component are svelte files, roll up complain with
[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
src\pages\index.svelte (1:0)
1: <script>
^
...
Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
at error ...
Do you have an svelte example using @curi/static ?
I may be doing something wrong, but I'm on Step 08 of the tutorial and...
WARNING in ./src/components/AddToCart.js
105:15-22 "export 'curious' was not found in '@curi/react'
@ ./src/components/AddToCart.js
@ ./src/components/Book.js
@ ./src/routes.js
@ ./src/index.js
@ multi (webpack)-dev-server/client?http://localhost:8080 ./index.js
WARNING in ./src/components/Checkout.js
79:15-22 "export 'curious' was not found in '@curi/react'
@ ./src/components/Checkout.js
@ ./src/routes.js
@ ./src/index.js
@ multi (webpack)-dev-server/client?http://localhost:8080 ./index.js
Inside the routes files, I thought I could do redirectTo: { name: 'NotFound' }
but I get this error:
TypeError: Expected "0" to be a string
How do we force redirect to the 404 page if conditions aren't met for a specific route?
I haven't verified this but I suspect the technique you're using to make your aria-live announcer visually hidden (negative positioning) won't work for right-to-left languages.
See:
Hi @pshrmn ! I am just about ready to integrate Curi into my app and am working with a tutorial that uses react router with Animated
and ReactTransitionGroup
v2. There's some funky .css that the author uses to prevent the issue that you outlined in your tutorial in this sandbox and I was hoping to glean some insights from the example that now I can only find a dead link on Google's results to.
You might be wondering why I'm choosing animated
. It could help to clarify that I'd like to build my app in a manner that could be more easily ported to React Native. Hence, all the other inquiries (and lack of knowledge).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.